Replace boost::function with std::function (C++11)
[bitcoinplatinum.git] / src / bench / bench.cpp
blob33631d2d150545196a1a559e5b40a140b8f00c9e
1 // Copyright (c) 2015-2016 The Bitcoin Core developers
2 // Distributed under the MIT software license, see the accompanying
3 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
5 #include "bench.h"
6 #include "perf.h"
8 #include <assert.h>
9 #include <iostream>
10 #include <iomanip>
11 #include <sys/time.h>
13 benchmark::BenchRunner::BenchmarkMap &benchmark::BenchRunner::benchmarks() {
14 static std::map<std::string, benchmark::BenchFunction> benchmarks_map;
15 return benchmarks_map;
18 static double gettimedouble(void) {
19 struct timeval tv;
20 gettimeofday(&tv, NULL);
21 return tv.tv_usec * 0.000001 + tv.tv_sec;
24 benchmark::BenchRunner::BenchRunner(std::string name, benchmark::BenchFunction func)
26 benchmarks().insert(std::make_pair(name, func));
29 void
30 benchmark::BenchRunner::RunAll(double elapsedTimeForOne)
32 perf_init();
33 std::cout << "#Benchmark" << "," << "count" << "," << "min" << "," << "max" << "," << "average" << ","
34 << "min_cycles" << "," << "max_cycles" << "," << "average_cycles" << "\n";
36 for (const auto &p: benchmarks()) {
37 State state(p.first, elapsedTimeForOne);
38 p.second(state);
40 perf_fini();
43 bool benchmark::State::KeepRunning()
45 if (count & countMask) {
46 ++count;
47 return true;
49 double now;
50 uint64_t nowCycles;
51 if (count == 0) {
52 lastTime = beginTime = now = gettimedouble();
53 lastCycles = beginCycles = nowCycles = perf_cpucycles();
55 else {
56 now = gettimedouble();
57 double elapsed = now - lastTime;
58 double elapsedOne = elapsed * countMaskInv;
59 if (elapsedOne < minTime) minTime = elapsedOne;
60 if (elapsedOne > maxTime) maxTime = elapsedOne;
62 // We only use relative values, so don't have to handle 64-bit wrap-around specially
63 nowCycles = perf_cpucycles();
64 uint64_t elapsedOneCycles = (nowCycles - lastCycles) * countMaskInv;
65 if (elapsedOneCycles < minCycles) minCycles = elapsedOneCycles;
66 if (elapsedOneCycles > maxCycles) maxCycles = elapsedOneCycles;
68 if (elapsed*128 < maxElapsed) {
69 // If the execution was much too fast (1/128th of maxElapsed), increase the count mask by 8x and restart timing.
70 // The restart avoids including the overhead of this code in the measurement.
71 countMask = ((countMask<<3)|7) & ((1LL<<60)-1);
72 countMaskInv = 1./(countMask+1);
73 count = 0;
74 minTime = std::numeric_limits<double>::max();
75 maxTime = std::numeric_limits<double>::min();
76 minCycles = std::numeric_limits<uint64_t>::max();
77 maxCycles = std::numeric_limits<uint64_t>::min();
78 return true;
80 if (elapsed*16 < maxElapsed) {
81 uint64_t newCountMask = ((countMask<<1)|1) & ((1LL<<60)-1);
82 if ((count & newCountMask)==0) {
83 countMask = newCountMask;
84 countMaskInv = 1./(countMask+1);
88 lastTime = now;
89 lastCycles = nowCycles;
90 ++count;
92 if (now - beginTime < maxElapsed) return true; // Keep going
94 --count;
96 assert(count != 0 && "count == 0 => (now == 0 && beginTime == 0) => return above");
98 // Output results
99 double average = (now-beginTime)/count;
100 int64_t averageCycles = (nowCycles-beginCycles)/count;
101 std::cout << std::fixed << std::setprecision(15) << name << "," << count << "," << minTime << "," << maxTime << "," << average << ","
102 << minCycles << "," << maxCycles << "," << averageCycles << "\n";
104 return false;