]>
git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/beast/test/bench/parser/bench_parser.cpp
3b4a83271f3b3e6968c493483adb8da0369606bf
2 // Copyright (c) 2016-2017 Vinnie Falco (vinnie dot falco at gmail dot com)
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)
7 // Official repository: https://github.com/boostorg/beast
10 #include "nodejs_parser.hpp"
12 #include "test/beast/http/message_fuzz.hpp"
14 #include <boost/beast/http.hpp>
15 #include <boost/beast/core/buffers_suffix.hpp>
16 #include <boost/beast/core/ostream.hpp>
17 #include <boost/beast/core/flat_buffer.hpp>
18 #include <boost/beast/core/multi_buffer.hpp>
19 #include <boost/beast/unit_test/suite.hpp>
28 class parser_test
: public beast::unit_test::suite
31 static std::size_t constexpr N
= 2000;
33 //using corpus = std::vector<multi_buffer>;
34 using corpus
= std::vector
<flat_buffer
>;
38 std::size_t size_
= 0;
40 template<class ConstBufferSequence
>
43 to_string(ConstBufferSequence
const& bs
)
46 s
.reserve(buffer_size(bs
));
47 for(auto b
: beast::detail::buffers_range(bs
))
48 s
.append(reinterpret_cast<char const*>(b
.data()),
54 build_corpus(std::size_t n
, std::true_type
)
59 for(std::size_t i
= 0; i
< n
; ++i
)
63 BEAST_EXPECT(v
[i
].size() > 0);
69 build_corpus(std::size_t n
, std::false_type
)
74 for(std::size_t i
= 0; i
< n
; ++i
)
78 BEAST_EXPECT(v
[i
].size() > 0);
83 template<class ConstBufferSequence
,
84 bool isRequest
, class Derived
>
87 feed(ConstBufferSequence
const& buffers
,
88 basic_parser
<isRequest
, Derived
>& parser
,
91 using boost::asio::buffer_size
;
92 beast::buffers_suffix
<
93 ConstBufferSequence
> cb
{buffers
};
107 if(buffer_size(cb
) == 0)
113 template<class Parser
>
115 testParser1(std::size_t repeat
, corpus
const& v
)
118 for(auto const& b
: v
)
122 p
.write(b
.data(), ec
);
123 if(! BEAST_EXPECTS(! ec
, ec
.message()))
124 log
<< to_string(b
.data()) << std::endl
;
128 template<class Parser
>
130 testParser2(std::size_t repeat
, corpus
const& v
)
133 for(auto const& b
: v
)
136 p
.header_limit((std::numeric_limits
<std::uint32_t>::max
)());
138 feed(b
.data(), p
, ec
);
139 if(! BEAST_EXPECTS(! ec
, ec
.message()))
140 log
<< to_string(b
.data()) << std::endl
;
144 template<class Function
>
146 timedTest(std::size_t repeat
, std::string
const& name
, Function
&& f
)
148 using namespace std::chrono
;
149 using clock_type
= std::chrono::high_resolution_clock
;
150 log
<< name
<< std::endl
;
151 for(std::size_t trial
= 1; trial
<= repeat
; ++trial
)
153 auto const t0
= clock_type::now();
155 auto const elapsed
= clock_type::now() - t0
;
157 "Trial " << trial
<< ": " <<
158 duration_cast
<milliseconds
>(elapsed
).count() << " ms" << std::endl
;
162 template<bool isRequest
>
164 basic_parser
<isRequest
, null_parser
<isRequest
>>
168 template<bool isRequest
, class Body
, class Fields
>
169 struct bench_parser
: basic_parser
<
170 isRequest
, bench_parser
<isRequest
, Body
, Fields
>>
172 using mutable_buffers_type
=
173 boost::asio::mutable_buffer
;
176 on_request_impl(verb
, string_view
,
177 string_view
, int, error_code
& ec
)
179 ec
.assign(0, ec
.category());
183 on_response_impl(int,
187 ec
.assign(0, ec
.category());
192 string_view
, string_view
, error_code
& ec
)
194 ec
.assign(0, ec
.category());
198 on_header_impl(error_code
& ec
)
200 ec
.assign(0, ec
.category());
205 boost::optional
<std::uint64_t> const&,
208 ec
.assign(0, ec
.category());
212 on_body_impl(string_view s
, error_code
& ec
)
214 ec
.assign(0, ec
.category());
219 on_chunk_header_impl(std::uint64_t,
220 string_view
, error_code
& ec
)
222 ec
.assign(0, ec
.category());
226 on_chunk_body_impl(std::uint64_t,
227 string_view s
, error_code
& ec
)
229 ec
.assign(0, ec
.category());
234 on_finish_impl(error_code
& ec
)
236 ec
.assign(0, ec
.category());
243 static std::size_t constexpr Trials
= 5;
244 static std::size_t constexpr Repeat
= 500;
246 creq_
= build_corpus(N
/2, std::true_type
{});
247 cres_
= build_corpus(N
/2, std::false_type
{});
249 log
<< "sizeof(request parser) == " <<
250 sizeof(null_parser
<true>) << '\n';
252 log
<< "sizeof(response parser) == " <<
253 sizeof(null_parser
<false>)<< '\n';
255 testcase
<< "Parser speed test, " <<
256 ((Repeat
* size_
+ 512) / 1024) << "KB in " <<
257 (Repeat
* (creq_
.size() + cres_
.size())) << " messages";
260 timedTest(Trials
, "http::parser",
263 testParser2
<request_parser
<dynamic_body
>>(Repeat
, creq_
);
264 testParser2
<response_parser
<dynamic_body
>>(Repeat
, cres_
);
268 timedTest(Trials
, "http::basic_parser",
271 testParser2
<bench_parser
<
272 true, dynamic_body
, fields
> >(
274 testParser2
<bench_parser
<
275 false, dynamic_body
, fields
>>(
279 timedTest(Trials
, "nodejs_parser",
282 testParser1
<nodejs_parser
<
283 true, dynamic_body
, fields
>>(
285 testParser1
<nodejs_parser
<
286 false, dynamic_body
, fields
>>(
301 BEAST_DEFINE_TESTSUITE(beast
,benchmarks
,parser
);