Merge #11667: Add scripts to dumpwallet RPC
[bitcoinplatinum.git] / src / bench / bench.cpp
blob148245281469090a31e13f3e02fb66a57d0fe511
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/bench.h>
6 #include <bench/perf.h>
8 #include <assert.h>
9 #include <iostream>
10 #include <iomanip>
12 benchmark::BenchRunner::BenchmarkMap &benchmark::BenchRunner::benchmarks() {
13 static std::map<std::string, benchmark::BenchFunction> benchmarks_map;
14 return benchmarks_map;
17 benchmark::BenchRunner::BenchRunner(std::string name, benchmark::BenchFunction func)
19 benchmarks().insert(std::make_pair(name, func));
22 void
23 benchmark::BenchRunner::RunAll(benchmark::duration elapsedTimeForOne)
25 perf_init();
26 if (std::ratio_less_equal<benchmark::clock::period, std::micro>::value) {
27 std::cerr << "WARNING: Clock precision is worse than microsecond - benchmarks may be less accurate!\n";
29 std::cout << "#Benchmark" << "," << "count" << "," << "min(ns)" << "," << "max(ns)" << "," << "average(ns)" << ","
30 << "min_cycles" << "," << "max_cycles" << "," << "average_cycles" << "\n";
32 for (const auto &p: benchmarks()) {
33 State state(p.first, elapsedTimeForOne);
34 p.second(state);
36 perf_fini();
39 bool benchmark::State::KeepRunning()
41 if (count & countMask) {
42 ++count;
43 return true;
45 time_point now;
47 uint64_t nowCycles;
48 if (count == 0) {
49 lastTime = beginTime = now = clock::now();
50 lastCycles = beginCycles = nowCycles = perf_cpucycles();
52 else {
53 now = clock::now();
54 auto elapsed = now - lastTime;
55 auto elapsedOne = elapsed / (countMask + 1);
56 if (elapsedOne < minTime) minTime = elapsedOne;
57 if (elapsedOne > maxTime) maxTime = elapsedOne;
59 // We only use relative values, so don't have to handle 64-bit wrap-around specially
60 nowCycles = perf_cpucycles();
61 uint64_t elapsedOneCycles = (nowCycles - lastCycles) / (countMask + 1);
62 if (elapsedOneCycles < minCycles) minCycles = elapsedOneCycles;
63 if (elapsedOneCycles > maxCycles) maxCycles = elapsedOneCycles;
65 if (elapsed*128 < maxElapsed) {
66 // If the execution was much too fast (1/128th of maxElapsed), increase the count mask by 8x and restart timing.
67 // The restart avoids including the overhead of this code in the measurement.
68 countMask = ((countMask<<3)|7) & ((1LL<<60)-1);
69 count = 0;
70 minTime = duration::max();
71 maxTime = duration::zero();
72 minCycles = std::numeric_limits<uint64_t>::max();
73 maxCycles = std::numeric_limits<uint64_t>::min();
74 return true;
76 if (elapsed*16 < maxElapsed) {
77 uint64_t newCountMask = ((countMask<<1)|1) & ((1LL<<60)-1);
78 if ((count & newCountMask)==0) {
79 countMask = newCountMask;
83 lastTime = now;
84 lastCycles = nowCycles;
85 ++count;
87 if (now - beginTime < maxElapsed) return true; // Keep going
89 --count;
91 assert(count != 0 && "count == 0 => (now == 0 && beginTime == 0) => return above");
93 // Output results
94 // Duration casts are only necessary here because hardware with sub-nanosecond clocks
95 // will lose precision.
96 int64_t min_elapsed = std::chrono::duration_cast<std::chrono::nanoseconds>(minTime).count();
97 int64_t max_elapsed = std::chrono::duration_cast<std::chrono::nanoseconds>(maxTime).count();
98 int64_t avg_elapsed = std::chrono::duration_cast<std::chrono::nanoseconds>((now-beginTime)/count).count();
99 int64_t averageCycles = (nowCycles-beginCycles)/count;
100 std::cout << std::fixed << std::setprecision(15) << name << "," << count << "," << min_elapsed << "," << max_elapsed << "," << avg_elapsed << ","
101 << minCycles << "," << maxCycles << "," << averageCycles << "\n";
102 std::cout.copyfmt(std::ios(nullptr));
104 return false;