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.
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
));
23 benchmark::BenchRunner::RunAll(benchmark::duration elapsedTimeForOne
)
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
);
36 bool benchmark::State::KeepRunning()
38 if (count
& countMask
) {
46 lastTime
= beginTime
= now
= clock::now();
47 lastCycles
= beginCycles
= nowCycles
= perf_cpucycles();
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);
67 minTime
= duration::max();
68 maxTime
= duration::zero();
69 minCycles
= std::numeric_limits
<uint64_t>::max();
70 maxCycles
= std::numeric_limits
<uint64_t>::min();
73 if (elapsed
*16 < maxElapsed
) {
74 uint64_t newCountMask
= ((countMask
<<1)|1) & ((1LL<<60)-1);
75 if ((count
& newCountMask
)==0) {
76 countMask
= newCountMask
;
81 lastCycles
= nowCycles
;
84 if (now
- beginTime
< maxElapsed
) return true; // Keep going
88 assert(count
!= 0 && "count == 0 => (now == 0 && beginTime == 0) => return above");
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));