CheckBlock
’s latency is critical for efficiently validating correct inputs during transaction validation, including mempool acceptance and new block creation.
This PR improves performance and maintainability by introducing the following changes:
- Benchmarks now measure
CheckBlock
performance for both valid and invalid cases separately (without serialization cost), ensuring accurate insights into critical paths. - Simplified checks for the most common cases (1 or 2 inputs - 70-90% of transactions have a single input).
- Optimized the general case by replacing
std::set
with sortedstd::vector
for improved locality. - Added tests for
uint256
,transaction_identifier
, andCOutPoint
comparisons, and separate validation tests against previous implementation to ensure correctness.
The goal of this change is to make block validation faster via a low-risk alternative.
Before:
ns/block | block/s | err% | total | benchmark |
---|---|---|---|---|
361,535.93 | 2,765.98 | 0.5% | 11.02 | CheckBlockBench |
ns/op | op/s | err% | total | benchmark |
---|---|---|---|---|
3,176,164.16 | 314.85 | 0.4% | 10.98 | DuplicateInputs |
After:
ns/block | block/s | err% | total | benchmark |
---|---|---|---|---|
186,777.35 | 5,353.97 | 0.3% | 10.98 | CheckBlockBench |
ns/op | op/s | err% | total | benchmark |
---|---|---|---|---|
985,571.51 | 1,014.64 | 0.8% | 10.91 | DuplicateInputs |
~2x faster CheckBlockBench
and ~3x faster DuplicateInputs
Before:
ns/block | block/s | err% | ins/block | cyc/block | IPC | bra/block | miss% | total | benchmark |
---|---|---|---|---|---|---|---|---|---|
1,096,261.84 | 912.19 | 0.1% | 7,963,390.88 | 3,487,375.26 | 2.283 | 1,266,941.00 | 1.8% | 11.03 | CheckBlockBench |
ns/op | op/s | err% | ins/op | cyc/op | IPC | bra/op | miss% | total | benchmark |
---|---|---|---|---|---|---|---|---|---|
8,366,309.48 | 119.53 | 0.0% | 23,865,177.67 | 26,620,160.23 | 0.897 | 5,972,887.41 | 4.0% | 10.78 | DuplicateInputs |
After:
ns/block | block/s | err% | ins/block | cyc/block | IPC | bra/block | miss% | total | benchmark |
---|---|---|---|---|---|---|---|---|---|
845,976.08 | 1,182.07 | 0.1% | 6,518,255.88 | 2,691,237.50 | 2.422 | 922,585.85 | 1.5% | 10.78 | `CheckBlockBench |
ns/op | op/s | err% | ins/op | cyc/op | IPC | bra/op | miss% | total | benchmark |
---|---|---|---|---|---|---|---|---|---|
3,923,195.87 | 254.89 | 0.1% | 14,660,648.04 | 12,480,569.27 | 1.175 | 3,681,101.94 | 4.0% | 11.00 | DuplicateInputs |
~1.3x faster CheckBlockBench
and ~2x faster DuplicateInputs
While the point of the change isn’t necessarily to speed up IBD, I’ve measured a reindex-chainstate
until 879000
blocks multiple times - which consistently showed a ~1% speedup.
0hyperfine \
1--runs 2 \
2--parameter-list COMMIT 2a170319e462ff35129b652f071ba0d0816468dc,d1689061579203ddbe0376a700890c1081b33f20 \
3--prepare 'rm -rfd /mnt/my_storage/BitcoinData/debug.log build/ && git checkout {COMMIT} && cmake -B build -DCMAKE_BUILD_TYPE=Release -DBUILD_UTIL=OFF -DBUILD_TX=OFF -DBUILD_TESTS=OFF -DENABLE_WALLET=OFF -DINSTALL_MAN=OFF && cmake --build build -j$(nproc)' \
4--cleanup 'mv /mnt/my_storage/BitcoinData/debug.log /mnt/my_storage/logs/debug-{COMMIT}-$(date +%s.log)' \
5'COMMIT={COMMIT} ./build/src/bitcoind -datadir=/mnt/my_storage/BitcoinData -stopatheight=879000 -dbcache=30000 -reindex-chainstate -connect=0 -printtoconsole=0'
6
7Benchmark 1: COMMIT=2a170319e462ff35129b652f071ba0d0816468dc ./build/src/bitcoind -datadir=/mnt/my_storage/BitcoinData -stopatheight=879000 -dbcache=30000 -reindex-chainstate -connect=0 -printtoconsole=0
8 Time (mean ± σ): 19928.276 s ± 7.167 s [User: 39987.270 s, System: 829.023 s]
9 Range (min … max): 19923.208 s … 19933.345 s 2 runs
10
11Benchmark 2: COMMIT=d1689061579203ddbe0376a700890c1081b33f20 ./build/src/bitcoind -datadir=/mnt/my_storage/BitcoinData -stopatheight=879000 -dbcache=30000 -reindex-chainstate -connect=0 -printtoconsole=0
12 Time (mean ± σ): 19709.943 s ± 39.615 s [User: 39803.778 s, System: 826.234 s]
13 Range (min … max): 19681.931 s … 19737.955 s 2 runs
14
15Summary
16 COMMIT=d1689061579203ddbe0376a700890c1081b33f20 ./build/src/bitcoind -datadir=/mnt/my_storage/BitcoinData -stopatheight=879000 -dbcache=30000 -reindex-chainstate -connect=0 -printtoconsole=0 ran
17 1.01 ± 0.00 times faster than COMMIT=2a170319e462ff35129b652f071ba0d0816468dc ./build/src/bitcoind -datadir=/mnt/my_storage/BitcoinData -stopatheight=879000 -dbcache=30000 -reindex-chainstate -connect=0 -printtoconsole=0
Related PRs: