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.
501* * Register pressure: 4502* * State size: 128 bits503*504* This random generator is a drop-in replacement for the generators supplied by ``<random>``. It is not505* cryptographically secure. It's intended purpose is to be very fast so that benchmarks that make use506* of randomness are not distorted too much by the random generator.507*508* Rng also provides a few non-standard helpers, optimized for speed.509*/510class Rng final {511public:512/**513* @brief This RNG provides 64bit randomness.514*/515using result_type = uint64_t;517static constexpr uint64_t(min)();518static constexpr uint64_t(max)();520/**521* As a safety precaution, we don't allow copying. Copying a PRNG would mean you would have two random generators that produce the522* same sequence, which is generally not what one wants. Instead create a new rng with the default constructor Rng(), which is523* automatically seeded from `std::random_device`. If you really need a copy, use `copy()`.524*/525Rng(Rng const&) = delete;527/**528* Same as Rng(Rng const&), we don't allow assignment. If you need a new Rng create one with the default constructor Rng().529*/530Rng& operator=(Rng const&) = delete;532// moving is ok533Rng(Rng&&) noexcept = default;534Rng& operator=(Rng&&) noexcept = default;535~Rng() noexcept = default;537/**538* @brief Creates a new Random generator with random seed.539*540* Instead of a default seed (as the random generators from the STD), this properly seeds the random generator from541* `std::random_device`. It guarantees correct seeding. Note that seeding can be relatively slow, depending on the source of542* randomness used. So it is best to create a Rng once and use it for all your randomness purposes.543*/544Rng();546/*!547Creates a new Rng that is seeded with a specific seed. Each Rng created from the same seed will produce the same randomness548sequence. This can be useful for deterministic behavior.550@verbatim embed:rst551.. note::553The random algorithm might change between nanobench releases. Whenever a faster and/or better random554generator becomes available, I will switch the implementation.555@endverbatim557As per the Romu paper, this seeds the Rng with splitMix64 algorithm and performs 10 initial rounds for further mixing up of the558internal state.560@param seed The 64bit seed. All values are allowed, even 0.561*/562explicit Rng(uint64_t seed) noexcept;563Rng(uint64_t x, uint64_t y) noexcept;564explicit Rng(std::vector<uint64_t> const& data);566/**567* Creates a copy of the Rng, thus the copy provides exactly the same random sequence as the original.568*/569ANKERL_NANOBENCH(NODISCARD) Rng copy() const noexcept;571/**572* @brief Produces a 64bit random value. This should be very fast, thus it is marked as inline. In my benchmark, this is ~46 times573* faster than `std::default_random_engine` for producing 64bit random values. It seems that the fastest std contender is574* `std::mt19937_64`. Still, this RNG is 2-3 times as fast.575*576* @return uint64_t The next 64 bit random value.577*/578inline uint64_t operator()() noexcept;580// This is slightly biased. See582/**583* Generates a random number between 0 and range (excluding range).584*585* The algorithm only produces 32bit numbers, and is slightly biased. The effect is quite small unless your range is close to the586* maximum value of an integer. It is possible to correct the bias with rejection sampling (see587* [here](https://lemire.me/blog/2016/06/30/fast-random-shuffling/), but this is most likely irrelevant in practices for the588* purposes of this Rng.589*590* See Daniel Lemire's blog post [A fast alternative to the modulo591* reduction](https://lemire.me/blog/2016/06/27/a-fast-alternative-to-the-modulo-reduction/)592*593* @param range Upper exclusive range. E.g a value of 3 will generate random numbers 0, 1, 2.594* @return uint32_t Generated random values in range [0, range(.595*/596inline uint32_t bounded(uint32_t range) noexcept;598// random double in range [0, 1(599// see http://prng.di.unimi.it/601/**602* Provides a random uniform double value between 0 and 1. This uses the method described in [Generating uniform doubles in the603* unit interval](http://prng.di.unimi.it/), and is extremely fast.604*605* @return double Uniformly distributed double value in range [0,1(, excluding 1.606*/607inline double uniform01() noexcept;609/**610* Shuffles all entries in the given container. Although this has a slight bias due to the implementation of bounded(), this is611* preferable to `std::shuffle` because it is over 5 times faster. See Daniel Lemire's blog post [Fast random612* shuffling](https://lemire.me/blog/2016/06/30/fast-random-shuffling/).613*614* @param container The whole container will be shuffled.615*/616template <typename Container>617void shuffle(Container& container) noexcept;619/**620* Extracts the full state of the generator, e.g. for serialization. For this RNG this is just 2 values, but to stay API compatible621* with future implementations that potentially use more state, we use a vector.622*623* @return Vector containing the full state:624*/625ANKERL_NANOBENCH(NODISCARD) std::vector<uint64_t> state() const;627private:628static constexpr uint64_t rotl(uint64_t x, unsigned k) noexcept;630uint64_t mX;631uint64_t mY;632};634/**635* @brief Main entry point to nanobench's benchmarking facility.636*637* It holds configuration and results from one or more benchmark runs. Usually it is used in a single line, where the object is638* constructed, configured, and then a benchmark is run. E.g. like this:639*640* ankerl::nanobench::Bench().unit("byte").batch(1000).run("random fluctuations", [&] {641* // here be the benchmark code642* });643*644* In that example Bench() constructs the benchmark, it is then configured with unit() and batch(), and after configuration a645* benchmark is executed with run(). Once run() has finished, it prints the result to `std::cout`. It would also store the results646* in the Bench instance, but in this case the object is immediately destroyed so it's not available any more.647*/648ANKERL_NANOBENCH(IGNORE_PADDED_PUSH)649class Bench {650public:651/**652* @brief Creates a new benchmark for configuration and running of benchmarks.653*/654Bench();656Bench(Bench&& other) noexcept;657Bench& operator=(Bench&& other) noexcept(ANKERL_NANOBENCH(NOEXCEPT_STRING_MOVE));658Bench(Bench const& other);659Bench& operator=(Bench const& other);660~Bench() noexcept;662/*!663@brief Repeatedly calls `op()` based on the configuration, and performs measurements.665This call is marked with `noinline` to prevent the compiler to optimize beyond different benchmarks. This can have quite a big666effect on benchmark accuracy.668@verbatim embed:rst669.. note::671Each call to your lambda must have a side effect that the compiler can't possibly optimize it away. E.g. add a result to an672externally defined number (like `x` in the above example), and finally call `doNotOptimizeAway` on the variables the compiler673must not remove. You can also use :cpp:func:`ankerl::nanobench::doNotOptimizeAway` directly in the lambda, but be aware that674this has a small overhead.676@endverbatim678@tparam Op The code to benchmark.679*/680template <typename Op>681ANKERL_NANOBENCH(NOINLINE)682Bench& run(char const* benchmarkName, Op&& op);684template <typename Op>685ANKERL_NANOBENCH(NOINLINE)686Bench& run(std::string const& benchmarkName, Op&& op);688/**689* @brief Same as run(char const* benchmarkName, Op op), but instead uses the previously set name.690* @tparam Op The code to benchmark.691*/692template <typename Op>693ANKERL_NANOBENCH(NOINLINE)694Bench& run(Op&& op);696/**697* @brief Title of the benchmark, will be shown in the table header. Changing the title will start a new markdown table.698*699* @param benchmarkTitle The title of the benchmark.700*/701Bench& title(char const* benchmarkTitle);702Bench& title(std::string const& benchmarkTitle);704/**705* @brief Gets the title of the benchmark706*/707ANKERL_NANOBENCH(NODISCARD) std::string const& title() const noexcept;709/// Name of the benchmark, will be shown in the table row.710Bench& name(char const* benchmarkName);711Bench& name(std::string const& benchmarkName);712ANKERL_NANOBENCH(NODISCARD) std::string const& name() const noexcept;714/**715* @brief Set context information.716*717* The information can be accessed using custom render templates via `{{context(variableName)}}`.718* Trying to render a variable that hasn't been set before raises an exception.719* Not included in (default) markdown table.720*721* @see clearContext, render722*723* @param variableName The name of the context variable.724* @param variableValue The value of the context variable.725*/726Bench& context(char const* variableName, char const* variableValue);727Bench& context(std::string const& variableName, std::string const& variableValue);729/**730* @brief Reset context information.731*732* This may improve efficiency when using many context entries,733* or improve robustness by removing spurious context entries.734*735* @see context736*/737Bench& clearContext();739/**740* @brief Sets the batch size.741*742* E.g. number of processed byte, or some other metric for the size of the processed data in each iteration. If you benchmark743* hashing of a 1000 byte long string and want byte/sec as a result, you can specify 1000 as the batch size.744*745* @tparam T Any input type is internally cast to `double`.746* @param b batch size747*/748template <typename T>749Bench& batch(T b) noexcept;750ANKERL_NANOBENCH(NODISCARD) double batch() const noexcept;
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.