mirror of
https://github.com/boostorg/beast.git
synced 2025-07-31 13:27:33 +02:00
@@ -5,6 +5,7 @@ Version 51
|
|||||||
* Fix file_body::get() not setting the more flag correctly
|
* Fix file_body::get() not setting the more flag correctly
|
||||||
* Use BOOST_FALLTHROUGH
|
* Use BOOST_FALLTHROUGH
|
||||||
* Use BOOST_STRINGIZE
|
* Use BOOST_STRINGIZE
|
||||||
|
* DynamicBuffer benchmarks
|
||||||
|
|
||||||
API Changes:
|
API Changes:
|
||||||
|
|
||||||
|
@@ -111,28 +111,16 @@ endfunction()
|
|||||||
|
|
||||||
if ("${VARIANT}" STREQUAL "coverage")
|
if ("${VARIANT}" STREQUAL "coverage")
|
||||||
set(CMAKE_CXX_FLAGS
|
set(CMAKE_CXX_FLAGS
|
||||||
"${CMAKE_CXX_FLAGS} -fprofile-arcs -ftest-coverage")
|
"${CMAKE_CXX_FLAGS} -DBEAST_NO_BUFFER_BENCH=1 -fprofile-arcs -ftest-coverage")
|
||||||
set (CMAKE_BUILD_TYPE RELWITHDEBINFO)
|
set (CMAKE_BUILD_TYPE RELWITHDEBINFO)
|
||||||
set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -lgcov")
|
set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -lgcov")
|
||||||
|
|
||||||
elseif ("${VARIANT}" STREQUAL "ubasan")
|
elseif ("${VARIANT}" STREQUAL "ubasan")
|
||||||
set(CMAKE_CXX_FLAGS
|
set(CMAKE_CXX_FLAGS
|
||||||
"${CMAKE_CXX_FLAGS} -funsigned-char -fno-omit-frame-pointer -fsanitize=address,undefined -fsanitize-blacklist=${PROJECT_SOURCE_DIR}/scripts/blacklist.supp")
|
"${CMAKE_CXX_FLAGS} -DBEAST_NO_BUFFER_BENCH=1 -funsigned-char -fno-omit-frame-pointer -fsanitize=address,undefined -fsanitize-blacklist=${PROJECT_SOURCE_DIR}/scripts/blacklist.supp")
|
||||||
set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=address,undefined")
|
set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=address,undefined")
|
||||||
set(CMAKE_BUILD_TYPE RELWITHDEBINFO)
|
set(CMAKE_BUILD_TYPE RELWITHDEBINFO)
|
||||||
|
|
||||||
elseif ("${VARIANT}" STREQUAL "asan")
|
|
||||||
set(CMAKE_CXX_FLAGS
|
|
||||||
"${CMAKE_CXX_FLAGS} -funsigned-char -fsanitize=address -fno-omit-frame-pointer")
|
|
||||||
set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=address")
|
|
||||||
set(CMAKE_BUILD_TYPE RELWITHDEBINFO)
|
|
||||||
|
|
||||||
elseif ("${VARIANT}" STREQUAL "usan")
|
|
||||||
set(CMAKE_CXX_FLAGS
|
|
||||||
"${CMAKE_CXX_FLAGS} -fsanitize=undefined -fsanitize-blacklist=${PROJECT_SOURCE_DIR}/scripts/blacklist.supp -fno-omit-frame-pointer")
|
|
||||||
set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=undefined")
|
|
||||||
set(CMAKE_BUILD_TYPE RELWITHDEBINFO)
|
|
||||||
|
|
||||||
elseif ("${VARIANT}" STREQUAL "debug")
|
elseif ("${VARIANT}" STREQUAL "debug")
|
||||||
set(CMAKE_BUILD_TYPE DEBUG)
|
set(CMAKE_BUILD_TYPE DEBUG)
|
||||||
|
|
||||||
|
30
Jamroot
30
Jamroot
@@ -54,9 +54,9 @@ if [ os.name ] = MACOSX
|
|||||||
|
|
||||||
variant coverage
|
variant coverage
|
||||||
:
|
:
|
||||||
debug
|
release
|
||||||
:
|
:
|
||||||
<cxxflags>"-fprofile-arcs -ftest-coverage"
|
<cxxflags>"-DBEAST_NO_BUFFER_BENCH=1 -fprofile-arcs -ftest-coverage"
|
||||||
<linkflags>"-lgcov"
|
<linkflags>"-lgcov"
|
||||||
;
|
;
|
||||||
|
|
||||||
@@ -64,34 +64,10 @@ variant ubasan
|
|||||||
:
|
:
|
||||||
release
|
release
|
||||||
:
|
:
|
||||||
<cxxflags>"-funsigned-char -fno-omit-frame-pointer -fsanitize=address,undefined -fsanitize-blacklist=scripts/blacklist.supp"
|
<cxxflags>"-DBEAST_NO_BUFFER_BENCH=1 -funsigned-char -fno-omit-frame-pointer -fsanitize=address,undefined -fsanitize-blacklist=scripts/blacklist.supp"
|
||||||
<linkflags>"-fsanitize=address,undefined"
|
<linkflags>"-fsanitize=address,undefined"
|
||||||
;
|
;
|
||||||
|
|
||||||
variant asan
|
|
||||||
:
|
|
||||||
release
|
|
||||||
:
|
|
||||||
<cxxflags>"-funsigned-char -fsanitize=address -fno-omit-frame-pointer"
|
|
||||||
<linkflags>"-fsanitize=address"
|
|
||||||
;
|
|
||||||
|
|
||||||
variant msan
|
|
||||||
:
|
|
||||||
debug
|
|
||||||
:
|
|
||||||
<cxxflags>"-fsanitize=memory -fsanitize-memory-track-origins=2 -fsanitize-memory-use-after-dtor -fno-omit-frame-pointer"
|
|
||||||
<linkflags>"-fsanitize=memory"
|
|
||||||
;
|
|
||||||
|
|
||||||
variant usan
|
|
||||||
:
|
|
||||||
debug
|
|
||||||
:
|
|
||||||
<cxxflags>"-fsanitize=undefined -fsanitize-blacklist=scripts/blacklist.supp -fno-omit-frame-pointer"
|
|
||||||
<linkflags>"-fsanitize=undefined"
|
|
||||||
;
|
|
||||||
|
|
||||||
project beast
|
project beast
|
||||||
: requirements
|
: requirements
|
||||||
<include>.
|
<include>.
|
||||||
|
@@ -18,6 +18,7 @@ unit-test core-tests :
|
|||||||
../extras/beast/unit_test/main.cpp
|
../extras/beast/unit_test/main.cpp
|
||||||
core/async_result.cpp
|
core/async_result.cpp
|
||||||
core/bind_handler.cpp
|
core/bind_handler.cpp
|
||||||
|
core/buffer_bench.cpp
|
||||||
core/buffer_cat.cpp
|
core/buffer_cat.cpp
|
||||||
core/buffer_prefix.cpp
|
core/buffer_prefix.cpp
|
||||||
core/buffered_read_stream.cpp
|
core/buffered_read_stream.cpp
|
||||||
|
@@ -10,6 +10,7 @@ add_executable (core-tests
|
|||||||
../../extras/beast/unit_test/main.cpp
|
../../extras/beast/unit_test/main.cpp
|
||||||
async_result.cpp
|
async_result.cpp
|
||||||
bind_handler.cpp
|
bind_handler.cpp
|
||||||
|
buffer_bench.cpp
|
||||||
buffer_cat.cpp
|
buffer_cat.cpp
|
||||||
buffer_prefix.cpp
|
buffer_prefix.cpp
|
||||||
buffer_test.hpp
|
buffer_test.hpp
|
||||||
|
241
test/core/buffer_bench.cpp
Normal file
241
test/core/buffer_bench.cpp
Normal file
@@ -0,0 +1,241 @@
|
|||||||
|
//
|
||||||
|
// Copyright (c) 2013-2017 Vinnie Falco (vinnie dot falco at gmail dot com)
|
||||||
|
//
|
||||||
|
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||||
|
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <beast/core/flat_buffer.hpp>
|
||||||
|
#include <beast/core/multi_buffer.hpp>
|
||||||
|
#include <beast/core/string_view.hpp>
|
||||||
|
#include <beast/core/detail/read_size_helper.hpp>
|
||||||
|
#include <beast/unit_test/suite.hpp>
|
||||||
|
#include <boost/asio/streambuf.hpp>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <chrono>
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <iomanip>
|
||||||
|
#include <utility>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace beast {
|
||||||
|
|
||||||
|
class buffer_bench_test : public beast::unit_test::suite
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using size_type = std::uint64_t;
|
||||||
|
|
||||||
|
class timer
|
||||||
|
{
|
||||||
|
using clock_type =
|
||||||
|
std::chrono::system_clock;
|
||||||
|
|
||||||
|
clock_type::time_point when_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
using duration =
|
||||||
|
clock_type::duration;
|
||||||
|
|
||||||
|
timer()
|
||||||
|
: when_(clock_type::now())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
duration
|
||||||
|
elapsed() const
|
||||||
|
{
|
||||||
|
return clock_type::now() - when_;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
inline
|
||||||
|
size_type
|
||||||
|
throughput(std::chrono::duration<
|
||||||
|
double> const& elapsed, std::size_t items)
|
||||||
|
{
|
||||||
|
using namespace std::chrono;
|
||||||
|
return static_cast<size_type>(
|
||||||
|
1 / (elapsed/items).count());
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class MutableBufferSequence>
|
||||||
|
static
|
||||||
|
std::size_t
|
||||||
|
fill(MutableBufferSequence const& buffers)
|
||||||
|
{
|
||||||
|
std::size_t n = 0;
|
||||||
|
using boost::asio::buffer_cast;
|
||||||
|
using boost::asio::buffer_size;
|
||||||
|
for(auto const& buffer : buffers)
|
||||||
|
{
|
||||||
|
std::fill(
|
||||||
|
buffer_cast<char*>(buffer),
|
||||||
|
buffer_cast<char*>(buffer) +
|
||||||
|
buffer_size(buffer), 0);
|
||||||
|
n += buffer_size(buffer);
|
||||||
|
}
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class DynamicBuffer>
|
||||||
|
size_type
|
||||||
|
do_prepares(std::size_t repeat,
|
||||||
|
std::size_t count, std::size_t size)
|
||||||
|
{
|
||||||
|
timer t;
|
||||||
|
size_type total = 0;
|
||||||
|
for(auto i = repeat; i--;)
|
||||||
|
{
|
||||||
|
DynamicBuffer b;
|
||||||
|
for(auto j = count; j--;)
|
||||||
|
{
|
||||||
|
auto const n = fill(b.prepare(size));
|
||||||
|
b.commit(n);
|
||||||
|
total += n;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return throughput(t.elapsed(), total);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class DynamicBuffer>
|
||||||
|
size_type
|
||||||
|
do_hints(std::size_t repeat,
|
||||||
|
std::size_t count, std::size_t size)
|
||||||
|
{
|
||||||
|
timer t;
|
||||||
|
size_type total = 0;
|
||||||
|
for(auto i = repeat; i--;)
|
||||||
|
{
|
||||||
|
DynamicBuffer b;
|
||||||
|
for(auto j = count; j--;)
|
||||||
|
{
|
||||||
|
for(auto remain = size; remain;)
|
||||||
|
{
|
||||||
|
using beast::detail::read_size_helper;
|
||||||
|
auto const n = fill(b.prepare(
|
||||||
|
read_size_helper(b, remain)));
|
||||||
|
b.commit(n);
|
||||||
|
remain -= n;
|
||||||
|
total += n;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return throughput(t.elapsed(), total);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class DynamicBuffer>
|
||||||
|
size_type
|
||||||
|
do_random(std::size_t repeat,
|
||||||
|
std::size_t count, std::size_t size)
|
||||||
|
{
|
||||||
|
timer t;
|
||||||
|
size_type total = 0;
|
||||||
|
for(auto i = repeat; i--;)
|
||||||
|
{
|
||||||
|
DynamicBuffer b;
|
||||||
|
for(auto j = count; j--;)
|
||||||
|
{
|
||||||
|
auto const n = fill(b.prepare(
|
||||||
|
1 + (rand()%(2*size))));
|
||||||
|
b.commit(n);
|
||||||
|
total += n;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return throughput(t.elapsed(), total);
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
inline
|
||||||
|
void
|
||||||
|
do_trials_1(bool)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class F0, class... FN>
|
||||||
|
void
|
||||||
|
do_trials_1(bool print, F0&& f, FN... fn)
|
||||||
|
{
|
||||||
|
timer t;
|
||||||
|
using namespace std::chrono;
|
||||||
|
static size_type constexpr den = 1024 * 1024;
|
||||||
|
if(print)
|
||||||
|
{
|
||||||
|
log << std::right << std::setw(10) <<
|
||||||
|
((f() + (den / 2)) / den) << " MB/s";
|
||||||
|
log.flush();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
f();
|
||||||
|
}
|
||||||
|
do_trials_1(print, fn...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class F0, class... FN>
|
||||||
|
void
|
||||||
|
do_trials(string_view name,
|
||||||
|
std::size_t trials, F0&& f0, FN... fn)
|
||||||
|
{
|
||||||
|
using namespace std::chrono;
|
||||||
|
// warm-up
|
||||||
|
do_trials_1(false, f0, fn...);
|
||||||
|
do_trials_1(false, f0, fn...);
|
||||||
|
while(trials--)
|
||||||
|
{
|
||||||
|
timer t;
|
||||||
|
log << std::left << std::setw(24) << name << ":";
|
||||||
|
log.flush();
|
||||||
|
do_trials_1(true, f0, fn...);
|
||||||
|
log << " " <<
|
||||||
|
duration_cast<milliseconds>(t.elapsed()).count() << "ms";
|
||||||
|
log << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
run() override
|
||||||
|
{
|
||||||
|
static std::size_t constexpr trials = 1;
|
||||||
|
static std::size_t constexpr repeat = 250;
|
||||||
|
std::vector<std::pair<std::size_t, std::size_t>> params;
|
||||||
|
params.emplace_back(1024, 1024);
|
||||||
|
params.emplace_back(512, 4096);
|
||||||
|
params.emplace_back(256, 32768);
|
||||||
|
log << std::endl;
|
||||||
|
for(auto const& param : params)
|
||||||
|
{
|
||||||
|
auto const count = param.first;
|
||||||
|
auto const size = param.second;
|
||||||
|
auto const s = std::string("count=") + std::to_string(count) +
|
||||||
|
", size=" + std::to_string(size);
|
||||||
|
log << std::left << std::setw(24) << s << " " <<
|
||||||
|
std::right << std::setw(15) << "prepare" <<
|
||||||
|
std::right << std::setw(15) << "with hint" <<
|
||||||
|
std::right << std::setw(15) << "random" <<
|
||||||
|
std::endl;
|
||||||
|
do_trials("multi_buffer", trials,
|
||||||
|
[&](){ return do_prepares<multi_buffer>(repeat, count, size); }
|
||||||
|
,[&](){ return do_hints <multi_buffer>(repeat, count, size); }
|
||||||
|
,[&](){ return do_random <multi_buffer>(repeat, count, size); }
|
||||||
|
);
|
||||||
|
do_trials("flat_buffer", trials,
|
||||||
|
[&](){ return do_prepares<flat_buffer>(repeat, count, size); }
|
||||||
|
,[&](){ return do_hints <flat_buffer>(repeat, count, size); }
|
||||||
|
,[&](){ return do_random <flat_buffer>(repeat, count, size); }
|
||||||
|
);
|
||||||
|
do_trials("boost::asio::streambuf", trials,
|
||||||
|
[&](){ return do_prepares<boost::asio::streambuf>(repeat, count, size); }
|
||||||
|
,[&](){ return do_hints <boost::asio::streambuf>(repeat, count, size); }
|
||||||
|
,[&](){ return do_random <boost::asio::streambuf>(repeat, count, size); }
|
||||||
|
);
|
||||||
|
log << std::endl;
|
||||||
|
}
|
||||||
|
pass();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#if defined(NDEBUG) && ! BEAST_NO_BUFFER_BENCH
|
||||||
|
BEAST_DEFINE_TESTSUITE(buffer_bench,core,beast);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
} // beast
|
Reference in New Issue
Block a user