mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-01-24 18:23:26 -03:00
optimization: Bulk serialization writes in SaveBlockUndo
and SaveBlock
Similarly to the serialization reads, buffered writes will enable batched xor calculations - especially since currently we need to copy the write inputs Span to do the obfuscation on it, batching enables doing the xor on the internal buffer instead. Before: | ns/op | op/s | err% | total | benchmark |--------------------:|--------------------:|--------:|----------:|:---------- | 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` Co-authored-by: Cory Fields <cory-nospam-@coryfields.com>
This commit is contained in:
parent
34eafa54a6
commit
1f736fbdb4
1 changed files with 36 additions and 16 deletions
|
@ -951,31 +951,38 @@ bool BlockManager::SaveBlockUndo(const CBlockUndo& blockundo, BlockValidationSta
|
||||||
const BlockfileType type = BlockfileTypeForHeight(block.nHeight);
|
const BlockfileType type = BlockfileTypeForHeight(block.nHeight);
|
||||||
auto& cursor = *Assert(WITH_LOCK(cs_LastBlockFile, return m_blockfile_cursors[type]));
|
auto& cursor = *Assert(WITH_LOCK(cs_LastBlockFile, return m_blockfile_cursors[type]));
|
||||||
|
|
||||||
// Write undo information to disk
|
|
||||||
if (block.GetUndoPos().IsNull()) {
|
if (block.GetUndoPos().IsNull()) {
|
||||||
FlatFilePos pos;
|
FlatFilePos pos;
|
||||||
const uint32_t blockundo_size{static_cast<uint32_t>(GetSerializeSize(blockundo))};
|
const uint32_t blockundo_size{static_cast<uint32_t>(GetSerializeSize(blockundo))};
|
||||||
if (!FindUndoPos(state, block.nFile, pos, blockundo_size + UNDO_DATA_DISK_OVERHEAD)) {
|
if (!FindUndoPos(state, block.nFile, pos, UNDO_DATA_DISK_OVERHEAD + blockundo_size)) {
|
||||||
LogError("%s: FindUndoPos failed\n", __func__);
|
LogError("%s: FindUndoPos failed\n", __func__);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// Open history file to append
|
AutoFile fileout{m_undo_file_seq.Open(pos, false), {}}; // We'll obfuscate ourselves
|
||||||
AutoFile fileout{OpenUndoFile(pos)};
|
|
||||||
if (fileout.IsNull()) {
|
if (fileout.IsNull()) {
|
||||||
LogError("%s: OpenUndoFile failed\n", __func__);
|
LogError("%s: OpenUndoFile failed\n", __func__);
|
||||||
return FatalError(m_opts.notifications, state, _("Failed to write undo data."));
|
return FatalError(m_opts.notifications, state, _("Failed to write undo data."));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write index header
|
{
|
||||||
fileout << GetParams().MessageStart() << blockundo_size;
|
DataStream header;
|
||||||
|
header.reserve(BLOCK_SERIALIZATION_HEADER_SIZE);
|
||||||
|
header << GetParams().MessageStart() << blockundo_size;
|
||||||
|
util::Xor(header, m_xor_key, pos.nPos);
|
||||||
|
fileout.write(header);
|
||||||
|
}
|
||||||
pos.nPos += BLOCK_SERIALIZATION_HEADER_SIZE;
|
pos.nPos += BLOCK_SERIALIZATION_HEADER_SIZE;
|
||||||
fileout << blockundo;
|
{
|
||||||
|
HashWriter hasher;
|
||||||
|
hasher << block.pprev->GetBlockHash();
|
||||||
|
hasher << blockundo;
|
||||||
|
|
||||||
// calculate & write checksum
|
DataStream undo_data;
|
||||||
HashWriter hasher{};
|
undo_data.reserve(blockundo_size + sizeof(uint256));
|
||||||
hasher << block.pprev->GetBlockHash();
|
undo_data << blockundo << hasher.GetHash();
|
||||||
hasher << blockundo;
|
util::Xor(undo_data, m_xor_key, pos.nPos);
|
||||||
fileout << hasher.GetHash();
|
fileout.write(undo_data);
|
||||||
|
}
|
||||||
|
|
||||||
// rev files are written in block height order, whereas blk files are written as blocks come in (often out of order)
|
// rev files are written in block height order, whereas blk files are written as blocks come in (often out of order)
|
||||||
// we want to flush the rev (undo) file once we've written the last block, which is indicated by the last height
|
// we want to flush the rev (undo) file once we've written the last block, which is indicated by the last height
|
||||||
|
@ -1105,21 +1112,34 @@ bool BlockManager::ReadRawBlockFromDisk(std::vector<uint8_t>& block, const FlatF
|
||||||
FlatFilePos BlockManager::SaveBlock(const CBlock& block, int nHeight)
|
FlatFilePos BlockManager::SaveBlock(const CBlock& block, int nHeight)
|
||||||
{
|
{
|
||||||
const uint32_t block_size{static_cast<uint32_t>(GetSerializeSize(TX_WITH_WITNESS(block)))};
|
const uint32_t block_size{static_cast<uint32_t>(GetSerializeSize(TX_WITH_WITNESS(block)))};
|
||||||
FlatFilePos pos{FindNextBlockPos(block_size + BLOCK_SERIALIZATION_HEADER_SIZE, nHeight, block.GetBlockTime())};
|
FlatFilePos pos{FindNextBlockPos(BLOCK_SERIALIZATION_HEADER_SIZE + block_size, nHeight, block.GetBlockTime())};
|
||||||
if (pos.IsNull()) {
|
if (pos.IsNull()) {
|
||||||
LogError("%s: FindNextBlockPos failed\n", __func__);
|
LogError("%s: FindNextBlockPos failed\n", __func__);
|
||||||
return FlatFilePos();
|
return FlatFilePos();
|
||||||
}
|
}
|
||||||
AutoFile fileout{OpenBlockFile(pos)};
|
AutoFile fileout{m_block_file_seq.Open(pos, false), {}}; // We'll obfuscate ourselves
|
||||||
if (fileout.IsNull()) {
|
if (fileout.IsNull()) {
|
||||||
LogError("%s: OpenBlockFile failed\n", __func__);
|
LogError("%s: OpenBlockFile failed\n", __func__);
|
||||||
m_opts.notifications.fatalError(_("Failed to write block."));
|
m_opts.notifications.fatalError(_("Failed to write block."));
|
||||||
return FlatFilePos();
|
return FlatFilePos();
|
||||||
}
|
}
|
||||||
|
|
||||||
fileout << GetParams().MessageStart() << block_size;
|
{
|
||||||
|
DataStream header;
|
||||||
|
header.reserve(BLOCK_SERIALIZATION_HEADER_SIZE);
|
||||||
|
header << GetParams().MessageStart() << block_size;
|
||||||
|
util::Xor(header, m_xor_key, pos.nPos);
|
||||||
|
fileout.write(header);
|
||||||
|
}
|
||||||
pos.nPos += BLOCK_SERIALIZATION_HEADER_SIZE;
|
pos.nPos += BLOCK_SERIALIZATION_HEADER_SIZE;
|
||||||
fileout << TX_WITH_WITNESS(block);
|
{
|
||||||
|
DataStream block_data;
|
||||||
|
block_data.reserve(block_size);
|
||||||
|
block_data << TX_WITH_WITNESS(block);
|
||||||
|
util::Xor(block_data, m_xor_key, pos.nPos);
|
||||||
|
fileout.write(block_data);
|
||||||
|
}
|
||||||
|
|
||||||
return pos;
|
return pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue