2 // Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
4 // Distributed under the Boost Software License, Version 1.0. (See accompanying
5 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7 // Official repository: https://github.com/boostorg/beast
10 #include <boost/beast/core/string.hpp>
11 #include <boost/beast/zlib/deflate_stream.hpp>
12 #include <boost/beast/test/throughput.hpp>
13 #include <boost/beast/_experimental/unit_test/dstream.hpp>
14 #include <boost/beast/_experimental/unit_test/suite.hpp>
19 #include "zlib-1.2.11/zlib.h"
25 class deflate_stream_test : public beast::unit_test::suite
28 // Lots of repeats, limited char range
31 corpus1(std::size_t n)
33 static std::string const alphabet{
34 "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
39 std::uniform_int_distribution<std::size_t> d0{
40 0, alphabet.size() - 1};
41 std::uniform_int_distribution<std::size_t> d1{
45 auto const rep = d1(g);
46 auto const ch = alphabet[d0(g)];
47 s.insert(s.end(), rep, ch);
56 corpus2(std::size_t n)
61 std::uniform_int_distribution<std::uint32_t> d0{0, 255};
63 s.push_back(static_cast<char>(d0(g)));
68 doDeflateBeast(string_view const& in)
73 Z_DEFAULT_COMPRESSION,
78 out.resize(deflate_upper_bound(in.size()));
79 zs.next_in = in.data();
80 zs.avail_in = in.size();
81 zs.next_out = &out[0];
82 zs.avail_out = out.size();
84 ds.write(zs, Flush::full, ec);
85 BEAST_EXPECTS(! ec, ec.message());
86 out.resize(zs.total_out);
91 doDeflateZLib(string_view const& in)
95 memset(&zs, 0, sizeof(zs));
96 result = deflateInit2(
98 Z_DEFAULT_COMPRESSION,
105 throw std::logic_error("deflateInit2 failed");
107 out.resize(deflateBound(&zs,
108 static_cast<uLong>(in.size())));
109 zs.next_in = (Bytef*)in.data();
110 zs.avail_in = static_cast<uInt>(in.size());
111 zs.next_out = (Bytef*)&out[0];
112 zs.avail_out = static_cast<uInt>(out.size());
113 result = deflate(&zs, Z_FULL_FLUSH);
115 throw std::logic_error("deflate failed");
116 out.resize(zs.total_out);
126 std::size_t constexpr trials = 3;
127 auto const c1 = corpus1(size);
128 auto const c2 = corpus2(size);
130 std::left << std::setw(10) << (std::to_string(size) + "B") <<
131 std::right << std::setw(12) << "Beast" << " " <<
132 std::right << std::setw(12) << "ZLib" <<
134 for(std::size_t i = 0; i < trials; ++i)
137 log << std::left << std::setw(10) << "corpus1";
139 for(std::size_t j = 0; j < repeat; ++j)
140 out1 = doDeflateBeast(c1);
142 test::throughput(t.elapsed(), size * repeat);
143 log << std::right << std::setw(12) << t1 << " B/s ";
145 for(std::size_t j = 0; j < repeat; ++j)
146 out2 = doDeflateZLib(c1);
147 BEAST_EXPECT(out1 == out2);
149 test::throughput(t.elapsed(), size * repeat);
150 log << std::right << std::setw(12) << t2 << " B/s";
151 log << std::right << std::setw(12) <<
152 unsigned(double(t1)*100/t2-100) << "%";
155 for(std::size_t i = 0; i < trials; ++i)
158 log << std::left << std::setw(10) << "corpus2";
160 for(std::size_t j = 0; j < repeat; ++j)
161 out1 = doDeflateBeast(c2);
163 test::throughput(t.elapsed(), size * repeat);
164 log << std::right << std::setw(12) << t1 << " B/s ";
166 for(std::size_t j = 0; j < repeat; ++j)
167 out2 = doDeflateZLib(c2);
168 BEAST_EXPECT(out1 == out2);
170 test::throughput(t.elapsed(), size * repeat);
171 log << std::right << std::setw(12) << t2 << " B/s";
172 log << std::right << std::setw(12) <<
173 unsigned(double(t1)*100/t2-100) << "%";
182 doCorpus( 16 * 1024, 512);
183 doCorpus( 1024 * 1024, 8);
184 doCorpus(8 * 1024 * 1024, 1);
195 BEAST_DEFINE_TESTSUITE(beast,zlib,deflate_stream);