diff options
Diffstat (limited to 'src/boost/libs/beast/test/bench/zlib')
-rw-r--r-- | src/boost/libs/beast/test/bench/zlib/CMakeLists.txt | 31 | ||||
-rw-r--r-- | src/boost/libs/beast/test/bench/zlib/Jamfile | 15 | ||||
-rw-r--r-- | src/boost/libs/beast/test/bench/zlib/deflate_stream.cpp | 199 | ||||
-rw-r--r-- | src/boost/libs/beast/test/bench/zlib/inflate_stream.cpp | 244 |
4 files changed, 489 insertions, 0 deletions
diff --git a/src/boost/libs/beast/test/bench/zlib/CMakeLists.txt b/src/boost/libs/beast/test/bench/zlib/CMakeLists.txt new file mode 100644 index 00000000..a030ed93 --- /dev/null +++ b/src/boost/libs/beast/test/bench/zlib/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (c) 2016-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) +# +# Official repository: https://github.com/boostorg/beast +# + +GroupSources (include/boost/beast beast) +GroupSources (test/extern/zlib-1.2.11 zlib) +GroupSources (test/bench/zlib "/") + +if (MSVC) + set_source_files_properties (${ZLIB_SOURCES} PROPERTIES COMPILE_FLAGS "/wd4127 /wd4131 /wd4244") +endif() + +add_executable (bench-zlib + ${BOOST_BEAST_FILES} + ${ZLIB_SOURCES} + Jamfile + deflate_stream.cpp + inflate_stream.cpp +) +target_link_libraries(bench-zlib + lib-asio + lib-beast + lib-test + ) + +set_property(TARGET bench-zlib PROPERTY FOLDER "tests-bench") diff --git a/src/boost/libs/beast/test/bench/zlib/Jamfile b/src/boost/libs/beast/test/bench/zlib/Jamfile new file mode 100644 index 00000000..6e210c29 --- /dev/null +++ b/src/boost/libs/beast/test/bench/zlib/Jamfile @@ -0,0 +1,15 @@ +# +# Copyright (c) 2016-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) +# +# Official repository: https://github.com/boostorg/beast +# + +exe bench-zlib : + $(ZLIB_SOURCES) + deflate_stream.cpp + inflate_stream.cpp + /boost/beast/test//lib-test + ; diff --git a/src/boost/libs/beast/test/bench/zlib/deflate_stream.cpp b/src/boost/libs/beast/test/bench/zlib/deflate_stream.cpp new file mode 100644 index 00000000..321fa98c --- /dev/null +++ b/src/boost/libs/beast/test/bench/zlib/deflate_stream.cpp @@ -0,0 +1,199 @@ +// +// Copyright (c) 2016-2019 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) +// +// Official repository: https://github.com/boostorg/beast +// + +#include <boost/beast/core/string.hpp> +#include <boost/beast/zlib/deflate_stream.hpp> +#include <boost/beast/test/throughput.hpp> +#include <boost/beast/_experimental/unit_test/dstream.hpp> +#include <boost/beast/_experimental/unit_test/suite.hpp> +#include <iomanip> +#include <random> +#include <string> + +#include "zlib-1.2.11/zlib.h" + +namespace boost { +namespace beast { +namespace zlib { + +class deflate_stream_test : public beast::unit_test::suite +{ +public: + // Lots of repeats, limited char range + static + std::string + corpus1(std::size_t n) + { + static std::string const alphabet{ + "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" + }; + std::string s; + s.reserve(n + 5); + std::mt19937 g; + std::uniform_int_distribution<std::size_t> d0{ + 0, alphabet.size() - 1}; + std::uniform_int_distribution<std::size_t> d1{ + 1, 5}; + while(s.size() < n) + { + auto const rep = d1(g); + auto const ch = alphabet[d0(g)]; + s.insert(s.end(), rep, ch); + } + s.resize(n); + return s; + } + + // Random data + static + std::string + corpus2(std::size_t n) + { + std::string s; + s.reserve(n); + std::mt19937 g; + std::uniform_int_distribution<std::uint32_t> d0{0, 255}; + while(n--) + s.push_back(static_cast<char>(d0(g))); + return s; + } + + std::string + doDeflateBeast(string_view const& in) + { + z_params zs; + deflate_stream ds; + ds.reset( + Z_DEFAULT_COMPRESSION, + 15, + 4, + Strategy::normal); + std::string out; + out.resize(deflate_upper_bound(in.size())); + zs.next_in = in.data(); + zs.avail_in = in.size(); + zs.next_out = &out[0]; + zs.avail_out = out.size(); + error_code ec; + ds.write(zs, Flush::full, ec); + BEAST_EXPECTS(! ec, ec.message()); + out.resize(zs.total_out); + return out; + } + + std::string + doDeflateZLib(string_view const& in) + { + int result; + z_stream zs; + memset(&zs, 0, sizeof(zs)); + result = deflateInit2( + &zs, + Z_DEFAULT_COMPRESSION, + Z_DEFLATED, + -15, + 4, + Z_DEFAULT_STRATEGY + ); + if(result != Z_OK) + throw std::logic_error("deflateInit2 failed"); + std::string out; + out.resize(deflateBound(&zs, + static_cast<uLong>(in.size()))); + zs.next_in = (Bytef*)in.data(); + zs.avail_in = static_cast<uInt>(in.size()); + zs.next_out = (Bytef*)&out[0]; + zs.avail_out = static_cast<uInt>(out.size()); + result = deflate(&zs, Z_FULL_FLUSH); + if(result != Z_OK) + throw std::logic_error("deflate failed"); + out.resize(zs.total_out); + deflateEnd(&zs); + return out; + } + + void + doCorpus( + std::size_t size, + std::size_t repeat) + { + std::size_t constexpr trials = 3; + auto const c1 = corpus1(size); + auto const c2 = corpus2(size); + log << + std::left << std::setw(10) << (std::to_string(size) + "B") << + std::right << std::setw(12) << "Beast" << " " << + std::right << std::setw(12) << "ZLib" << + std::endl; + for(std::size_t i = 0; i < trials; ++i) + { + test::timer t; + log << std::left << std::setw(10) << "corpus1"; + std::string out1; + for(std::size_t j = 0; j < repeat; ++j) + out1 = doDeflateBeast(c1); + auto const t1 = + test::throughput(t.elapsed(), size * repeat); + log << std::right << std::setw(12) << t1 << " B/s "; + std::string out2; + for(std::size_t j = 0; j < repeat; ++j) + out2 = doDeflateZLib(c1); + BEAST_EXPECT(out1 == out2); + auto const t2 = + test::throughput(t.elapsed(), size * repeat); + log << std::right << std::setw(12) << t2 << " B/s"; + log << std::right << std::setw(12) << + unsigned(double(t1)*100/t2-100) << "%"; + log << std::endl; + } + for(std::size_t i = 0; i < trials; ++i) + { + test::timer t; + log << std::left << std::setw(10) << "corpus2"; + std::string out1; + for(std::size_t j = 0; j < repeat; ++j) + out1 = doDeflateBeast(c2); + auto const t1 = + test::throughput(t.elapsed(), size * repeat); + log << std::right << std::setw(12) << t1 << " B/s "; + std::string out2; + for(std::size_t j = 0; j < repeat; ++j) + out2 = doDeflateZLib(c2); + BEAST_EXPECT(out1 == out2); + auto const t2 = + test::throughput(t.elapsed(), size * repeat); + log << std::right << std::setw(12) << t2 << " B/s"; + log << std::right << std::setw(12) << + unsigned(double(t1)*100/t2-100) << "%"; + log << std::endl; + } + log << std::endl; + } + + void + doBench() + { + doCorpus( 16 * 1024, 512); + doCorpus( 1024 * 1024, 8); + doCorpus(8 * 1024 * 1024, 1); + } + + void + run() override + { + doBench(); + pass(); + } +}; + +BEAST_DEFINE_TESTSUITE(beast,zlib,deflate_stream); + +} // zlib +} // beast +} // boost diff --git a/src/boost/libs/beast/test/bench/zlib/inflate_stream.cpp b/src/boost/libs/beast/test/bench/zlib/inflate_stream.cpp new file mode 100644 index 00000000..ea8d6d98 --- /dev/null +++ b/src/boost/libs/beast/test/bench/zlib/inflate_stream.cpp @@ -0,0 +1,244 @@ +// +// Copyright (c) 2016-2019 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) +// +// Official repository: https://github.com/boostorg/beast +// + +#include <boost/beast/core/string.hpp> +#include <boost/beast/zlib/inflate_stream.hpp> +#include <boost/beast/test/throughput.hpp> +#include <boost/beast/_experimental/unit_test/dstream.hpp> +#include <boost/beast/_experimental/unit_test/suite.hpp> +#include <iomanip> +#include <random> +#include <string> + +#include "zlib-1.2.11/zlib.h" + +namespace boost { +namespace beast { +namespace zlib { + +class inflate_stream_test : public beast::unit_test::suite +{ +public: + // Lots of repeats, limited char range + static + std::string + corpus1(std::size_t n) + { + static std::string const alphabet{ + "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" + }; + std::string s; + s.reserve(n + 5); + std::mt19937 g; + std::uniform_int_distribution<std::size_t> d0{ + 0, alphabet.size() - 1}; + std::uniform_int_distribution<std::size_t> d1{ + 1, 5}; + while(s.size() < n) + { + auto const rep = d1(g); + auto const ch = alphabet[d0(g)]; + s.insert(s.end(), rep, ch); + } + s.resize(n); + return s; + } + + // Random data + static + std::string + corpus2(std::size_t n) + { + std::string s; + s.reserve(n); + std::mt19937 g; + std::uniform_int_distribution<std::uint32_t> d0{0, 255}; + while(n--) + s.push_back(static_cast<char>(d0(g))); + return s; + } + + static + std::string + compress(string_view const& in) + { + int result; + z_stream zs; + memset(&zs, 0, sizeof(zs)); + result = deflateInit2( + &zs, + Z_DEFAULT_COMPRESSION, + Z_DEFLATED, + -15, + 4, + Z_DEFAULT_STRATEGY); + if(result != Z_OK) + throw std::logic_error("deflateInit2 failed"); + zs.next_in = (Bytef*)in.data(); + zs.avail_in = static_cast<uInt>(in.size()); + std::string out; + out.resize(deflateBound(&zs, + static_cast<uLong>(in.size()))); + zs.next_in = (Bytef*)in.data(); + zs.avail_in = static_cast<uInt>(in.size()); + zs.next_out = (Bytef*)&out[0]; + zs.avail_out = static_cast<uInt>(out.size()); + result = deflate(&zs, Z_FULL_FLUSH); + if(result != Z_OK) + throw std::logic_error("deflate failed"); + out.resize(zs.total_out); + deflateEnd(&zs); + return out; + } + + std::string + doInflateBeast(string_view const& in) + { + z_params zs; + std::string out; + inflate_stream is; + zs.next_in = &in[0]; + zs.avail_in = in.size(); + out.resize(in.size()); + zs.next_out = &out[0]; + zs.avail_out = out.size(); + for(;;) + { + error_code ec; + is.write(zs, Flush::sync, ec); + if(ec) + throw std::logic_error("inflate_stream failed"); + if(zs.avail_out > 0) + break; + out.resize(2 * zs.total_out); + zs.next_out = &out[zs.total_out]; + zs.avail_out = out.size() - zs.total_out; + } + out.resize(zs.total_out); + return out; + } + + std::string + doInflateZLib(string_view const& in) + { + int result; + z_stream zs; + std::string out; + memset(&zs, 0, sizeof(zs)); + result = inflateInit2(&zs, -15); + zs.next_in = (Bytef*)in.data(); + zs.avail_in = static_cast<uInt>(in.size()); + out.resize(in.size()); + zs.next_out = (Bytef*)&out[0]; + zs.avail_out = static_cast<uInt>(out.size()); + for(;;) + { + result = inflate(&zs, Z_SYNC_FLUSH); + if( result == Z_NEED_DICT || + result == Z_DATA_ERROR || + result == Z_MEM_ERROR) + { + throw std::logic_error("inflate failed"); + } + if(zs.avail_out > 0) + break; + if(result == Z_STREAM_END) + break; + out.resize(2 * zs.total_out); + zs.next_out = (Bytef*)&out[zs.total_out]; + zs.avail_out = static_cast<uInt>( + out.size() - zs.total_out); + } + out.resize(zs.total_out); + inflateEnd(&zs); + return out; + } + + void + doCorpus( + std::size_t size, + std::size_t repeat) + { + std::size_t constexpr trials = 3; + std::uint64_t constexpr scale = 16; + auto const c1 = corpus1(size); + auto const c2 = corpus2(size * scale); + auto const in1 = compress(c1); + auto const in2 = compress(c2); + log << + std::left << std::setw(10) << (std::to_string(size) + "B") << + std::right << std::setw(12) << "Beast" << " " << + std::right << std::setw(12) << "ZLib" << + std::endl; + for(std::size_t i = 0; i < trials; ++i) + { + test::timer t; + log << std::left << std::setw(10) << "corpus1"; + std::string out; + for(std::size_t j = 0; j < repeat; ++j) + out = doInflateBeast(in1); + BEAST_EXPECT(out == c1); + auto const t1 = + test::throughput(t.elapsed(), size * repeat); + log << std::right << std::setw(12) << t1 << " B/s "; + for(std::size_t j = 0; j < repeat; ++j) + out = doInflateZLib(in1); + BEAST_EXPECT(out == c1); + auto const t2 = + test::throughput(t.elapsed(), size * repeat); + log << std::right << std::setw(12) << t2 << " B/s"; + log << std::right << std::setw(12) << + unsigned(double(t1)*100/t2-100) << "%"; + log << std::endl; + } + for(std::size_t i = 0; i < trials; ++i) + { + test::timer t; + log << std::left << std::setw(10) << "corpus2"; + std::string out; + for(std::size_t j = 0; j < repeat; ++j) + out = doInflateBeast(in2); + BEAST_EXPECT(out == c2); + auto const t1 = + test::throughput(t.elapsed(), size * scale * repeat); + log << std::right << std::setw(12) << t1 << " B/s "; + for(std::size_t j = 0; j < repeat; ++j) + out = doInflateZLib(in2); + BEAST_EXPECT(out == c2); + auto const t2 = + test::throughput(t.elapsed(), size * scale * repeat); + log << std::right << std::setw(12) << t2 << " B/s"; + log << std::right << std::setw(12) << + unsigned(double(t1)*100/t2-100) << "%"; + log << std::endl; + } + log << std::endl; + } + + void + doBench() + { + doCorpus( 1 * 1024 * 1024, 64); + doCorpus( 4 * 1024 * 1024, 16); + doCorpus( 16 * 1024 * 1024, 8); + } + + void + run() override + { + doBench(); + pass(); + } +}; + +BEAST_DEFINE_TESTSUITE(beast,zlib,inflate_stream); + +} // zlib +} // beast +} // boost |