Use unique_ptr for pdbCopy (Db) and fix potential memory leak
[bitcoinplatinum.git] / src / bench / bench.cpp
blobdd4ba5ab0ee2389c8b5cd2d4feac850b7669b4a8
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>
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 std::cout << "#Benchmark" << "," << "count" << "," << "min(ns)" << "," << "max(ns)" << "," << "average(ns)" << ","
27 << "min_cycles" << "," << "max_cycles" << "," << "average_cycles" << "\n";
29 for (const auto &p: benchmarks()) {
30 State state(p.first, elapsedTimeForOne);
31 p.second(state);
33 perf_fini();
36 bool benchmark::State::KeepRunning()
38 if (count & countMask) {
39 ++count;
40 return true;
42 time_point now;
44 uint64_t nowCycles;
45 if (count == 0) {
46 lastTime = beginTime = now = clock::now();
47 lastCycles = beginCycles = nowCycles = perf_cpucycles();
49 else {
50 now = clock::now();
51 auto elapsed = now - lastTime;
52 auto elapsedOne = elapsed / (countMask + 1);
53 if (elapsedOne < minTime) minTime = elapsedOne;
54 if (elapsedOne > maxTime) maxTime = elapsedOne;
56 // We only use relative values, so don't have to handle 64-bit wrap-around specially
57 nowCycles = perf_cpucycles();
58 uint64_t elapsedOneCycles = (nowCycles - lastCycles) / (countMask + 1);
59 if (elapsedOneCycles < minCycles) minCycles = elapsedOneCycles;
60 if (elapsedOneCycles > maxCycles) maxCycles = elapsedOneCycles;
62 if (elapsed*128 < maxElapsed) {
63 // If the execution was much too fast (1/128th of maxElapsed), increase the count mask by 8x and restart timing.
64 // The restart avoids including the overhead of this code in the measurement.
65 countMask = ((countMask<<3)|7) & ((1LL<<60)-1);
66 count = 0;
67 minTime = duration::max();
68 maxTime = duration::zero();
69 minCycles = std::numeric_limits<uint64_t>::max();
70 maxCycles = std::numeric_limits<uint64_t>::min();
71 return true;
73 if (elapsed*16 < maxElapsed) {
74 uint64_t newCountMask = ((countMask<<1)|1) & ((1LL<<60)-1);
75 if ((count & newCountMask)==0) {
76 countMask = newCountMask;
80 lastTime = now;
81 lastCycles = nowCycles;
82 ++count;
84 if (now - beginTime < maxElapsed) return true; // Keep going
86 --count;
88 assert(count != 0 && "count == 0 => (now == 0 && beginTime == 0) => return above");
90 // Output results
91 // Duration casts are only necessary here because hardware with sub-nanosecond clocks
92 // will lose precision.
93 int64_t min_elapsed = std::chrono::duration_cast<std::chrono::nanoseconds>(minTime).count();
94 int64_t max_elapsed = std::chrono::duration_cast<std::chrono::nanoseconds>(maxTime).count();
95 int64_t avg_elapsed = std::chrono::duration_cast<std::chrono::nanoseconds>((now-beginTime)/count).count();
96 int64_t averageCycles = (nowCycles-beginCycles)/count;
97 std::cout << std::fixed << std::setprecision(15) << name << "," << count << "," << min_elapsed << "," << max_elapsed << "," << avg_elapsed << ","
98 << minCycles << "," << maxCycles << "," << averageCycles << "\n";
99 std::cout.copyfmt(std::ios(nullptr));
101 return false;