mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-01-19 14:45:08 +01:00
Merge bitcoin/bitcoin#29458: refactor: Preallocate result in TryParseHex to avoid resizing
a19235c14b
Preallocate result in `TryParseHex` to avoid resizing (Lőrinc)b7489ecb52
Add benchmark for TryParseHex (Lőrinc) Pull request description: This pull request introduces optimizations to the `TryParseHex` function, focusing primarily on the ideal case (valid hexadecimal input without spaces). A new benchmark, `HexParse` was introduced in a separate commit. The main optimization preallocates the result vector based on the input string's length. This aims to completely avoid costly dynamic reallocations when no spaces are present. ------------ Before: ``` | ns/base16 | base16/s | err% | total | benchmark |--------------------:|--------------------:|--------:|----------:|:---------- | 1.60 | 623,238,893.11 | 0.3% | 0.01 | `HexParse` | 1.65 | 606,747,566.34 | 0.6% | 0.01 | `HexParse` | 1.60 | 626,149,544.07 | 0.3% | 0.01 | `HexParse` ``` After: ``` | ns/base16 | base16/s | err% | total | benchmark |--------------------:|--------------------:|--------:|----------:|:---------- | 0.68 | 1,465,555,976.27 | 0.8% | 0.01 | `HexParse` | 0.68 | 1,472,962,920.18 | 0.3% | 0.01 | `HexParse` | 0.68 | 1,476,159,423.00 | 0.3% | 0.01 | `HexParse` ``` ACKs for top commit: achow101: ACKa19235c14b
hebasto: ACKa19235c14b
. andrewtoth: Re-ACKa19235c14b
Empact: Re-ACKa19235c14b
Tree-SHA512: e09a59791104be3fd1026862ce98de9efafa1f949626fa01e3b7d58e6a2ef02a11f0de55ddba5c43230a53effd24e6d368c1e12848b17e8ce91d7908a59333f0
This commit is contained in:
commit
6dda050865
@ -42,6 +42,7 @@ bench_bench_bitcoin_SOURCES = \
|
||||
bench/merkle_root.cpp \
|
||||
bench/nanobench.cpp \
|
||||
bench/nanobench.h \
|
||||
bench/parse_hex.cpp \
|
||||
bench/peer_eviction.cpp \
|
||||
bench/poly1305.cpp \
|
||||
bench/pool.cpp \
|
||||
|
36
src/bench/parse_hex.cpp
Normal file
36
src/bench/parse_hex.cpp
Normal file
@ -0,0 +1,36 @@
|
||||
// Copyright (c) 2024- The Bitcoin Core developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include <bench/bench.h>
|
||||
#include <random.h>
|
||||
#include <stddef.h>
|
||||
#include <util/strencodings.h>
|
||||
#include <cassert>
|
||||
#include <optional>
|
||||
#include <vector>
|
||||
|
||||
std::string generateHexString(size_t length) {
|
||||
const auto hex_digits = "0123456789ABCDEF";
|
||||
FastRandomContext rng(/*fDeterministic=*/true);
|
||||
|
||||
std::string data;
|
||||
while (data.size() < length) {
|
||||
auto digit = hex_digits[rng.randbits(4)];
|
||||
data.push_back(digit);
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
static void HexParse(benchmark::Bench& bench)
|
||||
{
|
||||
auto data = generateHexString(130); // Generates 678B0EDA0A1FD30904D5A65E3568DB82DB2D918B0AD8DEA18A63FECCB877D07CAD1495C7157584D877420EF38B8DA473A6348B4F51811AC13C786B962BEE5668F9 by default
|
||||
|
||||
bench.batch(data.size()).unit("base16").run([&] {
|
||||
auto result = TryParseHex(data);
|
||||
assert(result != std::nullopt); // make sure we're measuring the successful case
|
||||
ankerl::nanobench::doNotOptimizeAway(result);
|
||||
});
|
||||
}
|
||||
|
||||
BENCHMARK(HexParse, benchmark::PriorityLevel::HIGH);
|
@ -81,6 +81,8 @@ template <typename Byte>
|
||||
std::optional<std::vector<Byte>> TryParseHex(std::string_view str)
|
||||
{
|
||||
std::vector<Byte> vch;
|
||||
vch.reserve(str.size() / 2); // two hex characters form a single byte
|
||||
|
||||
auto it = str.begin();
|
||||
while (it != str.end()) {
|
||||
if (IsSpace(*it)) {
|
||||
|
Loading…
Reference in New Issue
Block a user