Imported Upstream version 1.72.0
[platform/upstream/boost.git] / libs / beast / test / bench / zlib / deflate_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/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>
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 deflate_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     std::string
68     doDeflateBeast(string_view const& in)
69     {
70         z_params zs;
71         deflate_stream ds;
72         ds.reset(
73             Z_DEFAULT_COMPRESSION,
74             15,
75             4,
76             Strategy::normal);
77         std::string out;
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();
83         error_code ec;
84         ds.write(zs, Flush::full, ec);
85         BEAST_EXPECTS(! ec, ec.message());
86         out.resize(zs.total_out);
87         return out;
88     }
89
90     std::string
91     doDeflateZLib(string_view const& in)
92     {
93         int result;
94         z_stream zs;
95         memset(&zs, 0, sizeof(zs));
96         result = deflateInit2(
97             &zs,
98             Z_DEFAULT_COMPRESSION,
99             Z_DEFLATED,
100             -15,
101             4,
102             Z_DEFAULT_STRATEGY
103         );
104         if(result != Z_OK)
105             throw std::logic_error("deflateInit2 failed");
106         std::string out;
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);
114         if(result != Z_OK)
115             throw std::logic_error("deflate failed");
116         out.resize(zs.total_out);
117         deflateEnd(&zs);
118         return out;
119     }
120
121     void
122     doCorpus(
123         std::size_t size,
124         std::size_t repeat)
125     {
126         std::size_t constexpr trials = 3;
127         auto const c1 = corpus1(size);
128         auto const c2 = corpus2(size);
129         log <<
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" <<
133                 std::endl;
134         for(std::size_t i = 0; i < trials; ++i)
135         {
136             test::timer t;
137             log << std::left << std::setw(10) << "corpus1";
138             std::string out1;
139             for(std::size_t j = 0; j < repeat; ++j)
140                 out1 = doDeflateBeast(c1);
141             auto const t1 =
142                 test::throughput(t.elapsed(), size * repeat);
143             log << std::right << std::setw(12) << t1 << " B/s ";
144             std::string out2;
145             for(std::size_t j = 0; j < repeat; ++j)
146                 out2 = doDeflateZLib(c1);
147             BEAST_EXPECT(out1 == out2);
148             auto const t2 =
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) << "%";
153             log << std::endl;
154         }
155         for(std::size_t i = 0; i < trials; ++i)
156         {
157             test::timer t;
158             log << std::left << std::setw(10) << "corpus2";
159             std::string out1;
160             for(std::size_t j = 0; j < repeat; ++j)
161                 out1 = doDeflateBeast(c2);
162             auto const t1 =
163                 test::throughput(t.elapsed(), size * repeat);
164             log << std::right << std::setw(12) << t1 << " B/s ";
165             std::string out2;
166             for(std::size_t j = 0; j < repeat; ++j)
167                 out2 = doDeflateZLib(c2);
168             BEAST_EXPECT(out1 == out2);
169             auto const t2 =
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) << "%";
174             log << std::endl;
175         }
176         log << std::endl;
177     }
178
179     void
180     doBench()
181     {
182         doCorpus(      16 * 1024, 512);
183         doCorpus(    1024 * 1024,   8);
184         doCorpus(8 * 1024 * 1024,   1);
185     }
186
187     void
188     run() override
189     {
190         doBench();
191         pass();
192     }
193 };
194
195 BEAST_DEFINE_TESTSUITE(beast,zlib,deflate_stream);
196
197 } // zlib
198 } // beast
199 } // boost