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.
1001*1002* The resulting mean squared error can be printed with `std::cout << logLogN`. E.g. it prints something like this:1003*1004* ```text1005* 2.46985e-05 * O(log log n), rms=1.481211006* ```1007*1008* @tparam Op Type of mapping operation.1009* @param name Name for the function, e.g. "O(log log n)"1010* @param op Op's operator() maps a `double` with the desired complexity function, e.g. `log2(log2(n))`.1011* @return BigO Error calculation, which is streamable to std::cout.1012*/1013template <typename Op>1014BigO complexityBigO(char const* name, Op op) const;1016template <typename Op>1017BigO complexityBigO(std::string const& name, Op op) const;1019/*!1020@verbatim embed:rst1022Convenience shortcut to :cpp:func:`ankerl::nanobench::render`.1024@endverbatim1025*/1026Bench& render(char const* templateContent, std::ostream& os);1027Bench& render(std::string const& templateContent, std::ostream& os);1029Bench& config(Config const& benchmarkConfig);1030ANKERL_NANOBENCH(NODISCARD) Config const& config() const noexcept;1032/**1033* @brief Configure an untimed setup step per epoch (forces single-iteration epochs).1034*1035* Example: `bench.setup(...).run(...);`1036*/1037template <typename SetupOp>1038detail::SetupRunner<SetupOp> setup(SetupOp setupOp);1040private:1041template <typename SetupOp, typename Op>1042Bench& runImpl(SetupOp& setupOp, Op&& op);1044template <typename SetupOp>1045friend class detail::SetupRunner;1047Config mConfig{};1048std::vector<Result> mResults{};1049};1050ANKERL_NANOBENCH(IGNORE_PADDED_POP)1052/**1053* @brief Makes sure none of the given arguments are optimized away by the compiler.1054*1055* @tparam Arg Type of the argument that shouldn't be optimized away.1056* @param arg The input that we mark as being used, even though we don't do anything with it.1057*/1058template <typename Arg>1059void doNotOptimizeAway(Arg&& arg);1061namespace detail {1063#if defined(_MSC_VER)1064void doNotOptimizeAwaySink(void const*);1066template <typename T>1067void doNotOptimizeAway(T const& val);1069#else1071// These assembly magic is directly from what Google Benchmark is doing. I have previously used what facebook's folly was doing, but1072// this seemed to have compilation problems in some cases. Google Benchmark seemed to be the most well tested anyways.1073// see https://github.com/google/benchmark/blob/v1.7.1/include/benchmark/benchmark.h#L443-L4461074template <typename T>1075void doNotOptimizeAway(T const& val) {1076// NOLINTNEXTLINE(hicpp-no-assembler)1077asm volatile("" : : "r,m"(val) : "memory");1078}1080template <typename T>1081void doNotOptimizeAway(T& val) {1082# if defined(__clang__)1083// NOLINTNEXTLINE(hicpp-no-assembler)1084asm volatile("" : "+r,m"(val) : : "memory");1085# else1086// NOLINTNEXTLINE(hicpp-no-assembler)1087asm volatile("" : "+m,r"(val) : : "memory");1088# endif1089}1090#endif1092// internally used, but visible because run() is templated.1093// Not movable/copy-able, so we simply use a pointer instead of unique_ptr. This saves us from1094// having to include <memory>, and the template instantiation overhead of unique_ptr which is unfortunately quite significant.1095ANKERL_NANOBENCH(IGNORE_EFFCPP_PUSH)1096class IterationLogic {1097public:1098explicit IterationLogic(Bench const& bench);1099IterationLogic(IterationLogic&&) = delete;1100IterationLogic& operator=(IterationLogic&&) = delete;1101IterationLogic(IterationLogic const&) = delete;1102IterationLogic& operator=(IterationLogic const&) = delete;1103~IterationLogic();1105ANKERL_NANOBENCH(NODISCARD) uint64_t numIters() const noexcept;1106void add(std::chrono::nanoseconds elapsed, PerformanceCounters const& pc) noexcept;1107void moveResultTo(std::vector<Result>& results) noexcept;1109private:1110struct Impl;1111Impl* mPimpl;1112};1113ANKERL_NANOBENCH(IGNORE_EFFCPP_POP)1115ANKERL_NANOBENCH(IGNORE_PADDED_PUSH)1116class PerformanceCounters {1117public:1118PerformanceCounters(PerformanceCounters const&) = delete;1119PerformanceCounters(PerformanceCounters&&) = delete;1120PerformanceCounters& operator=(PerformanceCounters const&) = delete;1121PerformanceCounters& operator=(PerformanceCounters&&) = delete;1123PerformanceCounters();1124~PerformanceCounters();1126void beginMeasure();1127void endMeasure();1128void updateResults(uint64_t numIters);1130ANKERL_NANOBENCH(NODISCARD) PerfCountSet<uint64_t> const& val() const noexcept;1131ANKERL_NANOBENCH(NODISCARD) PerfCountSet<bool> const& has() const noexcept;1133private:1134#if ANKERL_NANOBENCH(PERF_COUNTERS)1135LinuxPerformanceCounters* mPc = nullptr;1136#endif1137PerfCountSet<uint64_t> mVal{};1138PerfCountSet<bool> mHas{};1139};1140ANKERL_NANOBENCH(IGNORE_PADDED_POP)1142// Gets the singleton1143PerformanceCounters& performanceCounters();1145} // namespace detail1147class BigO {1148public:1149using RangeMeasure = std::vector<std::pair<double, double>>;1151template <typename Op>1152static RangeMeasure mapRangeMeasure(RangeMeasure data, Op op) {1153for (auto& rangeMeasure : data) {1154rangeMeasure.first = op(rangeMeasure.first);1155}1156return data;1157}1159static RangeMeasure collectRangeMeasure(std::vector<Result> const& results);1161template <typename Op>1162BigO(char const* bigOName, RangeMeasure const& rangeMeasure, Op rangeToN)1163: BigO(bigOName, mapRangeMeasure(rangeMeasure, rangeToN)) {}1165template <typename Op>1166BigO(std::string bigOName, RangeMeasure const& rangeMeasure, Op rangeToN)1167: BigO(std::move(bigOName), mapRangeMeasure(rangeMeasure, rangeToN)) {}1169BigO(char const* bigOName, RangeMeasure const& scaledRangeMeasure);1170BigO(std::string bigOName, RangeMeasure const& scaledRangeMeasure);1171ANKERL_NANOBENCH(NODISCARD) std::string const& name() const noexcept;1172ANKERL_NANOBENCH(NODISCARD) double constant() const noexcept;1173ANKERL_NANOBENCH(NODISCARD) double normalizedRootMeanSquare() const noexcept;1174ANKERL_NANOBENCH(NODISCARD) bool operator<(BigO const& other) const noexcept;1176private:1177std::string mName{};1178double mConstant{};1179double mNormalizedRootMeanSquare{};1180};1181std::ostream& operator<<(std::ostream& os, BigO const& bigO);1182std::ostream& operator<<(std::ostream& os, std::vector<ankerl::nanobench::BigO> const& bigOs);1184} // namespace nanobench1185} // namespace ankerl1187// implementation /////////////////////////////////////////////////////////////////////////////////1189namespace ankerl {1190namespace nanobench {1192constexpr uint64_t(Rng::min)() {1193return 0;1194}1196constexpr uint64_t(Rng::max)() {1197return (std::numeric_limits<uint64_t>::max)();1198}1200ANKERL_NANOBENCH_NO_SANITIZE("integer", "undefined")1201uint64_t Rng::operator()() noexcept {1202auto x = mX;1204mX = UINT64_C(15241094284759029579) * mY;1205mY = rotl(mY - x, 27);1207return x;1208}1210ANKERL_NANOBENCH_NO_SANITIZE("integer", "undefined")1211uint32_t Rng::bounded(uint32_t range) noexcept {1212uint64_t const r32 = static_cast<uint32_t>(operator()());1213auto multiresult = r32 * range;1214return static_cast<uint32_t>(multiresult >> 32U);1215}1217double Rng::uniform01() noexcept {1218auto i = (UINT64_C(0x3ff) << 52U) | (operator()() >> 12U);1219// can't use union in c++ here for type puning, it's undefined behavior.1220// std::memcpy is optimized anyways.1221double d{};1222std::memcpy(&d, &i, sizeof(double));1223return d - 1.0;1224}1226template <typename Container>1227void Rng::shuffle(Container& container) noexcept {1228auto i = container.size();1229while (i > 1U) {1230using std::swap;1231auto n = operator()();1232// using decltype(i) instead of size_t to be compatible to containers with 32bit index (see #80)1233auto b1 = static_cast<decltype(i)>((static_cast<uint32_t>(n) * static_cast<uint64_t>(i)) >> 32U);1234swap(container[--i], container[b1]);1236auto b2 = static_cast<decltype(i)>(((n >> 32U) * static_cast<uint64_t>(i)) >> 32U);1237swap(container[--i], container[b2]);1238}1239}1241ANKERL_NANOBENCH_NO_SANITIZE("integer", "undefined")1242constexpr uint64_t Rng::rotl(uint64_t x, unsigned k) noexcept {1243return (x << k) | (x >> (64U - k));1244}1246namespace detail {1248template <typename SetupOp>1249class SetupRunner {1250public:
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.