mirror of
https://github.com/bitcoin/bitcoin.git
synced 2026-04-07 06:07:32 +02:00
optimization: bulk serialization writes in WriteBlockUndo and WriteBlock
Similarly to the serialization reads optimization, buffered writes will enable batched XOR calculations. This is especially beneficial since the current implementation requires copying the write input's `std::span` to perform obfuscation. Batching allows us to apply XOR operations on the internal buffer instead, reducing unnecessary data copying and improving performance. ------ > macOS Sequoia 15.3.1 > C++ compiler .......................... Clang 19.1.7 > cmake -B build -DBUILD_BENCH=ON -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ && cmake --build build -j$(nproc) && build/bin/bench_bitcoin -filter='WriteBlockBench' -min-time=10000 Before: | ns/op | op/s | err% | total | benchmark |--------------------:|--------------------:|--------:|----------:|:---------- | 5,149,564.31 | 194.19 | 0.8% | 10.95 | `WriteBlockBench` After: | ns/op | op/s | err% | total | benchmark |--------------------:|--------------------:|--------:|----------:|:---------- | 2,990,564.63 | 334.39 | 1.5% | 11.27 | `WriteBlockBench` ------ > Ubuntu 24.04.2 LTS > C++ compiler .......................... GNU 13.3.0 > cmake -B build -DBUILD_BENCH=ON -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++ && cmake --build build -j$(nproc) && build/bin/bench_bitcoin -filter='WriteBlockBench' -min-time=20000 Before: | ns/op | op/s | err% | ins/op | cyc/op | IPC | bra/op | miss% | total | benchmark |--------------------:|--------------------:|--------:|----------------:|----------------:|-------:|---------------:|--------:|----------:|:---------- | 5,152,973.58 | 194.06 | 2.2% | 19,350,886.41 | 8,784,539.75 | 2.203 | 3,079,335.21 | 0.4% | 23.18 | `WriteBlockBench` After: | ns/op | op/s | err% | ins/op | cyc/op | IPC | bra/op | miss% | total | benchmark |--------------------:|--------------------:|--------:|----------------:|----------------:|-------:|---------------:|--------:|----------:|:---------- | 4,145,681.13 | 241.21 | 4.0% | 15,337,596.85 | 5,732,186.47 | 2.676 | 2,239,662.64 | 0.1% | 23.94 | `WriteBlockBench` Co-authored-by: Ryan Ofsky <ryan@ofsky.org> Co-authored-by: Cory Fields <cory-nospam-@coryfields.com>
This commit is contained in:
@@ -942,11 +942,12 @@ bool BlockManager::WriteBlockUndo(const CBlockUndo& blockundo, BlockValidationSt
|
||||
|
||||
{
|
||||
// Open history file to append
|
||||
AutoFile fileout{OpenUndoFile(pos)};
|
||||
if (fileout.IsNull()) {
|
||||
AutoFile file{OpenUndoFile(pos)};
|
||||
if (file.IsNull()) {
|
||||
LogError("OpenUndoFile failed for %s while writing block undo", pos.ToString());
|
||||
return FatalError(m_opts.notifications, state, _("Failed to write undo data."));
|
||||
}
|
||||
BufferedWriter fileout{file};
|
||||
|
||||
// Write index header
|
||||
fileout << GetParams().MessageStart() << blockundo_size;
|
||||
@@ -959,11 +960,7 @@ bool BlockManager::WriteBlockUndo(const CBlockUndo& blockundo, BlockValidationSt
|
||||
fileout << blockundo << hasher.GetHash();
|
||||
}
|
||||
|
||||
// Make sure `AutoFile` goes out of scope before we call `FlushUndoFile`
|
||||
if (fileout.fclose()) {
|
||||
LogError("WriteBlockUndo: fclose failed");
|
||||
return false;
|
||||
}
|
||||
fileout.flush(); // Make sure `AutoFile`/`BufferedWriter` go out of scope before we call `FlushUndoFile`
|
||||
}
|
||||
|
||||
// rev files are written in block height order, whereas blk files are written as blocks come in (often out of order)
|
||||
@@ -1090,12 +1087,13 @@ FlatFilePos BlockManager::WriteBlock(const CBlock& block, int nHeight)
|
||||
LogError("FindNextBlockPos failed for %s while writing block", pos.ToString());
|
||||
return FlatFilePos();
|
||||
}
|
||||
AutoFile fileout{OpenBlockFile(pos, /*fReadOnly=*/false)};
|
||||
if (fileout.IsNull()) {
|
||||
AutoFile file{OpenBlockFile(pos, /*fReadOnly=*/false)};
|
||||
if (file.IsNull()) {
|
||||
LogError("OpenBlockFile failed for %s while writing block", pos.ToString());
|
||||
m_opts.notifications.fatalError(_("Failed to write block."));
|
||||
return FlatFilePos();
|
||||
}
|
||||
BufferedWriter fileout{file};
|
||||
|
||||
// Write index header
|
||||
fileout << GetParams().MessageStart() << block_size;
|
||||
|
||||
Reference in New Issue
Block a user