Raven Core  3.0.0
P2P Digital Currency
bench.cpp
Go to the documentation of this file.
1 // Copyright (c) 2015-2016 The Bitcoin Core developers
2 // Copyright (c) 2017-2019 The Raven Core developers
3 // Distributed under the MIT software license, see the accompanying
4 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
5 
6 #include "bench.h"
7 #include "perf.h"
8 
9 #include <assert.h>
10 #include <iostream>
11 #include <iomanip>
12 #include <sys/time.h>
13 
15  static std::map<std::string, benchmark::BenchFunction> benchmarks_map;
16  return benchmarks_map;
17 }
18 
19 static double gettimedouble(void) {
20  struct timeval tv;
21  gettimeofday(&tv, nullptr);
22  return tv.tv_usec * 0.000001 + tv.tv_sec;
23 }
24 
26 {
27  benchmarks().insert(std::make_pair(name, func));
28 }
29 
30 void
31 benchmark::BenchRunner::RunAll(double elapsedTimeForOne)
32 {
33  perf_init();
34  std::cout << "#Benchmark" << "," << "count" << "," << "min" << "," << "max" << "," << "average" << ","
35  << "min_cycles" << "," << "max_cycles" << "," << "average_cycles" << "\n";
36 
37  for (const auto &p: benchmarks()) {
38  State state(p.first, elapsedTimeForOne);
39  p.second(state);
40  }
41  perf_fini();
42 }
43 
45 {
46  if (count & countMask) {
47  ++count;
48  return true;
49  }
50  double now;
51  uint64_t nowCycles;
52  if (count == 0) {
53  lastTime = beginTime = now = gettimedouble();
54  lastCycles = beginCycles = nowCycles = perf_cpucycles();
55  }
56  else {
57  now = gettimedouble();
58  double elapsed = now - lastTime;
59  double elapsedOne = elapsed / (countMask + 1);
60  if (elapsedOne < minTime) minTime = elapsedOne;
61  if (elapsedOne > maxTime) maxTime = elapsedOne;
62 
63  // We only use relative values, so don't have to handle 64-bit wrap-around specially
64  nowCycles = perf_cpucycles();
65  uint64_t elapsedOneCycles = (nowCycles - lastCycles) / (countMask + 1);
66  if (elapsedOneCycles < minCycles) minCycles = elapsedOneCycles;
67  if (elapsedOneCycles > maxCycles) maxCycles = elapsedOneCycles;
68 
69  if (elapsed*128 < maxElapsed) {
70  // If the execution was much too fast (1/128th of maxElapsed), increase the count mask by 8x and restart timing.
71  // The restart avoids including the overhead of this code in the measurement.
72  countMask = ((countMask<<3)|7) & ((1LL<<60)-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;
79  }
80  if (elapsed*16 < maxElapsed) {
81  uint64_t newCountMask = ((countMask<<1)|1) & ((1LL<<60)-1);
82  if ((count & newCountMask)==0) {
83  countMask = newCountMask;
84  }
85  }
86  }
87  lastTime = now;
88  lastCycles = nowCycles;
89  ++count;
90 
91  if (now - beginTime < maxElapsed) return true; // Keep going
92 
93  --count;
94 
95  assert(count != 0 && "count == 0 => (now == 0 && beginTime == 0) => return above");
96 
97  // Output results
98  double average = (now-beginTime)/count;
99  int64_t averageCycles = (nowCycles-beginCycles)/count;
100  std::cout << std::fixed << std::setprecision(15) << name << "," << count << "," << minTime << "," << maxTime << "," << average << ","
101  << minCycles << "," << maxCycles << "," << averageCycles << "\n";
102  std::cout.copyfmt(std::ios(nullptr));
103 
104  return false;
105 }
BenchRunner(std::string name, BenchFunction func)
Definition: bench.cpp:25
bool KeepRunning()
Definition: bench.cpp:44
void perf_fini(void)
Definition: perf.cpp:51
void perf_init(void)
Definition: perf.cpp:50
static void RunAll(double elapsedTimeForOne=1.0)
Definition: bench.cpp:31
uint64_t perf_cpucycles(void)
Functions for measurement of CPU cycles.
Definition: perf.cpp:52
std::map< std::string, BenchFunction > BenchmarkMap
Definition: bench.h:67
std::function< void(State &)> BenchFunction
Definition: bench.h:63
static BenchmarkMap & benchmarks()
Definition: bench.cpp:14