]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/beast/test/bench/buffers/bench_buffers.cpp
update sources to v12.2.3
[ceph.git] / ceph / src / boost / libs / beast / test / bench / buffers / bench_buffers.cpp
1 //
2 // Copyright (c) 2016-2017 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/flat_buffer.hpp>
11 #include <boost/beast/core/multi_buffer.hpp>
12 #include <boost/beast/core/read_size.hpp>
13 #include <boost/beast/core/string.hpp>
14 #include <boost/beast/unit_test/suite.hpp>
15 #include <boost/asio/streambuf.hpp>
16 #include <algorithm>
17 #include <chrono>
18 #include <cstdlib>
19 #include <iomanip>
20 #include <utility>
21 #include <vector>
22
23 namespace boost {
24 namespace beast {
25
26 class buffers_test : public beast::unit_test::suite
27 {
28 public:
29 using size_type = std::uint64_t;
30
31 class timer
32 {
33 using clock_type =
34 std::chrono::system_clock;
35
36 clock_type::time_point when_;
37
38 public:
39 using duration =
40 clock_type::duration;
41
42 timer()
43 : when_(clock_type::now())
44 {
45 }
46
47 duration
48 elapsed() const
49 {
50 return clock_type::now() - when_;
51 }
52 };
53
54 inline
55 size_type
56 throughput(std::chrono::duration<
57 double> const& elapsed, size_type items)
58 {
59 using namespace std::chrono;
60 return static_cast<size_type>(
61 1 / (elapsed/items).count());
62 }
63
64 template<class MutableBufferSequence>
65 static
66 std::size_t
67 fill(MutableBufferSequence const& buffers)
68 {
69 std::size_t n = 0;
70 for(auto b : beast::detail::buffers_range(buffers))
71 {
72 std::fill(
73 reinterpret_cast<char*>(b.data()),
74 reinterpret_cast<char*>(b.data()) +
75 b.size(), '\0');
76 n += b.size();
77 }
78 return n;
79 }
80
81 template<class DynamicBuffer>
82 size_type
83 do_prepares(std::size_t repeat,
84 std::size_t count, std::size_t size)
85 {
86 timer t;
87 size_type total = 0;
88 for(auto i = repeat; i--;)
89 {
90 DynamicBuffer b;
91 for(auto j = count; j--;)
92 {
93 auto const n = fill(b.prepare(size));
94 b.commit(n);
95 total += n;
96 }
97 }
98 return throughput(t.elapsed(), total);
99 }
100
101 template<class DynamicBuffer>
102 size_type
103 do_hints(std::size_t repeat,
104 std::size_t count, std::size_t size)
105 {
106 timer t;
107 size_type total = 0;
108 for(auto i = repeat; i--;)
109 {
110 DynamicBuffer b;
111 for(auto j = count; j--;)
112 {
113 for(auto remain = size; remain;)
114 {
115 auto const n = fill(b.prepare(
116 read_size(b, remain)));
117 b.commit(n);
118 remain -= n;
119 total += n;
120 }
121 }
122 }
123 return throughput(t.elapsed(), total);
124 }
125
126 template<class DynamicBuffer>
127 size_type
128 do_random(std::size_t repeat,
129 std::size_t count, std::size_t size)
130 {
131 timer t;
132 size_type total = 0;
133 for(auto i = repeat; i--;)
134 {
135 DynamicBuffer b;
136 for(auto j = count; j--;)
137 {
138 auto const n = fill(b.prepare(
139 1 + (rand()%(2*size))));
140 b.commit(n);
141 total += n;
142 }
143 }
144 return throughput(t.elapsed(), total);
145 }
146
147 static
148 inline
149 void
150 do_trials_1(bool)
151 {
152 }
153
154 template<class F0, class... FN>
155 void
156 do_trials_1(bool print, F0&& f, FN... fn)
157 {
158 timer t;
159 using namespace std::chrono;
160 static size_type constexpr den = 1024 * 1024;
161 if(print)
162 {
163 log << std::right << std::setw(10) <<
164 ((f() + (den / 2)) / den) << " MB/s";
165 log.flush();
166 }
167 else
168 {
169 f();
170 }
171 do_trials_1(print, fn...);
172 }
173
174 template<class F0, class... FN>
175 void
176 do_trials(string_view name,
177 std::size_t trials, F0&& f0, FN... fn)
178 {
179 using namespace std::chrono;
180 // warm-up
181 do_trials_1(false, f0, fn...);
182 do_trials_1(false, f0, fn...);
183 while(trials--)
184 {
185 timer t;
186 log << std::left << std::setw(24) << name << ":";
187 log.flush();
188 do_trials_1(true, f0, fn...);
189 log << " " <<
190 duration_cast<milliseconds>(t.elapsed()).count() << "ms";
191 log << std::endl;
192 }
193 }
194
195 void
196 run() override
197 {
198 static std::size_t constexpr trials = 1;
199 static std::size_t constexpr repeat = 250;
200 std::vector<std::pair<std::size_t, std::size_t>> params;
201 params.emplace_back(1024, 1024);
202 params.emplace_back(512, 4096);
203 params.emplace_back(256, 32768);
204 log << std::endl;
205 for(auto const& param : params)
206 {
207 auto const count = param.first;
208 auto const size = param.second;
209 auto const s = std::string("count=") + std::to_string(count) +
210 ", size=" + std::to_string(size);
211 log << std::left << std::setw(24) << s << " " <<
212 std::right << std::setw(15) << "prepare" <<
213 std::right << std::setw(15) << "with hint" <<
214 std::right << std::setw(15) << "random" <<
215 std::endl;
216 do_trials("multi_buffer", trials,
217 [&](){ return do_prepares<multi_buffer>(repeat, count, size); }
218 ,[&](){ return do_hints <multi_buffer>(repeat, count, size); }
219 ,[&](){ return do_random <multi_buffer>(repeat, count, size); }
220 );
221 do_trials("flat_buffer", trials,
222 [&](){ return do_prepares<flat_buffer>(repeat, count, size); }
223 ,[&](){ return do_hints <flat_buffer>(repeat, count, size); }
224 ,[&](){ return do_random <flat_buffer>(repeat, count, size); }
225 );
226 do_trials("boost::asio::streambuf", trials,
227 [&](){ return do_prepares<boost::asio::streambuf>(repeat, count, size); }
228 ,[&](){ return do_hints <boost::asio::streambuf>(repeat, count, size); }
229 ,[&](){ return do_random <boost::asio::streambuf>(repeat, count, size); }
230 );
231 log << std::endl;
232 }
233 pass();
234 }
235 };
236
237 BEAST_DEFINE_TESTSUITE(beast,benchmarks,buffers);
238
239 } // beast
240 } // boost