Bitcoin Core 31.99.0
P2P Digital Currency
bench.cpp
Go to the documentation of this file.
1// Copyright (c) 2015-present 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 <test/util/setup_common.h> // IWYU pragma: keep
8#include <util/check.h>
9#include <util/fs.h>
10
11#include <chrono>
12#include <compare>
13#include <fstream>
14#include <functional>
15#include <iostream>
16#include <regex>
17#include <string>
18#include <utility>
19#include <vector>
20
21using namespace std::chrono_literals;
22
28static std::function<std::vector<const char*>()> g_bench_command_line_args{};
29const std::function<std::vector<const char*>()> G_TEST_COMMAND_LINE_ARGUMENTS = []() {
31};
32
39static std::string g_running_benchmark_name;
40const std::function<std::string()> G_TEST_GET_FULL_NAME = []() {
42};
43
44namespace {
45
46void GenerateTemplateResults(const std::vector<ankerl::nanobench::Result>& benchmarkResults, const fs::path& file, const char* tpl)
47{
48 if (benchmarkResults.empty() || file.empty()) {
49 // nothing to write, bail out
50 return;
51 }
52 std::ofstream fout{file.std_path()};
53 if (fout.is_open()) {
54 ankerl::nanobench::render(tpl, benchmarkResults, fout);
55 std::cout << "Created " << file << std::endl;
56 } else {
57 std::cout << "Could not write to file " << file << std::endl;
58 }
59}
60
61} // namespace
62
63namespace benchmark {
64
66{
67 static BenchmarkMap benchmarks_map;
68 return benchmarks_map;
69}
70
72{
73 Assert(benchmarks().try_emplace(std::move(name), std::move(func)).second);
74}
75
77{
78 std::regex reFilter(args.regex_filter);
79 std::smatch baseMatch;
80
81 if (args.sanity_check) {
82 std::cout << "Running with -sanity-check option, output is being suppressed as benchmark results will be useless." << std::endl;
83 }
84
85 // Load inner test setup args
87 std::vector<const char*> ret;
88 ret.reserve(args.setup_args.size());
89 for (const auto& arg : args.setup_args) ret.emplace_back(arg.c_str());
90 return ret;
91 };
92
93 std::vector<ankerl::nanobench::Result> benchmarkResults;
94 for (const auto& [name, func] : benchmarks()) {
95
96 if (!std::regex_match(name, baseMatch, reFilter)) {
97 continue;
98 }
99
100 if (args.is_list_only) {
101 std::cout << name << std::endl;
102 continue;
103 }
104
105 Bench bench;
106 if (args.sanity_check) {
107 bench.epochs(1).epochIterations(1);
108 bench.output(nullptr);
109 }
110 bench.name(name);
112 if (args.min_time > 0ms) {
113 // convert to nanos before dividing to reduce rounding errors
114 std::chrono::nanoseconds min_time_ns = args.min_time;
115 bench.minEpochTime(min_time_ns / bench.epochs());
116 }
117
118 if (args.asymptote.empty()) {
119 func(bench);
120 } else {
121 for (auto n : args.asymptote) {
122 bench.complexityN(n);
123 func(bench);
124 }
125 std::cout << bench.complexityBigO() << std::endl;
126 }
127
128 if (!bench.results().empty()) {
129 benchmarkResults.push_back(bench.results().back());
130 }
131 }
132
133 GenerateTemplateResults(benchmarkResults, args.output_csv, "# Benchmark, evals, iterations, total, min, max, median\n"
134 "{{#result}}{{name}}, {{epochs}}, {{average(iterations)}}, {{sumProduct(iterations, elapsed)}}, {{minimum(elapsed)}}, {{maximum(elapsed)}}, {{median(elapsed)}}\n"
135 "{{/result}}");
136 GenerateTemplateResults(benchmarkResults, args.output_json, ankerl::nanobench::templates::json());
137}
138
139} // namespace benchmark
static std::string g_running_benchmark_name
Retrieve the name of the currently in-use benchmark.
Definition: bench.cpp:39
const std::function< std::vector< const char * >()> G_TEST_COMMAND_LINE_ARGUMENTS
Retrieve the command line arguments.
Definition: bench.cpp:29
const std::function< std::string()> G_TEST_GET_FULL_NAME
Retrieve the unit test name.
Definition: bench.cpp:40
static std::function< std::vector< const char * >()> g_bench_command_line_args
Retrieves the available test setup command line arguments that may be used in the benchmark.
Definition: bench.cpp:28
int ret
ArgsManager & args
Definition: bitcoind.cpp:278
#define Assert(val)
Identity function.
Definition: check.h:116
Main entry point to nanobench's benchmarking facility.
Definition: nanobench.h:632
Bench & epochs(size_t numEpochs) noexcept
Controls number of epochs, the number of measurements to perform.
ANKERL_NANOBENCH(NODISCARD) std Bench & name(char const *benchmarkName)
Gets the title of the benchmark.
std::vector< BigO > complexityBigO() const
ANKERL_NANOBENCH(NODISCARD) std ANKERL_NANOBENCH(NODISCARD) std Bench & output(std::ostream *outstream) noexcept
Set the output stream where the resulting markdown table will be printed to.
Bench & complexityN(T n) noexcept
Definition: nanobench.h:1319
ANKERL_NANOBENCH(NODISCARD) std Bench & minEpochTime(std::chrono::nanoseconds t) noexcept
Minimum time each epoch should take.
Bench & epochIterations(uint64_t numIters) noexcept
Sets exactly the number of iterations for each epoch.
static void RunAll(const Args &args)
Definition: bench.cpp:76
BenchRunner(std::string name, BenchFunction func)
Definition: bench.cpp:71
std::map< std::string, BenchFunction > BenchmarkMap
Definition: bench.h:57
static BenchmarkMap & benchmarks()
Definition: bench.cpp:65
char const * json() noexcept
Template to generate JSON data.
void render(char const *mustacheTemplate, Bench const &bench, std::ostream &out)
Renders output from a mustache-like template and benchmark results.
std::function< void(Bench &)> BenchFunction
Definition: bench.h:41
const char * name
Definition: rest.cpp:49