]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/convert/test/performance.cpp
update sources to v12.2.3
[ceph.git] / ceph / src / boost / libs / convert / test / performance.cpp
1 // Boost.Convert test and usage example
2 // Copyright (c) 2009-2016 Vladimir Batov.
3 // Use, modification and distribution are subject to the Boost Software License,
4 // Version 1.0. See http://www.boost.org/LICENSE_1_0.txt.
5
6 #include "./test.hpp"
7
8 #if defined(BOOST_CONVERT_IS_NOT_SUPPORTED)
9 int main(int, char const* []) { return 0; }
10 #else
11
12 #include "./prepare.hpp"
13 #include <boost/convert.hpp>
14 #include <boost/convert/stream.hpp>
15 #include <boost/convert/printf.hpp>
16 #include <boost/convert/strtol.hpp>
17 #include <boost/convert/spirit.hpp>
18 #include <boost/convert/lexical_cast.hpp>
19 #include <boost/detail/lightweight_test.hpp>
20 #include <boost/timer/timer.hpp>
21 #include <boost/array.hpp>
22 #include <boost/random/mersenne_twister.hpp>
23 #include <boost/random/uniform_int_distribution.hpp>
24 #include <cstdlib>
25 #include <cstdio>
26
27 using std::string;
28 using boost::convert;
29
30 namespace cnv = boost::cnv;
31 namespace arg = boost::cnv::parameter;
32
33 namespace { namespace local
34 {
35 template<typename Type>
36 struct array
37 {
38 typedef boost::array<Type, 20> type;
39 };
40 template<typename T> static typename array<T>::type const& get();
41
42 static int const num_cycles = 1000000;
43 int sum = 0;
44
45 struct timer : public boost::timer::cpu_timer
46 {
47 typedef timer this_type;
48 typedef boost::timer::cpu_timer base_type;
49
50 double value() const
51 {
52 boost::timer::cpu_times times = base_type::elapsed();
53 int const use_sum = (sum % 2) ? 0 : (sum % 2); BOOST_TEST(use_sum == 0);
54
55 return double(times.user + times.system) / 1000000000 + use_sum;
56 }
57 };
58 template< typename Type, typename Cnv> static double str_to (Cnv const&);
59 template<typename S, typename Type, typename Cnv> static double to_str (Cnv const&);
60
61 template<>
62 local::array<int>::type const&
63 get<int>()
64 {
65 static array<int>::type ints;
66 static bool filled;
67
68 if (!filled)
69 {
70 boost::random::mt19937 gen (::time(0));
71 boost::random::uniform_int_distribution<> dist (INT_MIN, INT_MAX); // INT_MAX(32) = 2,147,483,647
72
73 for (size_t k = 0; k < ints.size(); ++k)
74 ints[k] = dist(gen);
75
76 filled = true;
77 }
78 return ints;
79 }
80 template<>
81 array<long int>::type const&
82 get<long int>()
83 {
84 static array<long int>::type ints;
85 static bool filled;
86
87 if (!filled)
88 {
89 boost::random::mt19937 gen (::time(0));
90 boost::random::uniform_int_distribution<> dist (INT_MIN, INT_MAX); // INT_MAX(32) = 2147483647
91
92 for (size_t k = 0; k < ints.size(); ++k)
93 ints[k] = dist(gen);
94
95 filled = true;
96 }
97 return ints;
98 }
99 template<>
100 array<double>::type const&
101 get<double>()
102 {
103 static array<double>::type dbls;
104 static bool filled;
105
106 if (!filled)
107 {
108 boost::random::mt19937 gen (::time(0));
109 boost::random::uniform_int_distribution<> dist (INT_MIN, INT_MAX); // INT_MAX(32) = 2147483647
110
111 for (size_t k = 0; k < dbls.size(); ++k)
112 dbls[k] = double(dist(gen)) + 0.7654321;
113
114 filled = true;
115 }
116 return dbls;
117 }
118 }}
119
120 struct raw_str_to_int_spirit
121 {
122 int operator()(char const* str) const
123 {
124 char const* beg = str;
125 char const* end = beg + strlen(str);
126 int result;
127
128 if (boost::spirit::qi::parse(beg, end, boost::spirit::int_, result))
129 if (beg == end) // ensure the whole string was parsed
130 return result;
131
132 return (BOOST_ASSERT(0), result);
133 }
134 };
135
136 struct raw_str_to_int_lxcast
137 {
138 int operator()(char const* str) const
139 {
140 return boost::lexical_cast<int>(str);
141 }
142 };
143
144 template<typename Type, typename Converter>
145 double
146 raw_str_to(Converter const& cnv)
147 {
148 local::strings strings = local::get_strs(); // Create strings on the stack
149 int const size = strings.size();
150 local::timer timer;
151
152 for (int t = 0; t < local::num_cycles; ++t)
153 for (int k = 0; k < size; ++k)
154 local::sum += cnv(strings[k].c_str());
155
156 return timer.value();
157 }
158
159 template<typename Type, typename Converter>
160 double
161 local::str_to(Converter const& try_converter)
162 {
163 local::strings strings = local::get_strs(); // Create strings on the stack
164 int const size = strings.size();
165 local::timer timer;
166
167 for (int t = 0; t < local::num_cycles; ++t)
168 for (int k = 0; k < size; ++k)
169 local::sum += boost::convert<Type>(strings[k].c_str(), try_converter).value();
170
171 return timer.value();
172 }
173
174 template<typename string_type, typename Type, typename Converter>
175 double
176 local::to_str(Converter const& try_converter)
177 {
178 typedef typename local::array<Type>::type collection;
179
180 collection values = local::get<Type>();
181 int const size = values.size();
182 local::timer timer;
183
184 for (int t = 0; t < local::num_cycles; ++t)
185 for (int k = 0; k < size; ++k)
186 local::sum += *boost::convert<string_type>(Type(values[k]), try_converter).value().begin();
187
188 return timer.value();
189 }
190
191 template<typename Converter>
192 double
193 performance_str_to_type(Converter const& try_converter)
194 {
195 char const* input[] = { "no", "up", "dn" };
196 local::timer timer;
197
198 for (int k = 0; k < local::num_cycles; ++k)
199 {
200 change chg = boost::convert<change>(input[k % 3], try_converter).value();
201 int res = chg.value();
202
203 BOOST_TEST(res == k % 3);
204
205 local::sum += res; // Make sure chg is not optimized out
206 }
207 return timer.value();
208 }
209
210 template<typename Converter>
211 double
212 performance_type_to_str(Converter const& try_converter)
213 {
214 boost::array<change, 3> input = {{ change::no, change::up, change::dn }};
215 boost::array<string, 3> results = {{ "no", "up", "dn" }};
216 local::timer timer;
217
218 for (int k = 0; k < local::num_cycles; ++k)
219 {
220 string res = boost::convert<string>(input[k % 3], try_converter).value();
221
222 BOOST_TEST(res == results[k % 3]);
223
224 local::sum += res[0]; // Make sure res is not optimized out
225 }
226 return timer.value();
227 }
228
229 template<typename Raw, typename Cnv>
230 void
231 performance_comparative(Raw const& raw, Cnv const& cnv, char const* txt)
232 {
233 int const num_tries = 5;
234 double cnv_time = 0;
235 double raw_time = 0;
236
237 for (int k = 0; k < num_tries; ++k) cnv_time += local::str_to<int>(cnv);
238 for (int k = 0; k < num_tries; ++k) raw_time += raw_str_to<int>(raw);
239
240 cnv_time /= num_tries;
241 raw_time /= num_tries;
242
243 double change = 100 * (1 - cnv_time / raw_time);
244
245 printf("str-to-int: %s raw/cnv=%.2f/%.2f seconds (%.2f%%).\n", txt, raw_time, cnv_time, change);
246 }
247
248 int
249 main(int, char const* [])
250 {
251 printf("Started performance tests...\n");
252
253 printf("str-to-int: spirit/strtol/lcast/scanf/stream=%7.2f/%7.2f/%7.2f/%7.2f/%7.2f seconds.\n",
254 local::str_to<int>(boost::cnv::spirit()),
255 local::str_to<int>(boost::cnv::strtol()),
256 local::str_to<int>(boost::cnv::lexical_cast()),
257 local::str_to<int>(boost::cnv::printf()),
258 local::str_to<int>(boost::cnv::cstream()));
259 printf("str-to-lng: spirit/strtol/lcast/scanf/stream=%7.2f/%7.2f/%7.2f/%7.2f/%7.2f seconds.\n",
260 local::str_to<long int>(boost::cnv::spirit()),
261 local::str_to<long int>(boost::cnv::strtol()),
262 local::str_to<long int>(boost::cnv::lexical_cast()),
263 local::str_to<long int>(boost::cnv::printf()),
264 local::str_to<long int>(boost::cnv::cstream()));
265 printf("str-to-dbl: spirit/strtol/lcast/scanf/stream=%7.2f/%7.2f/%7.2f/%7.2f/%7.2f seconds.\n",
266 local::str_to<double>(boost::cnv::spirit()),
267 local::str_to<double>(boost::cnv::strtol()),
268 local::str_to<double>(boost::cnv::lexical_cast()),
269 local::str_to<double>(boost::cnv::printf()),
270 local::str_to<double>(boost::cnv::cstream()));
271
272 printf("int-to-str: spirit/strtol/lcast/prntf/stream=%7.2f/%7.2f/%7.2f/%7.2f/%7.2f seconds.\n",
273 local::to_str<std::string, int>(boost::cnv::spirit()),
274 local::to_str<std::string, int>(boost::cnv::strtol()),
275 local::to_str<std::string, int>(boost::cnv::lexical_cast()),
276 local::to_str<std::string, int>(boost::cnv::printf()),
277 local::to_str<std::string, int>(boost::cnv::cstream()));
278 printf("lng-to-str: spirit/strtol/lcast/prntf/stream=%7.2f/%7.2f/%7.2f/%7.2f/%7.2f seconds.\n",
279 local::to_str<std::string, long int>(boost::cnv::spirit()),
280 local::to_str<std::string, long int>(boost::cnv::strtol()),
281 local::to_str<std::string, long int>(boost::cnv::lexical_cast()),
282 local::to_str<std::string, long int>(boost::cnv::printf()),
283 local::to_str<std::string, long int>(boost::cnv::cstream()));
284 printf("dbl-to-str: spirit/strtol/lcast/prntf/stream=%7.2f/%7.2f/%7.2f/%7.2f/%7.2f seconds.\n",
285 local::to_str<std::string, double>(boost::cnv::spirit()),
286 local::to_str<std::string, double>(boost::cnv::strtol()(arg::precision = 6)),
287 local::to_str<std::string, double>(boost::cnv::lexical_cast()),
288 local::to_str<std::string, double>(boost::cnv::printf()(arg::precision = 6)),
289 local::to_str<std::string, double>(boost::cnv::cstream()(arg::precision = 6)));
290
291 printf("str-to-user-type: lcast/stream/strtol=%.2f/%.2f/%.2f seconds.\n",
292 performance_str_to_type(boost::cnv::lexical_cast()),
293 performance_str_to_type(boost::cnv::cstream()),
294 performance_str_to_type(boost::cnv::strtol()));
295 printf("user-type-to-str: lcast/stream/strtol=%.2f/%.2f/%.2f seconds.\n",
296 performance_type_to_str(boost::cnv::lexical_cast()),
297 performance_type_to_str(boost::cnv::cstream()),
298 performance_type_to_str(boost::cnv::strtol()));
299
300 //[small_string_results
301 printf("strtol int-to std::string/small-string: %.2f/%.2f seconds.\n",
302 local::to_str<std::string, int>(boost::cnv::strtol()),
303 local::to_str< my_string, int>(boost::cnv::strtol()));
304 printf("spirit int-to std::string/small-string: %.2f/%.2f seconds.\n",
305 local::to_str<std::string, int>(boost::cnv::spirit()),
306 local::to_str< my_string, int>(boost::cnv::spirit()));
307 printf("stream int-to std::string/small-string: %.2f/%.2f seconds.\n",
308 local::to_str<std::string, int>(boost::cnv::cstream()),
309 local::to_str< my_string, int>(boost::cnv::cstream()));
310 //]
311 performance_comparative(raw_str_to_int_spirit(), boost::cnv::spirit(), "spirit");
312 performance_comparative(raw_str_to_int_lxcast(), boost::cnv::lexical_cast(), "lxcast");
313
314 return boost::report_errors();
315 }
316
317 #endif