Bitcoin Core  22.99.0
P2P Digital Currency
bench_bitcoin.cpp
Go to the documentation of this file.
1 // Copyright (c) 2015-2021 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 <clientversion.h>
8 #include <crypto/sha256.h>
9 #include <fs.h>
10 #include <util/strencodings.h>
11 #include <util/system.h>
12 
13 #include <chrono>
14 #include <cstdint>
15 #include <iostream>
16 #include <sstream>
17 #include <vector>
18 
19 static const char* DEFAULT_BENCH_FILTER = ".*";
20 static constexpr int64_t DEFAULT_MIN_TIME_MS{10};
21 
22 static void SetupBenchArgs(ArgsManager& argsman)
23 {
24  SetupHelpOptions(argsman);
25 
26  argsman.AddArg("-asymptote=<n1,n2,n3,...>", "Test asymptotic growth of the runtime of an algorithm, if supported by the benchmark", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
27  argsman.AddArg("-filter=<regex>", strprintf("Regular expression filter to select benchmark by name (default: %s)", DEFAULT_BENCH_FILTER), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
28  argsman.AddArg("-list", "List benchmarks without executing them", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
29  argsman.AddArg("-min_time=<milliseconds>", strprintf("Minimum runtime per benchmark, in milliseconds (default: %d)", DEFAULT_MIN_TIME_MS), ArgsManager::ALLOW_ANY | ArgsManager::DISALLOW_NEGATION, OptionsCategory::OPTIONS);
30  argsman.AddArg("-output_csv=<output.csv>", "Generate CSV file with the most important benchmark results", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
31  argsman.AddArg("-output_json=<output.json>", "Generate JSON file with all benchmark results", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
32 }
33 
34 // parses a comma separated list like "10,20,30,50"
35 static std::vector<double> parseAsymptote(const std::string& str) {
36  std::stringstream ss(str);
37  std::vector<double> numbers;
38  double d;
39  char c;
40  while (ss >> d) {
41  numbers.push_back(d);
42  ss >> c;
43  }
44  return numbers;
45 }
46 
47 int main(int argc, char** argv)
48 {
49  ArgsManager argsman;
50  SetupBenchArgs(argsman);
52  std::string error;
53  if (!argsman.ParseParameters(argc, argv, error)) {
54  tfm::format(std::cerr, "Error parsing command line arguments: %s\n", error);
55  return EXIT_FAILURE;
56  }
57 
58  if (HelpRequested(argsman)) {
59  std::cout << "Usage: bench_bitcoin [options]\n"
60  "\n"
61  << argsman.GetHelpMessage()
62  << "Description:\n"
63  "\n"
64  " bench_bitcoin executes microbenchmarks. The quality of the benchmark results\n"
65  " highly depend on the stability of the machine. It can sometimes be difficult\n"
66  " to get stable, repeatable results, so here are a few tips:\n"
67  "\n"
68  " * Use pyperf [1] to disable frequency scaling, turbo boost etc. For best\n"
69  " results, use CPU pinning and CPU isolation (see [2]).\n"
70  "\n"
71  " * Each call of run() should do exactly the same work. E.g. inserting into\n"
72  " a std::vector doesn't do that as it will reallocate on certain calls. Make\n"
73  " sure each run has exactly the same preconditions.\n"
74  "\n"
75  " * If results are still not reliable, increase runtime with e.g.\n"
76  " -min_time=5000 to let a benchmark run for at least 5 seconds.\n"
77  "\n"
78  " * bench_bitcoin uses nanobench [3] for which there is extensive\n"
79  " documentation available online.\n"
80  "\n"
81  "Environment Variables:\n"
82  "\n"
83  " To attach a profiler you can run a benchmark in endless mode. This can be\n"
84  " done with the environment variable NANOBENCH_ENDLESS. E.g. like so:\n"
85  "\n"
86  " NANOBENCH_ENDLESS=MuHash ./bench_bitcoin -filter=MuHash\n"
87  "\n"
88  " In rare cases it can be useful to suppress stability warnings. This can be\n"
89  " done with the environment variable NANOBENCH_SUPPRESS_WARNINGS, e.g:\n"
90  "\n"
91  " NANOBENCH_SUPPRESS_WARNINGS=1 ./bench_bitcoin\n"
92  "\n"
93  "Notes:\n"
94  "\n"
95  " 1. pyperf\n"
96  " https://github.com/psf/pyperf\n"
97  "\n"
98  " 2. CPU pinning & isolation\n"
99  " https://pyperf.readthedocs.io/en/latest/system.html\n"
100  "\n"
101  " 3. nanobench\n"
102  " https://github.com/martinus/nanobench\n"
103  "\n";
104 
105  return EXIT_SUCCESS;
106  }
107 
109  args.asymptote = parseAsymptote(argsman.GetArg("-asymptote", ""));
110  args.is_list_only = argsman.GetBoolArg("-list", false);
111  args.min_time = std::chrono::milliseconds(argsman.GetIntArg("-min_time", DEFAULT_MIN_TIME_MS));
112  args.output_csv = fs::PathFromString(argsman.GetArg("-output_csv", ""));
113  args.output_json = fs::PathFromString(argsman.GetArg("-output_json", ""));
114  args.regex_filter = argsman.GetArg("-filter", DEFAULT_BENCH_FILTER);
115 
117 
118  return EXIT_SUCCESS;
119 }
ArgsManager::GetBoolArg
bool GetBoolArg(const std::string &strArg, bool fDefault) const
Return boolean argument or default value.
Definition: system.cpp:600
tinyformat::format
void format(std::ostream &out, const char *fmt, const Args &... args)
Format list of arguments to the stream according to given format string.
Definition: tinyformat.h:1062
fs.h
ArgsManager::GetHelpMessage
std::string GetHelpMessage() const
Get the help string.
Definition: system.cpp:668
ArgsManager::ALLOW_ANY
@ ALLOW_ANY
disable validation
Definition: system.h:172
ArgsManager::DISALLOW_NEGATION
@ DISALLOW_NEGATION
disallow -nofoo syntax
Definition: system.h:177
parseAsymptote
static std::vector< double > parseAsymptote(const std::string &str)
Definition: bench_bitcoin.cpp:35
benchmark::BenchRunner::RunAll
static void RunAll(const Args &args)
Definition: bench.cpp:55
DEFAULT_BENCH_FILTER
static const char * DEFAULT_BENCH_FILTER
Definition: bench_bitcoin.cpp:19
clientversion.h
HelpRequested
bool HelpRequested(const ArgsManager &args)
Definition: system.cpp:737
SetupHelpOptions
void SetupHelpOptions(ArgsManager &args)
Add help options to the args manager.
Definition: system.cpp:742
SHA256AutoDetect
std::string SHA256AutoDetect()
Autodetect the best available SHA256 implementation.
Definition: sha256.cpp:582
DEFAULT_MIN_TIME_MS
static constexpr int64_t DEFAULT_MIN_TIME_MS
Definition: bench_bitcoin.cpp:20
strencodings.h
SetupBenchArgs
static void SetupBenchArgs(ArgsManager &argsman)
Definition: bench_bitcoin.cpp:22
ArgsManager::AddArg
void AddArg(const std::string &name, const std::string &help, unsigned int flags, const OptionsCategory &cat)
Add argument.
Definition: system.cpp:640
ArgsManager::GetArg
std::string GetArg(const std::string &strArg, const std::string &strDefault) const
Return string argument or default value.
Definition: system.cpp:588
OptionsCategory::OPTIONS
@ OPTIONS
benchmark::Args
Definition: bench.h:44
fs::PathFromString
static path PathFromString(const std::string &string)
Convert byte string to path object.
Definition: fs.h:135
ArgsManager::ParseParameters
bool ParseParameters(int argc, const char *const argv[], std::string &error)
Definition: system.cpp:297
bench.h
sha256.h
system.h
strprintf
#define strprintf
Format arguments and return the string or write to given std::ostream (see tinyformat::format doc for...
Definition: tinyformat.h:1164
ArgsManager
Definition: system.h:164
error
bool error(const char *fmt, const Args &... args)
Definition: system.h:49
ArgsManager::GetIntArg
int64_t GetIntArg(const std::string &strArg, int64_t nDefault) const
Return integer argument or default value.
Definition: system.cpp:594
main
int main(int argc, char **argv)
Definition: bench_bitcoin.cpp:47
args
ArgsManager args
Definition: notifications.cpp:36