Changeset View
Changeset View
Standalone View
Standalone View
src/bench/bench_bitcoin.cpp
// Copyright (c) 2015-2019 The Bitcoin Core developers | // Copyright (c) 2015-2019 The Bitcoin Core developers | ||||
// Distributed under the MIT software license, see the accompanying | // Distributed under the MIT software license, see the accompanying | ||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php. | // file COPYING or http://www.opensource.org/licenses/mit-license.php. | ||||
#include <bench/bench.h> | #include <bench/bench.h> | ||||
#include <util/strencodings.h> | #include <util/strencodings.h> | ||||
#include <util/system.h> | #include <util/system.h> | ||||
#include <memory> | #include <memory> | ||||
static const int64_t DEFAULT_BENCH_EVALUATIONS = 5; | |||||
static const char *DEFAULT_BENCH_FILTER = ".*"; | static const char *DEFAULT_BENCH_FILTER = ".*"; | ||||
static const char *DEFAULT_BENCH_SCALING = "1.0"; | |||||
static const char *DEFAULT_BENCH_PRINTER = "console"; | |||||
static const char *DEFAULT_PLOT_PLOTLYURL = | |||||
"https://cdn.plot.ly/plotly-latest.min.js"; | |||||
static const int64_t DEFAULT_PLOT_WIDTH = 1024; | |||||
static const int64_t DEFAULT_PLOT_HEIGHT = 768; | |||||
static void SetupBenchArgs(ArgsManager &argsman) { | static void SetupBenchArgs(ArgsManager &argsman) { | ||||
SetupHelpOptions(argsman); | SetupHelpOptions(argsman); | ||||
argsman.AddArg("-list", | argsman.AddArg("-list", "List benchmarks without executing them", | ||||
"List benchmarks without executing them. Can be combined " | |||||
"with -scaling and -filter", | |||||
ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS); | |||||
argsman.AddArg( | |||||
"-evals=<n>", | |||||
strprintf("Number of measurement evaluations to perform. (default: %u)", | |||||
DEFAULT_BENCH_EVALUATIONS), | |||||
ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS); | ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS); | ||||
argsman.AddArg("-filter=<regex>", | argsman.AddArg("-filter=<regex>", | ||||
strprintf("Regular expression filter to select benchmark by " | strprintf("Regular expression filter to select benchmark by " | ||||
"name (default: %s)", | "name (default: %s)", | ||||
DEFAULT_BENCH_FILTER), | DEFAULT_BENCH_FILTER), | ||||
ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS); | ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS); | ||||
argsman.AddArg( | argsman.AddArg("-asymptote=n1,n2,n3,...", | ||||
"-scaling=<n>", | strprintf("Test asymptotic growth of the runtime of an " | ||||
strprintf("Scaling factor for benchmark's runtime (default: %u)", | "algorithm, if supported by the benchmark"), | ||||
DEFAULT_BENCH_SCALING), | |||||
ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS); | ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS); | ||||
argsman.AddArg( | argsman.AddArg( | ||||
"-printer=(console|junit|plot)", | "-output_csv=<output.csv>", | ||||
strprintf("Choose printer format. console: print data to console. " | "Generate CSV file with the most important benchmark results.", | ||||
"junit: print results as a Junit compliant XML." | |||||
"plot: print results as HTML graph (default: %s)", | |||||
DEFAULT_BENCH_PRINTER), | |||||
ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS); | ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS); | ||||
argsman.AddArg("-plot-plotlyurl=<uri>", | argsman.AddArg("-output_json=<output.json>", | ||||
strprintf("URL to use for plotly.js (default: %s)", | "Generate JSON file with all benchmark results.", | ||||
DEFAULT_PLOT_PLOTLYURL), | |||||
ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS); | |||||
argsman.AddArg( | |||||
"-plot-width=<x>", | |||||
strprintf("Plot width in pixel (default: %u)", DEFAULT_PLOT_WIDTH), | |||||
ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS); | |||||
argsman.AddArg( | |||||
"-plot-height=<x>", | |||||
strprintf("Plot height in pixel (default: %u)", DEFAULT_PLOT_HEIGHT), | |||||
ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS); | ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS); | ||||
} | } | ||||
// parses a comma separated list like "10,20,30,50" | |||||
static std::vector<double> parseAsymptote(const std::string &str) { | |||||
std::stringstream ss(str); | |||||
std::vector<double> numbers; | |||||
double d; | |||||
char c; | |||||
while (ss >> d) { | |||||
numbers.push_back(d); | |||||
ss >> c; | |||||
} | |||||
return numbers; | |||||
} | |||||
int main(int argc, char **argv) { | int main(int argc, char **argv) { | ||||
ArgsManager argsman; | ArgsManager argsman; | ||||
SetupBenchArgs(argsman); | SetupBenchArgs(argsman); | ||||
std::string error; | std::string error; | ||||
if (!argsman.ParseParameters(argc, argv, error)) { | if (!argsman.ParseParameters(argc, argv, error)) { | ||||
tfm::format(std::cerr, "Error parsing command line arguments: %s\n", | tfm::format(std::cerr, "Error parsing command line arguments: %s\n", | ||||
error); | error); | ||||
return EXIT_FAILURE; | return EXIT_FAILURE; | ||||
} | } | ||||
if (HelpRequested(argsman)) { | if (HelpRequested(argsman)) { | ||||
std::cout << argsman.GetHelpMessage(); | std::cout << argsman.GetHelpMessage(); | ||||
return EXIT_SUCCESS; | return EXIT_SUCCESS; | ||||
} | } | ||||
int64_t evaluations = argsman.GetArg("-evals", DEFAULT_BENCH_EVALUATIONS); | benchmark::Args args; | ||||
std::string regex_filter = argsman.GetArg("-filter", DEFAULT_BENCH_FILTER); | args.regex_filter = argsman.GetArg("-filter", DEFAULT_BENCH_FILTER); | ||||
std::string scaling_str = argsman.GetArg("-scaling", DEFAULT_BENCH_SCALING); | args.is_list_only = argsman.GetBoolArg("-list", false); | ||||
bool is_list_only = argsman.GetBoolArg("-list", false); | args.asymptote = parseAsymptote(argsman.GetArg("-asymptote", "")); | ||||
args.output_csv = argsman.GetArg("-output_csv", ""); | |||||
if (evaluations == 0) { | args.output_json = argsman.GetArg("-output_json", ""); | ||||
return EXIT_SUCCESS; | |||||
} else if (evaluations < 0) { | |||||
tfm::format(std::cerr, "Error parsing evaluations argument: %d\n", | |||||
evaluations); | |||||
return EXIT_FAILURE; | |||||
} | |||||
double scaling_factor; | |||||
if (!ParseDouble(scaling_str, &scaling_factor)) { | |||||
tfm::format(std::cerr, "Error parsing scaling factor as double: %s\n", | |||||
scaling_str); | |||||
return EXIT_FAILURE; | |||||
} | |||||
std::unique_ptr<benchmark::Printer> printer = | |||||
std::make_unique<benchmark::ConsolePrinter>(); | |||||
std::string printer_arg = argsman.GetArg("-printer", DEFAULT_BENCH_PRINTER); | |||||
if ("plot" == printer_arg) { | |||||
printer.reset(new benchmark::PlotlyPrinter( | |||||
argsman.GetArg("-plot-plotlyurl", DEFAULT_PLOT_PLOTLYURL), | |||||
argsman.GetArg("-plot-width", DEFAULT_PLOT_WIDTH), | |||||
argsman.GetArg("-plot-height", DEFAULT_PLOT_HEIGHT))); | |||||
} | |||||
if ("junit" == printer_arg) { | |||||
printer.reset(new benchmark::JunitPrinter()); | |||||
} | |||||
// gArgs no longer needed. Clear it here to avoid interactions with the | |||||
// testing setup in the benches | |||||
gArgs.ClearArgs(); | |||||
benchmark::BenchRunner::RunAll(*printer, evaluations, scaling_factor, | benchmark::BenchRunner::RunAll(args); | ||||
regex_filter, is_list_only); | |||||
return EXIT_SUCCESS; | return EXIT_SUCCESS; | ||||
} | } |