File: test_bench_random.cpp

package info (click to toggle)
boost1.90 1.90.0-2
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 593,156 kB
  • sloc: cpp: 4,190,642; xml: 196,648; python: 34,618; ansic: 23,145; asm: 5,468; sh: 3,776; makefile: 1,161; perl: 1,020; sql: 728; ruby: 676; yacc: 478; java: 77; lisp: 24; csh: 6
file content (185 lines) | stat: -rw-r--r-- 5,759 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
//
// 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()
{
    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;
}