• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/websocket/detail/utf8_checker.hpp>
11 #include <boost/beast/_experimental/unit_test/suite.hpp>
12 #include <chrono>
13 #include <random>
14 
15 #ifndef BEAST_USE_BOOST_LOCALE_BENCHMARK
16 #define BEAST_USE_BOOST_LOCALE_BENCHMARK 0
17 #endif
18 
19 #if BEAST_USE_BOOST_LOCALE_BENCHMARK
20 #include <boost/locale.hpp>
21 #endif
22 
23 namespace boost {
24 namespace beast {
25 
26 class utf8_checker_test : public beast::unit_test::suite
27 {
28     std::mt19937 rng_;
29 
30 public:
31     using size_type = std::uint64_t;
32 
33     class timer
34     {
35     public:
36         using clock_type =
37             std::chrono::system_clock;
38 
39     private:
40         clock_type::time_point when_;
41 
42     public:
43         using duration =
44             clock_type::duration;
45 
timer()46         timer()
47             : when_(clock_type::now())
48         {
49         }
50 
51         duration
elapsed() const52         elapsed() const
53         {
54             return clock_type::now() - when_;
55         }
56     };
57 
58     template<class UInt = std::size_t>
59     UInt
rand(std::size_t n)60     rand(std::size_t n)
61     {
62         return static_cast<UInt>(
63             std::uniform_int_distribution<
64                 std::size_t>{0, n-1}(rng_));
65     }
66 
67     static
68     inline
69     size_type
throughput(std::chrono::duration<double> const & elapsed,size_type items)70     throughput(std::chrono::duration<
71         double> const& elapsed, size_type items)
72     {
73         using namespace std::chrono;
74         return static_cast<size_type>(
75             1 / (elapsed/items).count());
76     }
77 
78     std::string
corpus(std::size_t n)79     corpus(std::size_t n)
80     {
81         std::string s;
82         s.reserve(n);
83         while(n--)
84             s.push_back(static_cast<char>(
85                 ' ' + rand(95)));
86         return s;
87     }
88 
89     void
checkBeast(std::string const & s)90     checkBeast(std::string const& s)
91     {
92         beast::websocket::detail::check_utf8(
93             s.data(), s.size());
94     }
95 
96 #if BEAST_USE_BOOST_LOCALE_BENCHMARK
97     void
checkLocale(std::string const & s)98     checkLocale(std::string const& s)
99     {
100         using namespace boost::locale;
101         auto p = s.begin();
102         auto const e = s.end();
103         while(p != e)
104         {
105             auto cp = utf::utf_traits<char>::decode(p, e);
106             if(cp == utf::illegal)
107                 break;
108         }
109     }
110 #endif
111 
112     template<class F>
113     typename timer::clock_type::duration
test(F const & f)114     test(F const& f)
115     {
116         timer t;
117         f();
118         return t.elapsed();
119     }
120 
121     void
run()122     run() override
123     {
124         auto const s = corpus(32 * 1024 * 1024);
125         for(int i = 0; i < 5; ++ i)
126         {
127             auto const elapsed = test([&]{
128                 checkBeast(s);
129                 checkBeast(s);
130                 checkBeast(s);
131                 checkBeast(s);
132                 checkBeast(s);
133             });
134             log << "beast:  " << throughput(elapsed, s.size()) << " char/s" << std::endl;
135         }
136     #if BEAST_USE_BOOST_LOCALE_BENCHMARK
137         for(int i = 0; i < 5; ++ i)
138         {
139             auto const elapsed = test([&]{
140                 checkLocale(s);
141                 checkLocale(s);
142                 checkLocale(s);
143                 checkLocale(s);
144                 checkLocale(s);
145             });
146             log << "locale: " << throughput(elapsed, s.size()) << " char/s" << std::endl;
147         }
148     #endif
149         pass();
150     }
151 };
152 
153 BEAST_DEFINE_TESTSUITE(beast,benchmarks,utf8_checker);
154 
155 } // beast
156 } // boost
157 
158