mirror of
https://github.com/bitcoin/bitcoin.git
synced 2026-04-12 00:27:53 +02:00
refactor: improve benchmark setup and execution for various tests
Note that `make_hard_case` already clears the UTXO pool in `coin_selection.cpp`. ./build/bin/bench_bitcoin -filter='^(BnBExhaustion|AddrManAddThenGood|DeserializeBlockTest|DeserializeAndCheckBlockTest|CheckBlockTest|LoadExternalBlockFile|FindByte|WalletCreatePlain|WalletCreateEncrypted|WalletLoadingDescriptors)$' | ns/op | op/s | err% | total | benchmark |--------------------:|--------------------:|--------:|----------:|:---------- | 15,088,500.00 | 66.28 | 0.2% | 0.17 | `AddrManAddThenGood` | 179,208.00 | 5,580.11 | 2.0% | 0.00 | `BnBExhaustion` | ns/block | block/s | err% | total | benchmark |--------------------:|--------------------:|--------:|----------:|:---------- | 318,166.00 | 3,143.01 | 3.5% | 0.00 | `CheckBlockTest` | 886,750.00 | 1,127.71 | 0.8% | 0.01 | `DeserializeBlockTest` | ns/op | op/s | err% | total | benchmark |--------------------:|--------------------:|--------:|----------:|:---------- | 42.00 | 23,809,523.81 | 2.4% | 0.00 | `FindByte` | 5,473,208.00 | 182.71 | 0.4% | 0.06 | `LoadExternalBlockFile` | 584,168,041.00 | 1.71 | 0.3% | 6.43 | `WalletCreateEncrypted` | 168,040,458.00 | 5.95 | 1.1% | 1.85 | `WalletCreatePlain` | 155,446,625.00 | 6.43 | 0.7% | 0.78 | `WalletLoadingDescriptors` | ns/op | op/s | err% | total | benchmark |--------------------:|--------------------:|--------:|----------:|:---------- | 14,894,917.00 | 67.14 | 0.3% | 0.16 | `AddrManAddThenGood` | 177,667.00 | 5,628.51 | 1.3% | 0.00 | `BnBExhaustion` | ns/block | block/s | err% | total | benchmark |--------------------:|--------------------:|--------:|----------:|:---------- | 313,791.00 | 3,186.83 | 3.8% | 0.00 | `CheckBlockTest` | 888,208.00 | 1,125.86 | 0.7% | 0.01 | `DeserializeBlockTest` | ns/op | op/s | err% | total | benchmark |--------------------:|--------------------:|--------:|----------:|:---------- | 41.00 | 24,390,243.90 | 2.4% | 0.00 | `FindByte` | 5,445,208.00 | 183.65 | 1.0% | 0.06 | `LoadExternalBlockFile` | 581,800,500.00 | 1.72 | 0.4% | 6.40 | `WalletCreateEncrypted` | 166,035,583.00 | 6.02 | 0.5% | 1.82 | `WalletCreatePlain` | 153,574,792.00 | 6.51 | 0.1% | 0.77 | `WalletLoadingDescriptors`
This commit is contained in:
@@ -161,18 +161,13 @@ static void AddrManAddThenGood(benchmark::Bench& bench)
|
||||
|
||||
CreateAddresses();
|
||||
|
||||
bench.run([&] {
|
||||
// To make the benchmark independent of the number of evaluations, we always prepare a new addrman.
|
||||
// This is necessary because AddrMan::Good() method modifies the object, affecting the timing of subsequent calls
|
||||
// to the same method and we want to do the same amount of work in every loop iteration.
|
||||
//
|
||||
// This has some overhead (exactly the result of AddrManAdd benchmark), but that overhead is constant so improvements in
|
||||
// AddrMan::Good() will still be noticeable.
|
||||
AddrMan addrman{EMPTY_NETGROUPMAN, /*deterministic=*/false, ADDRMAN_CONSISTENCY_CHECK_RATIO};
|
||||
AddAddressesToAddrMan(addrman);
|
||||
|
||||
markSomeAsGood(addrman);
|
||||
});
|
||||
std::optional<AddrMan> addrman;
|
||||
bench.epochIterations(1)
|
||||
.setup([&] {
|
||||
addrman.emplace(EMPTY_NETGROUPMAN, /*deterministic=*/false, ADDRMAN_CONSISTENCY_CHECK_RATIO);
|
||||
AddAddressesToAddrMan(*addrman);
|
||||
})
|
||||
.run([&] { markSomeAsGood(*addrman); });
|
||||
}
|
||||
|
||||
BENCHMARK(AddrManAdd);
|
||||
|
||||
@@ -27,38 +27,30 @@
|
||||
|
||||
static void DeserializeBlockTest(benchmark::Bench& bench)
|
||||
{
|
||||
DataStream stream(benchmark::data::block413567);
|
||||
std::byte a{0};
|
||||
stream.write({&a, 1}); // Prevent compaction
|
||||
|
||||
bench.unit("block").run([&] {
|
||||
CBlock block;
|
||||
stream >> TX_WITH_WITNESS(block);
|
||||
bool rewound = stream.Rewind(benchmark::data::block413567.size());
|
||||
assert(rewound);
|
||||
});
|
||||
DataStream stream;
|
||||
bench.unit("block").epochIterations(1)
|
||||
.setup([&] { stream = DataStream{benchmark::data::block413567}; })
|
||||
.run([&] { CBlock block; stream >> TX_WITH_WITNESS(block); });
|
||||
}
|
||||
|
||||
static void DeserializeAndCheckBlockTest(benchmark::Bench& bench)
|
||||
static void CheckBlockTest(benchmark::Bench& bench)
|
||||
{
|
||||
DataStream stream(benchmark::data::block413567);
|
||||
std::byte a{0};
|
||||
stream.write({&a, 1}); // Prevent compaction
|
||||
|
||||
ArgsManager bench_args;
|
||||
const auto chainParams = CreateChainParams(bench_args, ChainType::MAIN);
|
||||
|
||||
bench.unit("block").run([&] {
|
||||
CBlock block; // Note that CBlock caches its checked state, so we need to recreate it here
|
||||
stream >> TX_WITH_WITNESS(block);
|
||||
bool rewound = stream.Rewind(benchmark::data::block413567.size());
|
||||
assert(rewound);
|
||||
|
||||
BlockValidationState validationState;
|
||||
bool checked = CheckBlock(block, validationState, chainParams->GetConsensus());
|
||||
assert(checked);
|
||||
});
|
||||
CBlock block;
|
||||
bench.unit("block").epochIterations(1)
|
||||
.setup([&] {
|
||||
block = CBlock{};
|
||||
DataStream stream{benchmark::data::block413567};
|
||||
stream >> TX_WITH_WITNESS(block);
|
||||
})
|
||||
.run([&] {
|
||||
BlockValidationState validationState;
|
||||
bool checked = CheckBlock(block, validationState, chainParams->GetConsensus());
|
||||
assert(checked);
|
||||
});
|
||||
}
|
||||
|
||||
BENCHMARK(DeserializeBlockTest);
|
||||
BENCHMARK(DeserializeAndCheckBlockTest);
|
||||
BENCHMARK(CheckBlockTest);
|
||||
|
||||
@@ -124,17 +124,14 @@ static CAmount make_hard_case(int utxos, std::vector<OutputGroup>& utxo_pool)
|
||||
|
||||
static void BnBExhaustion(benchmark::Bench& bench)
|
||||
{
|
||||
// Setup
|
||||
std::vector<OutputGroup> utxo_pool;
|
||||
|
||||
bench.run([&] {
|
||||
// Benchmark
|
||||
CAmount target = make_hard_case(17, utxo_pool);
|
||||
(void)SelectCoinsBnB(utxo_pool, target, /*cost_of_change=*/0, MAX_STANDARD_TX_WEIGHT); // Should exhaust
|
||||
|
||||
// Cleanup
|
||||
utxo_pool.clear();
|
||||
});
|
||||
CAmount target;
|
||||
bench.epochIterations(1)
|
||||
.setup([&] { target = make_hard_case(17, utxo_pool); })
|
||||
.run([&] {
|
||||
auto res{SelectCoinsBnB(utxo_pool, target, /*cost_of_change=*/0, MAX_STANDARD_TX_WEIGHT)}; // Should exhaust
|
||||
ankerl::nanobench::doNotOptimizeAway(res);
|
||||
});
|
||||
}
|
||||
|
||||
BENCHMARK(CoinSelection);
|
||||
|
||||
@@ -62,12 +62,17 @@ static void LoadExternalBlockFile(benchmark::Bench& bench)
|
||||
|
||||
std::multimap<uint256, FlatFilePos> blocks_with_unknown_parent;
|
||||
FlatFilePos pos;
|
||||
bench.run([&] {
|
||||
// "rb" is "binary, O_RDONLY", positioned to the start of the file.
|
||||
// The file will be closed by LoadExternalBlockFile().
|
||||
AutoFile file{fsbridge::fopen(blkfile, "rb")};
|
||||
testing_setup->m_node.chainman->LoadExternalBlockFile(file, &pos, &blocks_with_unknown_parent);
|
||||
});
|
||||
bench.epochIterations(1)
|
||||
.setup([&] {
|
||||
blocks_with_unknown_parent.clear();
|
||||
pos = FlatFilePos{};
|
||||
})
|
||||
.run([&] {
|
||||
// "rb" is "binary, O_RDONLY", positioned to the start of the file.
|
||||
// The file will be closed by LoadExternalBlockFile().
|
||||
AutoFile file{fsbridge::fopen(blkfile, "rb")};
|
||||
testing_setup->m_node.chainman->LoadExternalBlockFile(file, &pos, &blocks_with_unknown_parent);
|
||||
});
|
||||
fs::remove(blkfile);
|
||||
}
|
||||
|
||||
|
||||
@@ -22,10 +22,9 @@ static void FindByte(benchmark::Bench& bench)
|
||||
file.seek(0, SEEK_SET);
|
||||
BufferedFile bf{file, /*nBufSize=*/file_size + 1, /*nRewindIn=*/file_size};
|
||||
|
||||
bench.run([&] {
|
||||
bf.SetPos(0);
|
||||
bf.FindByte(std::byte(1));
|
||||
});
|
||||
bench.epochIterations(1)
|
||||
.setup([&] { bf.SetPos(0); })
|
||||
.run([&] { bf.FindByte(std::byte(1)); });
|
||||
|
||||
assert(file.fclose() == 0);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user