]>
Commit | Line | Data |
---|---|---|
11fdf7f2 | 1 | // |
92f5a8d4 | 2 | // Copyright (c) 2017, 2018 James E. King III |
11fdf7f2 TL |
3 | // |
4 | // Distributed under the Boost Software License, Version 1.0. | |
5 | // (See accompanying file LICENSE_1_0.txt or copy at | |
92f5a8d4 | 6 | // https://www.boost.org/LICENSE_1_0.txt) |
11fdf7f2 TL |
7 | // |
8 | // benchmark for random_generators in different forms | |
9 | // | |
10 | ||
11 | #include <boost/core/ignore_unused.hpp> | |
12 | #include <boost/timer/timer.hpp> | |
13 | #include <boost/predef/os.h> | |
14 | #include <boost/uuid/random_generator.hpp> | |
15 | #include <boost/uuid/uuid.hpp> | |
16 | #include <boost/uuid/uuid_io.hpp> | |
17 | #include <iostream> | |
18 | #include <limits> | |
19 | ||
92f5a8d4 TL |
20 | #if !defined(BOOST_NO_STRESS_TEST) |
21 | // must be a Valgrind, UBsan, or other stressful job | |
11fdf7f2 TL |
22 | #define AVG_LOOPS 1 |
23 | #define GEN_LOOPS 10 | |
24 | #define REUSE_LOOPS 100 | |
25 | #else | |
26 | #define AVG_LOOPS 10 | |
27 | #define GEN_LOOPS 10000 | |
28 | #define REUSE_LOOPS 1000000 | |
29 | #endif | |
30 | ||
31 | template<class Generator> | |
32 | void auto_timed_generator_ctordtor(size_t count) | |
33 | { | |
34 | boost::timer::auto_cpu_timer t; | |
35 | for (size_t i = 0; i < count; ++i) | |
36 | { | |
37 | Generator gen; | |
38 | boost::ignore_unused(gen); | |
39 | } | |
40 | } | |
41 | ||
42 | template<class Generator> | |
43 | void auto_timed_generator_novel(size_t count) | |
44 | { | |
45 | boost::timer::auto_cpu_timer t; | |
46 | for (size_t i = 0; i < count; ++i) | |
47 | { | |
48 | Generator gen; | |
49 | boost::uuids::uuid u = gen(); | |
50 | boost::ignore_unused(u); | |
51 | } | |
52 | } | |
53 | ||
54 | template<class Generator> | |
55 | void auto_timed_generator_reuse(size_t count) | |
56 | { | |
57 | Generator gen; | |
58 | { | |
59 | boost::timer::auto_cpu_timer t; | |
60 | for (size_t i = 0; i < count; ++i) | |
61 | { | |
62 | boost::uuids::uuid u = gen(); | |
63 | boost::ignore_unused(u); | |
64 | } | |
65 | } | |
66 | } | |
67 | ||
68 | template<class Generator> | |
69 | boost::timer::cpu_times timed_generator(size_t count) | |
70 | { | |
71 | boost::timer::cpu_timer t; | |
72 | Generator gen; | |
73 | for (size_t i = 0; i < count; ++i) | |
74 | { | |
75 | boost::uuids::uuid u = gen(); | |
76 | boost::ignore_unused(u); | |
77 | } | |
78 | return t.elapsed(); | |
79 | } | |
80 | ||
81 | int main(int, char*[]) | |
82 | { | |
83 | std::cout << "Operating system entropy provider: " | |
84 | << boost::uuids::detail::random_provider().name() << std::endl; | |
85 | ||
92f5a8d4 | 86 | #if !defined(BOOST_NO_STRESS_TEST) |
11fdf7f2 TL |
87 | |
88 | // | |
89 | // Determine the cutoff point where it is more wall-clock efficient to | |
90 | // use the bulk generator over the standard one. | |
91 | // | |
92 | ||
93 | std::cout << "Calculating the number of operator() calls where random_generator" << std::endl; | |
94 | std::cout << "is more efficient than random_generator_mt19937..." << std::endl; | |
95 | std::cout << "at "; | |
96 | bool asterisk = false; | |
97 | size_t minn = (std::numeric_limits<size_t>::max)(); | |
98 | size_t summ = 0; | |
99 | size_t maxx = 0; | |
100 | for (size_t i = 0; i < AVG_LOOPS + 1; ++i) // the first loop is thrown away, see below | |
101 | { | |
102 | size_t answer = 0; | |
103 | for (size_t count = 1; !answer; ++count) | |
104 | { | |
105 | boost::timer::cpu_times standard = timed_generator<boost::uuids::random_generator>(count); | |
106 | boost::timer::cpu_times pseudo = timed_generator<boost::uuids::random_generator_mt19937>(count); | |
107 | if (standard.wall > pseudo.wall) | |
108 | { | |
109 | answer = count; | |
110 | } | |
111 | else if (count >= 999) | |
112 | { | |
113 | std::cout << "*"; | |
114 | asterisk = true; | |
115 | answer = count; | |
116 | } | |
117 | } | |
118 | ||
119 | // throw away the first answer in case it contains time related to loading | |
120 | // or initializing the crypto library being used | |
121 | if (i > 0) | |
122 | { | |
123 | if (minn > answer) minn = answer; | |
124 | if (maxx < answer) maxx = answer; | |
125 | summ += answer; | |
126 | std::cout << answer << " " << std::flush; | |
127 | } | |
128 | } | |
129 | if (asterisk) | |
130 | { | |
131 | std::cout << "* = limited to 999" << std::endl; | |
132 | } | |
133 | std::cout << "calls to operator()" << std::endl; | |
134 | size_t answer = summ / AVG_LOOPS; | |
135 | std::cout << "For this platform, random_generator_mt19937 outperforms " | |
136 | << "random_generator after " << answer << " generations (min " << minn << " / max " << maxx << ")." | |
137 | << std::endl; | |
138 | std::cout << std::endl; | |
139 | ||
140 | #endif | |
141 | ||
142 | // | |
143 | // Measure ctor/dtor of both | |
144 | // | |
145 | std::cout << "Construction/destruction time for random_generator " | |
146 | << "(" << GEN_LOOPS << " iterations): " << std::endl; | |
147 | auto_timed_generator_ctordtor<boost::uuids::random_generator>(GEN_LOOPS); | |
148 | std::cout << std::endl; | |
149 | ||
150 | std::cout << "Construction/destruction time for random_generator_mt19937 " | |
151 | << "(" << GEN_LOOPS << " iterations): " << std::endl; | |
152 | auto_timed_generator_ctordtor<boost::uuids::random_generator_mt19937>(GEN_LOOPS); | |
153 | std::cout << std::endl; | |
154 | ||
155 | // | |
156 | // Two common use cases: | |
157 | // | |
158 | // Use an OS provided RNG which has no seed code but is slower to reuse | |
159 | // Use a PRNG which is expensive to seed once but fast to reuse | |
160 | // | |
161 | // Measure the default selections of the library | |
162 | // | |
163 | ||
164 | std::cout << "Benchmark boost::uuids::random_generator " | |
165 | << "(reused for " << REUSE_LOOPS << " loops):" << std::endl; | |
166 | auto_timed_generator_reuse<boost::uuids::random_generator>(REUSE_LOOPS); | |
167 | std::cout << std::endl; | |
168 | ||
169 | std::cout << "Benchmark boost::uuids::random_generator_mt19937 " | |
170 | << "(reused for " << REUSE_LOOPS << " loops):" << std::endl; | |
171 | auto_timed_generator_reuse<boost::uuids::random_generator_mt19937>(REUSE_LOOPS); | |
172 | std::cout << std::endl; | |
173 | ||
174 | std::cout << "Benchmark boost::uuids::random_generator " | |
175 | << "(new generator each loop for " << GEN_LOOPS << " loops):" << std::endl; | |
176 | auto_timed_generator_novel<boost::uuids::random_generator>(GEN_LOOPS); | |
177 | std::cout << std::endl; | |
178 | ||
179 | std::cout << "Benchmark boost::uuids::random_generator_mt19937 " | |
180 | << "(new generator each loop for " << GEN_LOOPS << " loops):" << std::endl; | |
181 | auto_timed_generator_novel<boost::uuids::random_generator_mt19937>(GEN_LOOPS); | |
182 | std::cout << std::endl; | |
183 | ||
184 | return 0; | |
185 | } | |
186 | ||
187 |