1 /************************************************************************************
2 *                                                                                   *
3 *   Copyright (c) 2014 - 2018 Axel Menzel <info@rttr.org>                           *
4 *                                                                                   *
5 *   This file is part of RTTR (Run Time Type Reflection)                            *
6 *   License: MIT License                                                            *
7 *                                                                                   *
8 *   Permission is hereby granted, free of charge, to any person obtaining           *
9 *   a copy of this software and associated documentation files (the "Software"),    *
10 *   to deal in the Software without restriction, including without limitation       *
11 *   the rights to use, copy, modify, merge, publish, distribute, sublicense,        *
12 *   and/or sell copies of the Software, and to permit persons to whom the           *
13 *   Software is furnished to do so, subject to the following conditions:            *
14 *                                                                                   *
15 *   The above copyright notice and this permission notice shall be included in      *
16 *   all copies or substantial portions of the Software.                             *
17 *                                                                                   *
18 *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR      *
19 *   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,        *
20 *   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE     *
21 *   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER          *
22 *   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,   *
23 *   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE   *
24 *   SOFTWARE.                                                                       *
25 *                                                                                   *
26 *************************************************************************************/
27 
28 #include <rttr/type>
29 #include <rttr/registration>
30 
31 #include <nonius/nonius.h++>
32 #include <nonius/html_group_reporter.h>
33 
34 #include <locale>
35 
36 /////////////////////////////////////////////////////////////////////////////////////////
37 /////////////////////////////////////////////////////////////////////////////////////////
38 /////////////////////////////////////////////////////////////////////////////////////////
39 
setup_integer()40 static int setup_integer()
41 {
42     return 12345;
43 }
44 
45 /////////////////////////////////////////////////////////////////////////////////////////
46 
setup_float()47 static float setup_float()
48 {
49     return 123.12345f;
50 }
51 
52 /////////////////////////////////////////////////////////////////////////////////////////
53 
setup_double()54 static double setup_double()
55 {
56     return 123456.123456;
57 }
58 
59 /////////////////////////////////////////////////////////////////////////////////////////
60 
setup_bool()61 static bool setup_bool()
62 {
63     return true;
64 }
65 
66 /////////////////////////////////////////////////////////////////////////////////////////
67 
setup_string_integer()68 static std::string setup_string_integer()
69 {
70     return std::string("12345");
71 }
72 
73 /////////////////////////////////////////////////////////////////////////////////////////
74 
setup_string_float()75 static std::string setup_string_float()
76 {
77     return std::string("123.12345");
78 }
79 
80 /////////////////////////////////////////////////////////////////////////////////////////
81 
setup_string_double()82 static std::string setup_string_double()
83 {
84     return std::string("123456.123456");
85 }
86 
87 /////////////////////////////////////////////////////////////////////////////////////////
88 
setup_string_bool()89 static std::string setup_string_bool()
90 {
91     return std::string("1");
92 }
93 
94 
95 /////////////////////////////////////////////////////////////////////////////////////////
96 /////////////////////////////////////////////////////////////////////////////////////////
97 /////////////////////////////////////////////////////////////////////////////////////////
98 
bench_native_int_to_string()99 nonius::benchmark bench_native_int_to_string()
100 {
101     return nonius::benchmark("native", [](nonius::chronometer meter)
102     {
103         int var = setup_integer();
104         std::string result;
105         meter.measure([&]()
106         {
107             result = std::to_string(var);
108         });
109     });
110 }
111 
112 /////////////////////////////////////////////////////////////////////////////////////////
113 
bench_variant_int_to_string()114 nonius::benchmark bench_variant_int_to_string()
115 {
116     return nonius::benchmark("rttr::variant", [](nonius::chronometer meter)
117     {
118         rttr::variant var = setup_integer();
119         std::string result;
120         meter.measure([&]()
121         {
122             result = var.to_string();
123         });
124     });
125 }
126 
127 /////////////////////////////////////////////////////////////////////////////////////////
128 /////////////////////////////////////////////////////////////////////////////////////////
129 
bench_native_string_to_int()130 nonius::benchmark bench_native_string_to_int()
131 {
132     return nonius::benchmark("native", [](nonius::chronometer meter)
133     {
134         std::string number_string = setup_string_integer();
135         int result = 0;
136         meter.measure([&]()
137         {
138             std::size_t pos = 0;
139             result = std::stoi(number_string, &pos);
140         });
141     });
142 }
143 
144 /////////////////////////////////////////////////////////////////////////////////////////
145 
bench_variant_string_to_int()146 nonius::benchmark bench_variant_string_to_int()
147 {
148     return nonius::benchmark("rttr::variant", [](nonius::chronometer meter)
149     {
150         rttr::variant var = setup_string_integer();
151         int result = 0;
152         meter.measure([&]()
153         {
154             result = var.to_int();
155         });
156     });
157 }
158 
159 /////////////////////////////////////////////////////////////////////////////////////////
160 /////////////////////////////////////////////////////////////////////////////////////////
161 /////////////////////////////////////////////////////////////////////////////////////////
162 
bench_native_float_to_string()163 nonius::benchmark bench_native_float_to_string()
164 {
165     return nonius::benchmark("native", [](nonius::chronometer meter)
166     {
167         float var = setup_float();
168         std::string result;
169         meter.measure([&]()
170         {
171             result = std::to_string(var);
172         });
173     });
174 }
175 
176 /////////////////////////////////////////////////////////////////////////////////////////
177 
bench_variant_float_to_string()178 nonius::benchmark bench_variant_float_to_string()
179 {
180     return nonius::benchmark("rttr::variant", [](nonius::chronometer meter)
181     {
182         rttr::variant var = setup_float();
183         std::string result;
184         meter.measure([&]()
185         {
186             result = var.to_string();
187         });
188     });
189 }
190 
191 /////////////////////////////////////////////////////////////////////////////////////////
192 /////////////////////////////////////////////////////////////////////////////////////////
193 
bench_native_string_to_float()194 nonius::benchmark bench_native_string_to_float()
195 {
196     return nonius::benchmark("native", [](nonius::chronometer meter)
197     {
198         std::string number_string = setup_string_float();
199         float result;
200         meter.measure([&]()
201         {
202             std::size_t pos = 0;
203             result = std::stof(number_string, &pos);
204         });
205     });
206 }
207 
208 /////////////////////////////////////////////////////////////////////////////////////////
209 
bench_variant_string_to_float()210 nonius::benchmark bench_variant_string_to_float()
211 {
212     return nonius::benchmark("rttr::variant", [](nonius::chronometer meter)
213     {
214         rttr::variant var = setup_string_float();
215         float result = 0.0f;
216         meter.measure([&]()
217         {
218             result = var.to_float();
219         });
220     });
221 }
222 
223 /////////////////////////////////////////////////////////////////////////////////////////
224 /////////////////////////////////////////////////////////////////////////////////////////
225 /////////////////////////////////////////////////////////////////////////////////////////
226 
bench_native_double_to_string()227 nonius::benchmark bench_native_double_to_string()
228 {
229     return nonius::benchmark("native", [](nonius::chronometer meter)
230     {
231         double var = setup_double();
232         std::string result;
233         meter.measure([&]()
234         {
235             result = std::to_string(var);
236         });
237     });
238 }
239 
240 /////////////////////////////////////////////////////////////////////////////////////////
241 
bench_variant_double_to_string()242 nonius::benchmark bench_variant_double_to_string()
243 {
244     return nonius::benchmark("rttr::variant", [](nonius::chronometer meter)
245     {
246         rttr::variant var = setup_double();
247         std::string result;
248         meter.measure([&]()
249         {
250             result = var.to_string();
251         });
252     });
253 }
254 
255 /////////////////////////////////////////////////////////////////////////////////////////
256 /////////////////////////////////////////////////////////////////////////////////////////
257 
bench_native_string_to_double()258 nonius::benchmark bench_native_string_to_double()
259 {
260     return nonius::benchmark("native", [](nonius::chronometer meter)
261     {
262         std::string number_string = setup_string_double();
263         double result;
264         meter.measure([&]()
265         {
266             std::size_t pos = 0;
267             result = std::stod(number_string, &pos);
268         });
269     });
270 }
271 
272 /////////////////////////////////////////////////////////////////////////////////////////
273 
bench_variant_string_to_double()274 nonius::benchmark bench_variant_string_to_double()
275 {
276     return nonius::benchmark("rttr::variant", [](nonius::chronometer meter)
277     {
278         rttr::variant var = setup_string_double();
279         double result = 0.0;
280         meter.measure([&]()
281         {
282             result = var.to_double();
283         });
284     });
285 }
286 
287 /////////////////////////////////////////////////////////////////////////////////////////
288 /////////////////////////////////////////////////////////////////////////////////////////
289 /////////////////////////////////////////////////////////////////////////////////////////
290 
bench_native_bool_to_string()291 nonius::benchmark bench_native_bool_to_string()
292 {
293     return nonius::benchmark("native", [](nonius::chronometer meter)
294     {
295         bool value = setup_bool();
296         std::string result;
297         meter.measure([&]()
298         {
299             result = value ? std::string("true") : std::string("false");
300         });
301     });
302 }
303 
304 /////////////////////////////////////////////////////////////////////////////////////////
305 
bench_variant_bool_to_string()306 nonius::benchmark bench_variant_bool_to_string()
307 {
308     return nonius::benchmark("rttr::variant", [](nonius::chronometer meter)
309     {
310         rttr::variant var = setup_bool();
311         std::string result;
312         meter.measure([&]()
313         {
314             result = var.to_string();
315         });
316     });
317 }
318 
319 /////////////////////////////////////////////////////////////////////////////////////////
320 /////////////////////////////////////////////////////////////////////////////////////////
321 
string_to_bool(std::string text)322 static bool string_to_bool(std::string text)
323 {
324     std::transform(text.cbegin(), text.cend(), text.begin(), ::tolower);
325     text.erase( std::remove_if( text.begin(), text.end(), []( char ch ) { return std::isspace<char>( ch, std::locale::classic() ); } ), text.end() );
326 
327     return !(text == "false" || text == "0" || text.empty());
328 }
329 
330 /////////////////////////////////////////////////////////////////////////////////////////
331 
bench_native_string_to_bool()332 nonius::benchmark bench_native_string_to_bool()
333 {
334     return nonius::benchmark("native", [](nonius::chronometer meter)
335     {
336         std::string bool_string = setup_string_bool();
337         bool result = false;
338         meter.measure([&]()
339         {
340             result = string_to_bool(bool_string);
341         });
342     });
343 }
344 
345 /////////////////////////////////////////////////////////////////////////////////////////
346 
bench_variant_string_to_bool()347 nonius::benchmark bench_variant_string_to_bool()
348 {
349     return nonius::benchmark("rttr::variant", [](nonius::chronometer meter)
350     {
351         rttr::variant var = setup_string_bool();
352         bool result = false;
353         meter.measure([&]()
354         {
355             result = var.to_bool();
356         });
357     });
358 }
359 
360 /////////////////////////////////////////////////////////////////////////////////////////
361 /////////////////////////////////////////////////////////////////////////////////////////
362 /////////////////////////////////////////////////////////////////////////////////////////
363 
bench_variant_conversion()364 void bench_variant_conversion()
365 {
366     nonius::configuration cfg;
367     cfg.title = "rttr::variant conversion";
368 
369     nonius::html_group_reporter reporter;
370     reporter.set_output_file("benchmark_variant_conversion.html");
371 
372     //////////////////////////////////
373 
374     reporter.set_current_group_name("int to string", "Converts an integer number to a <code>std::string</code>:<br><pre>rttr::variant var = 12345;\nvar.to_string();</pre>");
375 
376     nonius::benchmark benchmarks_group_1[] = { bench_native_int_to_string(),
377                                                bench_variant_int_to_string()
378                                               };
379 
380     nonius::go(cfg, std::begin(benchmarks_group_1), std::end(benchmarks_group_1), reporter);
381 
382     //////////////////////////////////
383 
384     reporter.set_current_group_name("string to int", "Converts a <code>std::string</code> to an integer:<br><pre>rttr::variant var = std::string(\"12345\");\nvar.to_int()</pre>");
385 
386     nonius::benchmark benchmarks_group_2[] = { bench_native_string_to_int(),
387                                                bench_variant_string_to_int()
388                                               };
389 
390     nonius::go(cfg, std::begin(benchmarks_group_2), std::end(benchmarks_group_2), reporter);
391 
392     //////////////////////////////////
393 
394     reporter.set_current_group_name("float to string", "Converts a floating point number to a <code>std::string</code>:<br><pre>rttr::variant var = 123.12345f;\nvar.to_string();</pre>");
395 
396     nonius::benchmark benchmarks_group_3[] = { bench_native_string_to_float(),
397                                                bench_variant_string_to_float()
398                                               };
399 
400     nonius::go(cfg, std::begin(benchmarks_group_3), std::end(benchmarks_group_3), reporter);
401 
402     //////////////////////////////////
403 
404     reporter.set_current_group_name("string to float", "Converts a <code>std::string</code> to a floating point number:<br><pre>rttr::variant var = std::string(\"123.12345\");\nvar.to_float().");
405 
406     nonius::benchmark benchmarks_group_4[] = { bench_native_float_to_string(),
407                                                bench_variant_float_to_string()
408                                               };
409 
410     nonius::go(cfg, std::begin(benchmarks_group_4), std::end(benchmarks_group_4), reporter);
411 
412     //////////////////////////////////
413 
414     reporter.set_current_group_name("double to string", "Converts a double number to a <code>std::string</code>:<br><pre>rttr::variant var = 123456.123456;\nvar.to_string();</pre>");
415 
416     nonius::benchmark benchmarks_group_5[] = { bench_native_string_to_double(),
417                                                bench_variant_string_to_double()
418                                               };
419 
420     nonius::go(cfg, std::begin(benchmarks_group_5), std::end(benchmarks_group_5), reporter);
421 
422     //////////////////////////////////
423 
424     reporter.set_current_group_name("string to double", "Converts a <code>std::string</code> to a double number:<br><pre>rttr::variant var = std::string(\"123456.123456\");\nvar.to_double();</pre>");
425 
426     nonius::benchmark benchmarks_group_6[] = { bench_native_double_to_string(),
427                                                bench_variant_double_to_string()
428                                               };
429 
430     nonius::go(cfg, std::begin(benchmarks_group_6), std::end(benchmarks_group_6), reporter);
431 
432     //////////////////////////////////
433 
434     reporter.set_current_group_name("bool to string", "Converts a bool number to a <code>std::string</code>:<br><pre>rttr::variant var = 123456.123456;\nvar.to_string();</pre>");
435 
436     nonius::benchmark benchmarks_group_7[] = { bench_native_string_to_bool(),
437                                                bench_variant_string_to_bool()
438                                               };
439 
440     nonius::go(cfg, std::begin(benchmarks_group_7), std::end(benchmarks_group_7), reporter);
441 
442     //////////////////////////////////
443 
444     reporter.set_current_group_name("string to bool", "Converts a <code>std::string</code> to a bool number:<br><pre>rttr::variant var = std::string(\"123456.123456\");\nvar.to_bool();</pre>");
445 
446     nonius::benchmark benchmarks_group_8[] = { bench_native_bool_to_string(),
447                                                bench_variant_bool_to_string()
448                                               };
449 
450     nonius::go(cfg, std::begin(benchmarks_group_8), std::end(benchmarks_group_8), reporter);
451 
452     //////////////////////////////////
453 
454     reporter.generate_report();
455 }
456 
457 /////////////////////////////////////////////////////////////////////////////////////////
458