]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/libs/beast/test/bench/parser/bench_parser.cpp
import new upstream nautilus stable release 14.2.8
[ceph.git] / ceph / src / boost / libs / beast / test / bench / parser / bench_parser.cpp
CommitLineData
7c673cae 1//
92f5a8d4 2// Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
7c673cae
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//
b32b8144
FG
7// Official repository: https://github.com/boostorg/beast
8//
7c673cae
FG
9
10#include "nodejs_parser.hpp"
7c673cae 11
b32b8144
FG
12#include "test/beast/http/message_fuzz.hpp"
13
14#include <boost/beast/http.hpp>
92f5a8d4 15#include <boost/beast/core/buffer_traits.hpp>
b32b8144 16#include <boost/beast/core/buffers_suffix.hpp>
92f5a8d4 17#include <boost/beast/core/buffers_to_string.hpp>
b32b8144
FG
18#include <boost/beast/core/ostream.hpp>
19#include <boost/beast/core/flat_buffer.hpp>
20#include <boost/beast/core/multi_buffer.hpp>
92f5a8d4 21#include <boost/beast/_experimental/unit_test/suite.hpp>
7c673cae
FG
22#include <chrono>
23#include <iostream>
24#include <vector>
25
b32b8144 26namespace boost {
7c673cae
FG
27namespace beast {
28namespace http {
29
b32b8144 30class parser_test : public beast::unit_test::suite
7c673cae
FG
31{
32public:
33 static std::size_t constexpr N = 2000;
34
b32b8144
FG
35 //using corpus = std::vector<multi_buffer>;
36 using corpus = std::vector<flat_buffer>;
7c673cae
FG
37
38 corpus creq_;
39 corpus cres_;
40 std::size_t size_ = 0;
41
7c673cae
FG
42 corpus
43 build_corpus(std::size_t n, std::true_type)
44 {
45 corpus v;
b32b8144 46 v.resize(n);
7c673cae
FG
47 message_fuzz mg;
48 for(std::size_t i = 0; i < n; ++i)
49 {
50 mg.request(v[i]);
51 size_ += v[i].size();
b32b8144 52 BEAST_EXPECT(v[i].size() > 0);
7c673cae
FG
53 }
54 return v;
55 }
56
57 corpus
58 build_corpus(std::size_t n, std::false_type)
59 {
60 corpus v;
b32b8144 61 v.resize(n);
7c673cae
FG
62 message_fuzz mg;
63 for(std::size_t i = 0; i < n; ++i)
64 {
65 mg.response(v[i]);
66 size_ += v[i].size();
b32b8144 67 BEAST_EXPECT(v[i].size() > 0);
7c673cae
FG
68 }
69 return v;
70 }
71
72 template<class ConstBufferSequence,
92f5a8d4 73 bool isRequest>
7c673cae
FG
74 static
75 std::size_t
76 feed(ConstBufferSequence const& buffers,
92f5a8d4 77 basic_parser<isRequest>& parser,
7c673cae
FG
78 error_code& ec)
79 {
b32b8144 80 beast::buffers_suffix<
7c673cae
FG
81 ConstBufferSequence> cb{buffers};
82 std::size_t used = 0;
83 for(;;)
84 {
85 auto const n =
b32b8144 86 parser.put(cb, ec);
7c673cae
FG
87 if(ec)
88 return 0;
89 if(n == 0)
90 break;
91 cb.consume(n);
92 used += n;
b32b8144 93 if(parser.is_done())
7c673cae 94 break;
92f5a8d4 95 if(buffer_bytes(cb) == 0)
7c673cae
FG
96 break;
97 }
98 return used;
99 }
100
101 template<class Parser>
102 void
103 testParser1(std::size_t repeat, corpus const& v)
104 {
105 while(repeat--)
b32b8144 106 for(auto const& b : v)
7c673cae
FG
107 {
108 Parser p;
109 error_code ec;
b32b8144 110 p.write(b.data(), ec);
7c673cae 111 if(! BEAST_EXPECTS(! ec, ec.message()))
92f5a8d4 112 log << buffers_to_string(b.data()) << std::endl;
7c673cae
FG
113 }
114 }
115
116 template<class Parser>
117 void
118 testParser2(std::size_t repeat, corpus const& v)
119 {
120 while(repeat--)
b32b8144 121 for(auto const& b : v)
7c673cae
FG
122 {
123 Parser p;
b32b8144 124 p.header_limit((std::numeric_limits<std::uint32_t>::max)());
7c673cae 125 error_code ec;
b32b8144 126 feed(b.data(), p, ec);
7c673cae 127 if(! BEAST_EXPECTS(! ec, ec.message()))
92f5a8d4 128 log << buffers_to_string(b.data()) << std::endl;
7c673cae
FG
129 }
130 }
131
132 template<class Function>
133 void
134 timedTest(std::size_t repeat, std::string const& name, Function&& f)
135 {
136 using namespace std::chrono;
137 using clock_type = std::chrono::high_resolution_clock;
138 log << name << std::endl;
139 for(std::size_t trial = 1; trial <= repeat; ++trial)
140 {
141 auto const t0 = clock_type::now();
142 f();
143 auto const elapsed = clock_type::now() - t0;
144 log <<
145 "Trial " << trial << ": " <<
146 duration_cast<milliseconds>(elapsed).count() << " ms" << std::endl;
147 }
148 }
149
150 template<bool isRequest>
151 struct null_parser :
92f5a8d4 152 basic_parser<isRequest>
7c673cae 153 {
92f5a8d4
TL
154 void
155 on_request_impl(
156 verb, string_view, string_view,
157 int, error_code&) override
158 {
159 }
160
161 void
162 on_response_impl(
163 int, string_view, int,
164 error_code&) override
165 {
166 }
167
168 void
169 on_field_impl(
170 field, string_view, string_view,
171 error_code&) override
172 {
173 }
174
175 void
176 on_header_impl(error_code&) override
177 {
178 }
179
180 void
181 on_body_init_impl(
182 boost::optional<std::uint64_t> const&,
183 error_code&) override
184 {
185 }
186
187 std::size_t
188 on_body_impl(
189 string_view,
190 error_code&) override
191 {
192 return 0;
193 }
194
195 void
196 on_chunk_header_impl(
197 std::uint64_t,
198 string_view,
199 error_code&) override
200 {
201 }
202
203 std::size_t
204 on_chunk_body_impl(
205 std::uint64_t,
206 string_view,
207 error_code&) override
208 {
209 return 0;
210 }
211
212 void
213 on_finish_impl(error_code&) override
214 {
215 }
7c673cae
FG
216 };
217
218 template<bool isRequest, class Body, class Fields>
92f5a8d4 219 struct bench_parser : basic_parser<isRequest>
7c673cae
FG
220 {
221 using mutable_buffers_type =
92f5a8d4 222 net::mutable_buffer;
7c673cae
FG
223
224 void
b32b8144 225 on_request_impl(verb, string_view,
92f5a8d4 226 string_view, int, error_code&) override
7c673cae
FG
227 {
228 }
229
230 void
b32b8144 231 on_response_impl(int,
92f5a8d4 232 string_view, int, error_code&) override
7c673cae
FG
233 {
234 }
235
236 void
b32b8144 237 on_field_impl(field,
92f5a8d4 238 string_view, string_view, error_code&) override
7c673cae
FG
239 {
240 }
241
242 void
92f5a8d4 243 on_header_impl(error_code&) override
7c673cae
FG
244 {
245 }
246
247 void
b32b8144
FG
248 on_body_init_impl(
249 boost::optional<std::uint64_t> const&,
92f5a8d4 250 error_code&) override
7c673cae
FG
251 {
252 }
253
b32b8144 254 std::size_t
92f5a8d4
TL
255 on_body_impl(
256 string_view s, error_code&) override
7c673cae 257 {
b32b8144 258 return s.size();
7c673cae
FG
259 }
260
261 void
b32b8144 262 on_chunk_header_impl(std::uint64_t,
92f5a8d4 263 string_view, error_code&) override
7c673cae
FG
264 {
265 }
266
b32b8144
FG
267 std::size_t
268 on_chunk_body_impl(std::uint64_t,
92f5a8d4 269 string_view s, error_code&) override
7c673cae 270 {
b32b8144 271 return s.size();
7c673cae
FG
272 }
273
274 void
92f5a8d4 275 on_finish_impl(error_code&) override
7c673cae
FG
276 {
277 }
278 };
279
280 void
281 testSpeed()
282 {
b32b8144 283 static std::size_t constexpr Trials = 5;
7c673cae
FG
284 static std::size_t constexpr Repeat = 500;
285
b32b8144
FG
286 creq_ = build_corpus(N/2, std::true_type{});
287 cres_ = build_corpus(N/2, std::false_type{});
288
7c673cae
FG
289 log << "sizeof(request parser) == " <<
290 sizeof(null_parser<true>) << '\n';
291
292 log << "sizeof(response parser) == " <<
293 sizeof(null_parser<false>)<< '\n';
294
295 testcase << "Parser speed test, " <<
296 ((Repeat * size_ + 512) / 1024) << "KB in " <<
297 (Repeat * (creq_.size() + cres_.size())) << " messages";
298
b32b8144
FG
299#if 0
300 timedTest(Trials, "http::parser",
7c673cae
FG
301 [&]
302 {
b32b8144
FG
303 testParser2<request_parser<dynamic_body>>(Repeat, creq_);
304 testParser2<response_parser<dynamic_body>>(Repeat, cres_);
7c673cae 305 });
b32b8144
FG
306#endif
307#if 1
7c673cae
FG
308 timedTest(Trials, "http::basic_parser",
309 [&]
310 {
311 testParser2<bench_parser<
b32b8144 312 true, dynamic_body, fields> >(
7c673cae
FG
313 Repeat, creq_);
314 testParser2<bench_parser<
b32b8144
FG
315 false, dynamic_body, fields>>(
316 Repeat, cres_);
317 });
318#if 1
319 timedTest(Trials, "nodejs_parser",
320 [&]
321 {
322 testParser1<nodejs_parser<
323 true, dynamic_body, fields>>(
324 Repeat, creq_);
325 testParser1<nodejs_parser<
326 false, dynamic_body, fields>>(
7c673cae
FG
327 Repeat, cres_);
328 });
b32b8144
FG
329#endif
330#endif
7c673cae
FG
331 pass();
332 }
333
334 void run() override
335 {
336 pass();
337 testSpeed();
338 }
339};
340
b32b8144 341BEAST_DEFINE_TESTSUITE(beast,benchmarks,parser);
7c673cae
FG
342
343} // http
344} // beast
b32b8144 345} // boost
7c673cae 346