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. Testing with various buffer sizes showed that 16 KiB provides the best performance.
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.
BufferedFile
was avoided for both reads and writes due to its unrelated operations and potential deprecation.
Microbenchmarks show a ~23%/19% 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=‘ReadBlockFromDiskTest|SaveBlockToDiskBench’ -min-time=10000
Before:
ns/op | op/s | err% | total | benchmark |
---|---|---|---|---|
2,288,264.16 | 437.01 | 0.2% | 11.00 | ReadBlockFromDiskBench |
5,260,934.43 | 190.08 | 1.2% | 11.08 | SaveBlockToDiskBench |
After optimization: Buffer serialization reads in UndoReadFromDisk and ReadBlockFromDisk
(23% faster read):
ns/op | op/s | err% | total | benchmark |
---|---|---|---|---|
1,847,259.64 | 541.34 | 0.2% | 11.03 | ReadBlockFromDiskBench |
After optimization: Buffer serialization writes in UndoWriteToDisk and WriteBlockToDisk
(19% faster write):
ns/op | op/s | err% | total | benchmark |
---|---|---|---|---|
4,394,044.07 | 227.58 | 1.3% | 10.93 | SaveBlockToDiskBench |