An alternative implementation of #31539, where the whole block is read into memory instead of doing it in chunks, as suggested by @theuni.
This is a follow-up to #31490 (first few commits duplicated here, hence a draft) and a precursor to #31144.
Currently, obfuscation operations are performed byte-by-byte during serialization. Buffering the reads allows batching these operations (implemented in #31144) and improves file access efficiency by reducing fread calls and associated locking overhead. For writes, buffering enables batched obfuscations directly on the internal buffer, avoiding the need to copy input spans for obfuscation. Xor key offsets are calculated based on the file position, and the batched obfuscation is applied before writing to disk.
2 full IBD runs against master for 870k blocks (seeded from real nodes) indicates a 6% total speedup.
0hyperfine --runs 2 --export-json /mnt/my_storage/ibd-xor-buffered.json --parameter-list COMMIT d73f37dda221835b5109ede1b84db2dc7c4b74a1,6853b2740851befffa3ca0b24d94212ed1e48d66 --prepare 'rm -rf /mnt/my_storage/BitcoinData/* && git checkout {COMMIT} && git clean -fxd && git reset --hard && 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)' 'COMMIT={COMMIT} ./build/src/bitcoind -datadir=/mnt/my_storage/BitcoinData -stopatheight=870000 -printtoconsole=0'
1
2Benchmark 1: COMMIT=d73f37dda221835b5109ede1b84db2dc7c4b74a1 ./build/src/bitcoind -datadir=/mnt/my_storage/BitcoinData -stopatheight=870000 -printtoconsole=0
3 Time (mean ± σ): 40216.674 s ± 113.132 s [User: 51496.289 s, System: 3541.340 s]
4 Range (min … max): 40136.678 s … 40296.671 s 2 runs
5
6Benchmark 2: COMMIT=6853b2740851befffa3ca0b24d94212ed1e48d66 ./build/src/bitcoind -datadir=/mnt/my_storage/BitcoinData -stopatheight=870000 -printtoconsole=0
7 Time (mean ± σ): 37964.015 s ± 624.115 s [User: 49086.037 s, System: 3375.072 s]
8 Range (min … max): 37522.699 s … 38405.331 s 2 runs
9
10Summary
11 COMMIT=6853b2740851befffa3ca0b24d94212ed1e48d66 ./build/src/bitcoind -datadir=/mnt/my_storage/BitcoinData -stopatheight=870000 -printtoconsole=0 ran
12 1.06 ± 0.02 times faster than COMMIT=d73f37dda221835b5109ede1b84db2dc7c4b74a1 ./build/src/bitcoind -datadir=/mnt/my_storage/BitcoinData -stopatheight=870000 -printtoconsole=0
Microbenchmarks show a ~27%/290% speedup (the followup XOR batching improves this further):
cmake -B build -DBUILD_BENCH=ON -DCMAKE_BUILD_TYPE=Release && cmake –build build -j$(nproc) && build/src/bench/bench_bitcoin -filter=‘ReadBlockFromDiskBench|SaveBlockToDiskBench’ -min-time=10000
Before:
ns/op | op/s | err% | total | benchmark |
---|---|---|---|---|
2,285,753.56 | 437.49 | 0.3% | 11.03 | ReadBlockFromDiskBench |
5,244,636.51 | 190.67 | 0.3% | 11.04 | SaveBlockToDiskBench |
After:
ns/op | op/s | err% | total | benchmark |
---|---|---|---|---|
1,787,371.46 | 559.48 | 1.6% | 11.16 | SaveBlockToDiskBench |
1,804,240.57 | 554.25 | 0.2% | 11.01 | ReadBlockFromDiskBench |