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.
2001throw std::runtime_error("unknown list '" + std::string(n.begin, n.end) + "'");2003case templates::Node::Type::section:2004if (n == "result") {2005const size_t nbResults = results.size();2006for (size_t i = 0; i < nbResults; ++i) {2007generateResult(n.children, i, results, out);2008}2009} else if (n == "measurement") {2010if (results.size() != 1) {2011throw std::runtime_error(2012"render: can only use section 'measurement' here if there is a single result, but there are " +2013detail::fmt::to_s(results.size()));2014}2015// when we only have a single result, we can immediately go into its measurement.2016auto const& r = results.front();2017for (size_t i = 0; i < r.size(); ++i) {2018generateResultMeasurement(n.children, i, r, out);2019}2020} else {2021throw std::runtime_error("render: unknown section '" + std::string(n.begin, n.end) + "'");2022}2023break;2025case templates::Node::Type::tag:2026if (results.size() == 1) {2027// result & config are both supported there2028generateResultTag(n, results.front(), out);2029} else {2030// This just uses the last result's config.2031if (!generateConfigTag(n, results.back().config(), out)) {2032throw std::runtime_error("unknown tag '" + std::string(n.begin, n.end) + "'");2033}2034}2035break;2036}2037}2038}2040void render(std::string const& mustacheTemplate, std::vector<Result> const& results, std::ostream& out) {2041render(mustacheTemplate.c_str(), results, out);2042}2044void render(char const* mustacheTemplate, const Bench& bench, std::ostream& out) {2045render(mustacheTemplate, bench.results(), out);2046}2048void render(std::string const& mustacheTemplate, const Bench& bench, std::ostream& out) {2049render(mustacheTemplate.c_str(), bench.results(), out);2050}2052namespace detail {2054PerformanceCounters& performanceCounters() {2055# if defined(__clang__)2056# pragma clang diagnostic push2057# pragma clang diagnostic ignored "-Wexit-time-destructors"2058# endif2059static PerformanceCounters pc;2060# if defined(__clang__)2061# pragma clang diagnostic pop2062# endif2063return pc;2064}2066// Windows version of doNotOptimizeAway2067// see https://github.com/google/benchmark/blob/v1.7.1/include/benchmark/benchmark.h#L5142068// see https://github.com/facebook/folly/blob/v2023.01.30.00/folly/lang/Hint-inl.h#L54-L582069// see https://learn.microsoft.com/en-us/cpp/preprocessor/optimize2070# if defined(_MSC_VER)2071# pragma optimize("", off)2072void doNotOptimizeAwaySink(void const*) {}2073# pragma optimize("", on)2074# endif2076template <typename T>2077T parseFile(std::string const& filename, bool* fail) {2078std::ifstream fin(filename); // NOLINT(misc-const-correctness)2079T num{};2080fin >> num;2081if (fail != nullptr) {2082*fail = fin.fail();2083}2084return num;2085}2087char const* getEnv(char const* name) {2088# if defined(_MSC_VER)2089# pragma warning(push)2090# pragma warning(disable : 4996) // getenv': This function or variable may be unsafe.2091# endif2092return std::getenv(name); // NOLINT(concurrency-mt-unsafe)2093# if defined(_MSC_VER)2094# pragma warning(pop)2095# endif2096}2098bool isEndlessRunning(std::string const& name) {2099auto const* const endless = getEnv("NANOBENCH_ENDLESS");2100return nullptr != endless && endless == name;2101}2103// True when environment variable NANOBENCH_SUPPRESS_WARNINGS is either not set at all, or set to "0"2104bool isWarningsEnabled() {2105auto const* const suppression = getEnv("NANOBENCH_SUPPRESS_WARNINGS");2106return nullptr == suppression || suppression == std::string("0");2107}2109void gatherStabilityInformation(std::vector<std::string>& warnings, std::vector<std::string>& recommendations) {2110warnings.clear();2111recommendations.clear();2113# if defined(DEBUG)2114warnings.emplace_back("DEBUG defined");2115bool const recommendCheckFlags = true;2116# else2117bool const recommendCheckFlags = false;2118# endif2120bool recommendPyPerf = false;2121# if defined(__linux__)2122auto nprocs = sysconf(_SC_NPROCESSORS_CONF);2123if (nprocs <= 0) {2124warnings.emplace_back("couldn't figure out number of processors - no governor, turbo check possible");2125} else {2126// check frequency scaling2127for (long id = 0; id < nprocs; ++id) {2128auto idStr = detail::fmt::to_s(static_cast<uint64_t>(id));2129auto sysCpu = "/sys/devices/system/cpu/cpu" + idStr;2130auto minFreq = parseFile<int64_t>(sysCpu + "/cpufreq/scaling_min_freq", nullptr);2131auto maxFreq = parseFile<int64_t>(sysCpu + "/cpufreq/scaling_max_freq", nullptr);2132if (minFreq != maxFreq) {2133auto minMHz = d(minFreq) / 1000.0;2134auto maxMHz = d(maxFreq) / 1000.0;2135warnings.emplace_back("CPU frequency scaling enabled: CPU " + idStr + " between " +2136detail::fmt::Number(1, 1, minMHz).to_s() + " and " + detail::fmt::Number(1, 1, maxMHz).to_s() +2137" MHz");2138recommendPyPerf = true;2139break;2140}2141}2143auto fail = false;2144auto currentGovernor = parseFile<std::string>("/sys/devices/system/cpu/cpu0/cpufreq/scaling_governor", &fail);2145if (!fail && "performance" != currentGovernor) {2146warnings.emplace_back("CPU governor is '" + currentGovernor + "' but should be 'performance'");2147recommendPyPerf = true;2148}2150auto noTurbo = parseFile<int>("/sys/devices/system/cpu/intel_pstate/no_turbo", &fail);2151if (!fail && noTurbo == 0) {2152warnings.emplace_back("Turbo is enabled, CPU frequency will fluctuate");2153recommendPyPerf = true;2154}2155}2156# endif2158if (recommendCheckFlags) {2159recommendations.emplace_back("Make sure you compile for Release");2160}2161if (recommendPyPerf) {2162recommendations.emplace_back("Use 'pyperf system tune' before benchmarking. See https://github.com/psf/pyperf");2163}2164}2166void printStabilityInformationOnce(std::ostream* outStream) {2167static bool shouldPrint = true;2168if (shouldPrint && (nullptr != outStream) && isWarningsEnabled()) {2169auto& os = *outStream;2170shouldPrint = false;2171std::vector<std::string> warnings;2172std::vector<std::string> recommendations;2173gatherStabilityInformation(warnings, recommendations);2174if (warnings.empty()) {2175return;2176}2178os << "Warning, results might be unstable:" << std::endl;2179for (auto const& w : warnings) {2180os << "* " << w << std::endl;2181}2183os << std::endl << "Recommendations" << std::endl;2184for (auto const& r : recommendations) {2185os << "* " << r << std::endl;2186}2187}2188}2190// remembers the last table settings used. When it changes, a new table header is automatically written for the new entry.2191uint64_t& singletonHeaderHash() noexcept {2192static uint64_t sHeaderHash{};2193return sHeaderHash;2194}2196ANKERL_NANOBENCH_NO_SANITIZE("integer", "undefined")2197inline uint64_t hash_combine(uint64_t seed, uint64_t val) {2198return seed ^ (val + UINT64_C(0x9e3779b9) + (seed << 6U) + (seed >> 2U));2199}2201// determines resolution of the given clock. This is done by measuring multiple times and returning the minimum time difference.2202Clock::duration calcClockResolution(size_t numEvaluations) noexcept {2203auto bestDuration = Clock::duration::max();2204Clock::time_point tBegin;2205Clock::time_point tEnd;2206for (size_t i = 0; i < numEvaluations; ++i) {2207tBegin = Clock::now();2208do {2209tEnd = Clock::now();2210} while (tBegin == tEnd);2211bestDuration = (std::min)(bestDuration, tEnd - tBegin);2212}2213return bestDuration;2214}2216// Calculates clock resolution once, and remembers the result2217Clock::duration clockResolution() noexcept {2218static Clock::duration const sResolution = calcClockResolution(20);2219return sResolution;2220}2222ANKERL_NANOBENCH(IGNORE_PADDED_PUSH)2223struct IterationLogic::Impl {2224enum class State { warmup, upscaling_runtime, measuring, endless };2226explicit Impl(Bench const& bench)2227: mBench(bench)2228, mResult(bench.config()) {2229printStabilityInformationOnce(mBench.output());2231// determine target runtime per epoch2232mTargetRuntimePerEpoch = detail::clockResolution() * mBench.clockResolutionMultiple();2233if (mTargetRuntimePerEpoch > mBench.maxEpochTime()) {2234mTargetRuntimePerEpoch = mBench.maxEpochTime();2235}2236if (mTargetRuntimePerEpoch < mBench.minEpochTime()) {2237mTargetRuntimePerEpoch = mBench.minEpochTime();2238}2240if (isEndlessRunning(mBench.name())) {2241std::cerr << "NANOBENCH_ENDLESS set: running '" << mBench.name() << "' endlessly" << std::endl;2242mNumIters = (std::numeric_limits<uint64_t>::max)();2243mState = State::endless;2244} else if (0 != mBench.warmup()) {2245mNumIters = mBench.warmup();2246mState = State::warmup;2247} else if (0 != mBench.epochIterations()) {2248// exact number of iterations2249mNumIters = mBench.epochIterations();2250mState = State::measuring;
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.