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