]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/beast/test/bench/zlib/inflate_stream.cpp
import new upstream nautilus stable release 14.2.8
[ceph.git] / ceph / src / boost / libs / beast / test / bench / zlib / inflate_stream.cpp
1 //
2 // Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
3 //
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)
6 //
7 // Official repository: https://github.com/boostorg/beast
8 //
9
10 #include <boost/beast/core/string.hpp>
11 #include <boost/beast/zlib/inflate_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>
15 #include <iomanip>
16 #include <random>
17 #include <string>
18
19 #include "zlib-1.2.11/zlib.h"
20
21 namespace boost {
22 namespace beast {
23 namespace zlib {
24
25 class inflate_stream_test : public beast::unit_test::suite
26 {
27 public:
28 // Lots of repeats, limited char range
29 static
30 std::string
31 corpus1(std::size_t n)
32 {
33 static std::string const alphabet{
34 "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
35 };
36 std::string s;
37 s.reserve(n + 5);
38 std::mt19937 g;
39 std::uniform_int_distribution<std::size_t> d0{
40 0, alphabet.size() - 1};
41 std::uniform_int_distribution<std::size_t> d1{
42 1, 5};
43 while(s.size() < n)
44 {
45 auto const rep = d1(g);
46 auto const ch = alphabet[d0(g)];
47 s.insert(s.end(), rep, ch);
48 }
49 s.resize(n);
50 return s;
51 }
52
53 // Random data
54 static
55 std::string
56 corpus2(std::size_t n)
57 {
58 std::string s;
59 s.reserve(n);
60 std::mt19937 g;
61 std::uniform_int_distribution<std::uint32_t> d0{0, 255};
62 while(n--)
63 s.push_back(static_cast<char>(d0(g)));
64 return s;
65 }
66
67 static
68 std::string
69 compress(string_view const& in)
70 {
71 int result;
72 z_stream zs;
73 memset(&zs, 0, sizeof(zs));
74 result = deflateInit2(
75 &zs,
76 Z_DEFAULT_COMPRESSION,
77 Z_DEFLATED,
78 -15,
79 4,
80 Z_DEFAULT_STRATEGY);
81 if(result != Z_OK)
82 throw std::logic_error("deflateInit2 failed");
83 zs.next_in = (Bytef*)in.data();
84 zs.avail_in = static_cast<uInt>(in.size());
85 std::string out;
86 out.resize(deflateBound(&zs,
87 static_cast<uLong>(in.size())));
88 zs.next_in = (Bytef*)in.data();
89 zs.avail_in = static_cast<uInt>(in.size());
90 zs.next_out = (Bytef*)&out[0];
91 zs.avail_out = static_cast<uInt>(out.size());
92 result = deflate(&zs, Z_FULL_FLUSH);
93 if(result != Z_OK)
94 throw std::logic_error("deflate failed");
95 out.resize(zs.total_out);
96 deflateEnd(&zs);
97 return out;
98 }
99
100 std::string
101 doInflateBeast(string_view const& in)
102 {
103 z_params zs;
104 std::string out;
105 inflate_stream is;
106 zs.next_in = &in[0];
107 zs.avail_in = in.size();
108 out.resize(in.size());
109 zs.next_out = &out[0];
110 zs.avail_out = out.size();
111 for(;;)
112 {
113 error_code ec;
114 is.write(zs, Flush::sync, ec);
115 if(ec)
116 throw std::logic_error("inflate_stream failed");
117 if(zs.avail_out > 0)
118 break;
119 out.resize(2 * zs.total_out);
120 zs.next_out = &out[zs.total_out];
121 zs.avail_out = out.size() - zs.total_out;
122 }
123 out.resize(zs.total_out);
124 return out;
125 }
126
127 std::string
128 doInflateZLib(string_view const& in)
129 {
130 int result;
131 z_stream zs;
132 std::string out;
133 memset(&zs, 0, sizeof(zs));
134 result = inflateInit2(&zs, -15);
135 zs.next_in = (Bytef*)in.data();
136 zs.avail_in = static_cast<uInt>(in.size());
137 out.resize(in.size());
138 zs.next_out = (Bytef*)&out[0];
139 zs.avail_out = static_cast<uInt>(out.size());
140 for(;;)
141 {
142 result = inflate(&zs, Z_SYNC_FLUSH);
143 if( result == Z_NEED_DICT ||
144 result == Z_DATA_ERROR ||
145 result == Z_MEM_ERROR)
146 {
147 throw std::logic_error("inflate failed");
148 }
149 if(zs.avail_out > 0)
150 break;
151 if(result == Z_STREAM_END)
152 break;
153 out.resize(2 * zs.total_out);
154 zs.next_out = (Bytef*)&out[zs.total_out];
155 zs.avail_out = static_cast<uInt>(
156 out.size() - zs.total_out);
157 }
158 out.resize(zs.total_out);
159 inflateEnd(&zs);
160 return out;
161 }
162
163 void
164 doCorpus(
165 std::size_t size,
166 std::size_t repeat)
167 {
168 std::size_t constexpr trials = 3;
169 std::uint64_t constexpr scale = 16;
170 auto const c1 = corpus1(size);
171 auto const c2 = corpus2(size * scale);
172 auto const in1 = compress(c1);
173 auto const in2 = compress(c2);
174 log <<
175 std::left << std::setw(10) << (std::to_string(size) + "B") <<
176 std::right << std::setw(12) << "Beast" << " " <<
177 std::right << std::setw(12) << "ZLib" <<
178 std::endl;
179 for(std::size_t i = 0; i < trials; ++i)
180 {
181 test::timer t;
182 log << std::left << std::setw(10) << "corpus1";
183 std::string out;
184 for(std::size_t j = 0; j < repeat; ++j)
185 out = doInflateBeast(in1);
186 BEAST_EXPECT(out == c1);
187 auto const t1 =
188 test::throughput(t.elapsed(), size * repeat);
189 log << std::right << std::setw(12) << t1 << " B/s ";
190 for(std::size_t j = 0; j < repeat; ++j)
191 out = doInflateZLib(in1);
192 BEAST_EXPECT(out == c1);
193 auto const t2 =
194 test::throughput(t.elapsed(), size * repeat);
195 log << std::right << std::setw(12) << t2 << " B/s";
196 log << std::right << std::setw(12) <<
197 unsigned(double(t1)*100/t2-100) << "%";
198 log << std::endl;
199 }
200 for(std::size_t i = 0; i < trials; ++i)
201 {
202 test::timer t;
203 log << std::left << std::setw(10) << "corpus2";
204 std::string out;
205 for(std::size_t j = 0; j < repeat; ++j)
206 out = doInflateBeast(in2);
207 BEAST_EXPECT(out == c2);
208 auto const t1 =
209 test::throughput(t.elapsed(), size * scale * repeat);
210 log << std::right << std::setw(12) << t1 << " B/s ";
211 for(std::size_t j = 0; j < repeat; ++j)
212 out = doInflateZLib(in2);
213 BEAST_EXPECT(out == c2);
214 auto const t2 =
215 test::throughput(t.elapsed(), size * scale * repeat);
216 log << std::right << std::setw(12) << t2 << " B/s";
217 log << std::right << std::setw(12) <<
218 unsigned(double(t1)*100/t2-100) << "%";
219 log << std::endl;
220 }
221 log << std::endl;
222 }
223
224 void
225 doBench()
226 {
227 doCorpus( 1 * 1024 * 1024, 64);
228 doCorpus( 4 * 1024 * 1024, 16);
229 doCorpus( 16 * 1024 * 1024, 8);
230 }
231
232 void
233 run() override
234 {
235 doBench();
236 pass();
237 }
238 };
239
240 BEAST_DEFINE_TESTSUITE(beast,zlib,inflate_stream);
241
242 } // zlib
243 } // beast
244 } // boost