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.
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) {
20 gettimeofday(&tv
, nullptr);
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
));
30 benchmark::BenchRunner::RunAll(double elapsedTimeForOne
)
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
);
43 bool benchmark::State::KeepRunning()
45 if (count
& countMask
) {
52 lastTime
= beginTime
= now
= gettimedouble();
53 lastCycles
= beginCycles
= nowCycles
= perf_cpucycles();
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);
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();
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);
89 lastCycles
= nowCycles
;
92 if (now
- beginTime
< maxElapsed
) return true; // Keep going
96 assert(count
!= 0 && "count == 0 => (now == 0 && beginTime == 0) => return above");
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";
103 std::cout
.copyfmt(std::ios(nullptr));