Bitcoin ABC  0.22.13
P2P Digital Currency
bench.cpp
Go to the documentation of this file.
1 // Copyright (c) 2015-2019 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.
4 
5 #include <bench/bench.h>
6 
7 #include <chainparams.h>
8 #include <validation.h>
9 
10 #include <test/util/setup_common.h>
11 
12 #include <algorithm>
13 #include <cassert>
14 #include <iomanip>
15 #include <iostream>
16 #include <numeric>
17 #include <regex>
18 
20  std::cout << "# Benchmark, evals, iterations, total, min, max, median"
21  << std::endl;
22 }
23 
25  auto results = state.m_elapsed_results;
26  std::sort(results.begin(), results.end());
27 
28  double total = state.m_num_iters *
29  std::accumulate(results.begin(), results.end(), 0.0);
30 
31  double front = 0;
32  double back = 0;
33  double median = 0;
34 
35  if (!results.empty()) {
36  front = results.front();
37  back = results.back();
38 
39  size_t mid = results.size() / 2;
40  median = results[mid];
41  if (0 == results.size() % 2) {
42  median = (results[mid] + results[mid + 1]) / 2;
43  }
44  }
45 
46  std::cout << std::setprecision(6);
47  std::cout << state.m_name << ", " << state.m_num_evals << ", "
48  << state.m_num_iters << ", " << total << ", " << front << ", "
49  << back << ", " << median << std::endl;
50 }
51 
53 benchmark::PlotlyPrinter::PlotlyPrinter(std::string plotly_url, int64_t width,
54  int64_t height)
55  : m_plotly_url(plotly_url), m_width(width), m_height(height) {}
56 
58  std::cout << "<html><head>"
59  << "<script src=\"" << m_plotly_url << "\"></script>"
60  << "</head><body><div id=\"myDiv\" style=\"width:" << m_width
61  << "px; height:" << m_height << "px\"></div>"
62  << "<script> var data = [" << std::endl;
63 }
64 
66  std::cout << "{ " << std::endl
67  << " name: '" << state.m_name << "', " << std::endl
68  << " y: [";
69 
70  const char *prefix = "";
71  for (const auto &e : state.m_elapsed_results) {
72  std::cout << prefix << std::setprecision(6) << e;
73  prefix = ", ";
74  }
75  std::cout << "]," << std::endl
76  << " boxpoints: 'all', jitter: 0.3, pointpos: 0, type: 'box',"
77  << std::endl
78  << "}," << std::endl;
79 }
80 
82  std::cout << "]; var layout = { showlegend: false, yaxis: { rangemode: "
83  "'tozero', autorange: true } };"
84  << "Plotly.newPlot('myDiv', data, layout);"
85  << "</script></body></html>";
86 }
87 
89  std::cout << "<?xml version='1.0' encoding='UTF-8'?>" << std::endl;
90 }
91 
93  auto results = state.m_elapsed_results;
94  double bench_duration =
95  state.m_num_iters *
96  std::accumulate(results.begin(), results.end(), 0.0);
97 
98  /*
99  * Don't print the results now, we need them all to build the <testsuite>
100  * node.
101  */
102  bench_results.emplace_back(std::move(state.m_name), bench_duration);
103  total_duration += bench_duration;
104 }
105 
107  std::cout << std::setprecision(6);
108  std::cout << "<testsuite tests=\"" << bench_results.size() << "\" time=\""
109  << total_duration
110  << "\" name=\"Bitcoin ABC benchmarks\" id=\"0\">" << std::endl;
111 
112  for (const auto &result : bench_results) {
113  std::cout << "<testcase classname=\"" << result.first << "\" name=\""
114  << result.first << "\" time=\"" << result.second
115  << "\"></testcase>" << std::endl;
116  }
117 
118  std::cout << "</testsuite>" << std::endl;
119 }
120 
122  static std::map<std::string, Bench> benchmarks_map;
123  return benchmarks_map;
124 }
125 
128  uint64_t num_iters_for_one_second) {
129  benchmarks().insert(
130  std::make_pair(name, Bench{func, num_iters_for_one_second}));
131 }
132 
133 void benchmark::BenchRunner::RunAll(Printer &printer, uint64_t num_evals,
134  double scaling, const std::string &filter,
135  bool is_list_only) {
136  if (!std::ratio_less_equal<benchmark::clock::period, std::micro>::value) {
137  std::cerr << "WARNING: Clock precision is worse than microsecond - "
138  "benchmarks may be less accurate!\n";
139  }
140 #ifdef DEBUG
141  std::cerr << "WARNING: This is a debug build - may result in slower "
142  "benchmarks.\n";
143 #endif
144 
145  std::regex reFilter(filter);
146  std::smatch baseMatch;
147 
148  printer.header();
149 
150  for (const auto &p : benchmarks()) {
151  if (!std::regex_match(p.first, baseMatch, reFilter)) {
152  continue;
153  }
154 
155  uint64_t num_iters =
156  static_cast<uint64_t>(p.second.num_iters_for_one_second * scaling);
157  if (0 == num_iters) {
158  num_iters = 1;
159  }
160  State state(p.first, num_evals, num_iters, printer);
161  if (!is_list_only) {
162  p.second.func(state);
163  }
164  printer.result(state);
165  }
166 
167  printer.footer();
168 }
169 
171  if (m_start_time != time_point()) {
172  std::chrono::duration<double> diff = current_time - m_start_time;
173  m_elapsed_results.push_back(diff.count() / m_num_iters);
174 
175  if (m_elapsed_results.size() == m_num_evals) {
176  return false;
177  }
178  }
179 
180  m_num_iters_left = m_num_iters - 1;
181  return true;
182 }
void result(const State &state) override
Definition: bench.cpp:24
void result(const State &state) override
Definition: bench.cpp:92
BenchRunner(std::string name, BenchFunction func, uint64_t num_iters_for_one_second)
Definition: bench.cpp:126
const uint64_t m_num_iters
Definition: bench.h:59
void result(const State &state) override
Definition: bench.cpp:65
std::string m_plotly_url
Definition: bench.h:127
std::function< void(State &)> BenchFunction
Definition: bench.h:83
const char * prefix
Definition: rest.cpp:754
std::vector< double > m_elapsed_results
Definition: bench.h:61
virtual void result(const State &state)=0
bool UpdateTimer(time_point finish_time)
Definition: bench.cpp:170
void header() override
Definition: bench.cpp:57
void footer() override
Definition: bench.cpp:81
void header() override
Definition: bench.cpp:19
void header() override
Definition: bench.cpp:88
const char * name
Definition: rest.cpp:43
virtual void header()=0
void footer() override
Definition: bench.cpp:52
const uint64_t m_num_evals
Definition: bench.h:60
std::map< std::string, Bench > BenchmarkMap
Definition: bench.h:90
virtual void footer()=0
static void RunAll(Printer &printer, uint64_t num_evals, double scaling, const std::string &filter, bool is_list_only)
Definition: bench.cpp:133
std::string m_name
Definition: bench.h:57
clock::time_point time_point
Definition: bench.h:50
static BenchmarkMap & benchmarks()
Definition: bench.cpp:121
PlotlyPrinter(std::string plotly_url, int64_t width, int64_t height)
Definition: bench.cpp:53
void footer() override
Definition: bench.cpp:106