Inside Bitcoin
Opening the selected file…
Inside Bitcoin
Opening the selected file…
The code behind the network, with room to understand it.
Release published 2026-10-28 · Snapshot fetched 2026-11-01. Latest stable release at fetch time; development branches and Git history are excluded. Only the selected code window and visible folders load here.
1// Copyright (c) 2015-present The Bitcoin Core developers2// Distributed under the MIT software license, see the accompanying3// file COPYING or http://www.opensource.org/licenses/mit-license.php.5#include <bench/bench.h>6#include <crypto/sha256.h>7#include <test/util/setup_common.h>8#include <tinyformat.h>9#include <util/fs.h>10#include <util/time.h>12#include <cstdint>13#include <cstdlib>14#include <exception>15#include <iostream>16#include <optional>17#include <sstream>18#include <string>19#include <vector>21static const char* DEFAULT_BENCH_FILTER = ".*";22static constexpr int64_t DEFAULT_MIN_TIME_MS{10};24static void SetupBenchArgs(ArgsManager& argsman)25{26SetupHelpOptions(argsman);27SetupCommonTestArgs(argsman);29argsman.AddArg("-asymptote=<n1,n2,n3,...>", "Test asymptotic growth of the runtime of an algorithm, if supported by the benchmark", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);30argsman.AddArg("-filter=<regex>", strprintf("Regular expression filter to select benchmark by name (default: %s)", DEFAULT_BENCH_FILTER), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);31argsman.AddArg("-list", "List benchmarks without executing them", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);32argsman.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);33argsman.AddArg("-output-csv=<output.csv>", "Generate CSV file with the most important benchmark results", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);34argsman.AddArg("-output-json=<output.json>", "Generate JSON file with all benchmark results", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);35argsman.AddArg("-sanity-check", "Run benchmarks for only one iteration with no output", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);36}38// parses a comma separated list like "10,20,30,50"39static std::vector<double> parseAsymptote(const std::string& str) {40std::stringstream ss(str);41std::vector<double> numbers;42double d;43char c;44while (ss >> d) {45numbers.push_back(d);46ss >> c;47}48return numbers;49}51static std::vector<std::string> parseTestSetupArgs(const ArgsManager& argsman)52{53// Parses unit test framework arguments supported by the benchmark framework.54std::vector<std::string> args;55static std::vector<std::string> AVAILABLE_ARGS = {"-testdatadir"};56for (const std::string& arg_name : AVAILABLE_ARGS) {57auto op_arg = argsman.GetArg(arg_name);58if (op_arg) args.emplace_back(strprintf("%s=%s", arg_name, *op_arg));59}60return args;61}63int main(int argc, char** argv)64{65ArgsManager argsman;66SetupBenchArgs(argsman);67SHA256AutoDetect();68std::string error;69if (!argsman.ParseParameters(argc, argv, error)) {70tfm::format(std::cerr, "Error parsing command line arguments: %s\n", error);71return EXIT_FAILURE;72}74if (HelpRequested(argsman)) {75std::cout << "Usage: bench_bitcoin [options]\n"76"\n"77<< argsman.GetHelpMessage()78<< "Description:\n"79"\n"80" bench_bitcoin executes microbenchmarks. The quality of the benchmark results\n"81" highly depend on the stability of the machine. It can sometimes be difficult\n"82" to get stable, repeatable results, so here are a few tips:\n"83"\n"84" * Use pyperf [1] to disable frequency scaling, turbo boost etc. For best\n"85" results, use CPU pinning and CPU isolation (see [2]).\n"86"\n"87" * Each call of run() should do exactly the same work. E.g. inserting into\n"88" a std::vector doesn't do that as it will reallocate on certain calls. Make\n"89" sure each run has exactly the same preconditions.\n"90"\n"91" * If results are still not reliable, increase runtime with e.g.\n"92" -min-time=5000 to let a benchmark run for at least 5 seconds.\n"93"\n"94" * bench_bitcoin uses nanobench [3] for which there is extensive\n"95" documentation available online.\n"96"\n"97"Environment Variables:\n"98"\n"99" To attach a profiler you can run a benchmark in endless mode. This can be\n"100" done with the environment variable NANOBENCH_ENDLESS. E.g. like so:\n"101"\n"102" NANOBENCH_ENDLESS=MuHash ./bench_bitcoin -filter=MuHash\n"103"\n"104" In rare cases it can be useful to suppress stability warnings. This can be\n"105" done with the environment variable NANOBENCH_SUPPRESS_WARNINGS, e.g:\n"106"\n"107" NANOBENCH_SUPPRESS_WARNINGS=1 ./bench_bitcoin\n"108"\n"109"Notes:\n"110"\n"111" 1. pyperf\n"112" https://github.com/psf/pyperf\n"113"\n"114" 2. CPU pinning & isolation\n"115" https://pyperf.readthedocs.io/en/latest/system.html\n"116"\n"117" 3. nanobench\n"118" https://github.com/martinus/nanobench\n"119"\n";121return EXIT_SUCCESS;122}124try {125benchmark::Args args;126args.asymptote = parseAsymptote(argsman.GetArg("-asymptote", ""));127args.is_list_only = argsman.GetBoolArg("-list", false);128args.min_time = std::chrono::milliseconds(argsman.GetIntArg("-min-time", DEFAULT_MIN_TIME_MS));129args.output_csv = argsman.GetPathArg("-output-csv");130args.output_json = argsman.GetPathArg("-output-json");131args.regex_filter = argsman.GetArg("-filter", DEFAULT_BENCH_FILTER);132args.sanity_check = argsman.GetBoolArg("-sanity-check", false);133args.setup_args = parseTestSetupArgs(argsman);135benchmark::BenchRunner::RunAll(args);137return EXIT_SUCCESS;138} catch (const std::exception& e) {139tfm::format(std::cerr, "Error: %s\n", e.what());140return EXIT_FAILURE;141}142}
Independent explanations by MyBitcoinExplorer. Not affiliated with or endorsed by Bitcoin Core. Guides are educational and do not replace the source or its tests.
Bitcoin Core source © its contributors, distributed under the MIT license. Original notices and bundled third-party licenses are retained in the source tree.