summaryrefslogtreecommitdiffstats
path: root/src/boost/libs/uuid/test/test_bench_random.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/boost/libs/uuid/test/test_bench_random.cpp')
-rw-r--r--src/boost/libs/uuid/test/test_bench_random.cpp187
1 files changed, 187 insertions, 0 deletions
diff --git a/src/boost/libs/uuid/test/test_bench_random.cpp b/src/boost/libs/uuid/test/test_bench_random.cpp
new file mode 100644
index 000000000..e86f159ee
--- /dev/null
+++ b/src/boost/libs/uuid/test/test_bench_random.cpp
@@ -0,0 +1,187 @@
+//
+// Copyright (c) 2017, 2018 James E. King III
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// https://www.boost.org/LICENSE_1_0.txt)
+//
+// benchmark for random_generators in different forms
+//
+
+#include <boost/core/ignore_unused.hpp>
+#include <boost/timer/timer.hpp>
+#include <boost/predef/os.h>
+#include <boost/uuid/random_generator.hpp>
+#include <boost/uuid/uuid.hpp>
+#include <boost/uuid/uuid_io.hpp>
+#include <iostream>
+#include <limits>
+
+#if !defined(BOOST_NO_STRESS_TEST)
+// must be a Valgrind, UBsan, or other stressful job
+#define AVG_LOOPS 1
+#define GEN_LOOPS 10
+#define REUSE_LOOPS 100
+#else
+#define AVG_LOOPS 10
+#define GEN_LOOPS 10000
+#define REUSE_LOOPS 1000000
+#endif
+
+template<class Generator>
+void auto_timed_generator_ctordtor(size_t count)
+{
+ boost::timer::auto_cpu_timer t;
+ for (size_t i = 0; i < count; ++i)
+ {
+ Generator gen;
+ boost::ignore_unused(gen);
+ }
+}
+
+template<class Generator>
+void auto_timed_generator_novel(size_t count)
+{
+ boost::timer::auto_cpu_timer t;
+ for (size_t i = 0; i < count; ++i)
+ {
+ Generator gen;
+ boost::uuids::uuid u = gen();
+ boost::ignore_unused(u);
+ }
+}
+
+template<class Generator>
+void auto_timed_generator_reuse(size_t count)
+{
+ Generator gen;
+ {
+ boost::timer::auto_cpu_timer t;
+ for (size_t i = 0; i < count; ++i)
+ {
+ boost::uuids::uuid u = gen();
+ boost::ignore_unused(u);
+ }
+ }
+}
+
+template<class Generator>
+boost::timer::cpu_times timed_generator(size_t count)
+{
+ boost::timer::cpu_timer t;
+ Generator gen;
+ for (size_t i = 0; i < count; ++i)
+ {
+ boost::uuids::uuid u = gen();
+ boost::ignore_unused(u);
+ }
+ return t.elapsed();
+}
+
+int main(int, char*[])
+{
+ std::cout << "Operating system entropy provider: "
+ << boost::uuids::detail::random_provider().name() << std::endl;
+
+#if !defined(BOOST_NO_STRESS_TEST)
+
+ //
+ // Determine the cutoff point where it is more wall-clock efficient to
+ // use the bulk generator over the standard one.
+ //
+
+ std::cout << "Calculating the number of operator() calls where random_generator" << std::endl;
+ std::cout << "is more efficient than random_generator_mt19937..." << std::endl;
+ std::cout << "at ";
+ bool asterisk = false;
+ size_t minn = (std::numeric_limits<size_t>::max)();
+ size_t summ = 0;
+ size_t maxx = 0;
+ for (size_t i = 0; i < AVG_LOOPS + 1; ++i) // the first loop is thrown away, see below
+ {
+ size_t answer = 0;
+ for (size_t count = 1; !answer; ++count)
+ {
+ boost::timer::cpu_times standard = timed_generator<boost::uuids::random_generator>(count);
+ boost::timer::cpu_times pseudo = timed_generator<boost::uuids::random_generator_mt19937>(count);
+ if (standard.wall > pseudo.wall)
+ {
+ answer = count;
+ }
+ else if (count >= 999)
+ {
+ std::cout << "*";
+ asterisk = true;
+ answer = count;
+ }
+ }
+
+ // throw away the first answer in case it contains time related to loading
+ // or initializing the crypto library being used
+ if (i > 0)
+ {
+ if (minn > answer) minn = answer;
+ if (maxx < answer) maxx = answer;
+ summ += answer;
+ std::cout << answer << " " << std::flush;
+ }
+ }
+ if (asterisk)
+ {
+ std::cout << "* = limited to 999" << std::endl;
+ }
+ std::cout << "calls to operator()" << std::endl;
+ size_t answer = summ / AVG_LOOPS;
+ std::cout << "For this platform, random_generator_mt19937 outperforms "
+ << "random_generator after " << answer << " generations (min " << minn << " / max " << maxx << ")."
+ << std::endl;
+ std::cout << std::endl;
+
+#endif
+
+ //
+ // Measure ctor/dtor of both
+ //
+ std::cout << "Construction/destruction time for random_generator "
+ << "(" << GEN_LOOPS << " iterations): " << std::endl;
+ auto_timed_generator_ctordtor<boost::uuids::random_generator>(GEN_LOOPS);
+ std::cout << std::endl;
+
+ std::cout << "Construction/destruction time for random_generator_mt19937 "
+ << "(" << GEN_LOOPS << " iterations): " << std::endl;
+ auto_timed_generator_ctordtor<boost::uuids::random_generator_mt19937>(GEN_LOOPS);
+ std::cout << std::endl;
+
+ //
+ // Two common use cases:
+ //
+ // Use an OS provided RNG which has no seed code but is slower to reuse
+ // Use a PRNG which is expensive to seed once but fast to reuse
+ //
+ // Measure the default selections of the library
+ //
+
+ std::cout << "Benchmark boost::uuids::random_generator "
+ << "(reused for " << REUSE_LOOPS << " loops):" << std::endl;
+ auto_timed_generator_reuse<boost::uuids::random_generator>(REUSE_LOOPS);
+ std::cout << std::endl;
+
+ std::cout << "Benchmark boost::uuids::random_generator_mt19937 "
+ << "(reused for " << REUSE_LOOPS << " loops):" << std::endl;
+ auto_timed_generator_reuse<boost::uuids::random_generator_mt19937>(REUSE_LOOPS);
+ std::cout << std::endl;
+
+ std::cout << "Benchmark boost::uuids::random_generator "
+ << "(new generator each loop for " << GEN_LOOPS << " loops):" << std::endl;
+ auto_timed_generator_novel<boost::uuids::random_generator>(GEN_LOOPS);
+ std::cout << std::endl;
+
+ std::cout << "Benchmark boost::uuids::random_generator_mt19937 "
+ << "(new generator each loop for " << GEN_LOOPS << " loops):" << std::endl;
+ auto_timed_generator_novel<boost::uuids::random_generator_mt19937>(GEN_LOOPS);
+ std::cout << std::endl;
+
+ return 0;
+}
+
+