Merge bitcoin/bitcoin#31490: refactor: inline UndoWriteToDisk and WriteBlockToDisk to reduce serialization calls

223081ece6 scripted-diff: rename block and undo functions for consistency (Lőrinc)
baaa3b2846 refactor,blocks: remove costly asserts and modernize affected logs (Lőrinc)
fa39f27a0f refactor,blocks: deduplicate block's serialized size calculations (Lőrinc)
dfb2f9d004 refactor,blocks: inline `WriteBlockToDisk` (Lőrinc)
42bc491465 refactor,blocks: inline `UndoWriteToDisk` (Lőrinc)
86b85bb11f bench: add SaveBlockBench (Lőrinc)
34f9a0157a refactor,bench: rename bench/readblock.cpp to bench/readwriteblock.cpp (Lőrinc)

Pull request description:

  `UndoWriteToDisk` and `WriteBlockToDisk` were delegating a subset of their functionality to single-use methods that didn't optimally capture a meaningful chunk of the algorithm, resulting in calculating things twice (serialized size, header size).
  This change inlines the awkward methods (asserting that all previous behavior was retained), and in separate commits makes the usages less confusing.
  Besides making the methods slightly more intuitive, the refactorings reduce duplicate calculations as well.

  The speed difference is insignificant for now (~0.5% for the new `SaveBlockToDiskBench`), but are a cleanup for follow-ups such as https://github.com/bitcoin/bitcoin/pull/31539

ACKs for top commit:
  ryanofsky:
    Code review ACK 223081ece6. Since last review, "Save" was renamed to "Write", uint32_t references were dropped, some log statements and comments were improved as suggested, and a lot of tweaks made to commits and commit messages which should make this easier to review.
  hodlinator:
    ACK 223081ece6
  TheCharlatan:
    ACK 223081ece6
  andrewtoth:
    ACK 223081ece6

Tree-SHA512: 951bc8ad3504c510988afd95c561e3e259c6212bd14f6536fe56e8eb5bf5c35c32a368bbdb1d5aea1acc473d7e5bd9cdcde02008a148b05af1f955e413062d5c
This commit is contained in:
Ryan Ofsky
2025-01-22 11:49:36 -05:00
20 changed files with 179 additions and 204 deletions

View File

@@ -36,7 +36,7 @@ BOOST_AUTO_TEST_CASE(blockmanager_find_block_pos)
};
BlockManager blockman{*Assert(m_node.shutdown_signal), blockman_opts};
// simulate adding a genesis block normally
BOOST_CHECK_EQUAL(blockman.SaveBlockToDisk(params->GenesisBlock(), 0).nPos, BLOCK_SERIALIZATION_HEADER_SIZE);
BOOST_CHECK_EQUAL(blockman.WriteBlock(params->GenesisBlock(), 0).nPos, BLOCK_SERIALIZATION_HEADER_SIZE);
// simulate what happens during reindex
// simulate a well-formed genesis block being found at offset 8 in the blk00000.dat file
// the block is found at offset 8 because there is an 8 byte serialization header
@@ -49,7 +49,7 @@ BOOST_AUTO_TEST_CASE(blockmanager_find_block_pos)
// this is a check to make sure that https://github.com/bitcoin/bitcoin/issues/21379 does not recur
// 8 bytes (for serialization header) + 285 (for serialized genesis block) = 293
// add another 8 bytes for the second block's serialization header and we get 293 + 8 = 301
FlatFilePos actual{blockman.SaveBlockToDisk(params->GenesisBlock(), 1)};
FlatFilePos actual{blockman.WriteBlock(params->GenesisBlock(), 1)};
BOOST_CHECK_EQUAL(actual.nPos, BLOCK_SERIALIZATION_HEADER_SIZE + ::GetSerializeSize(TX_WITH_WITNESS(params->GenesisBlock())) + BLOCK_SERIALIZATION_HEADER_SIZE);
}
@@ -158,10 +158,10 @@ BOOST_AUTO_TEST_CASE(blockmanager_flush_block_file)
BOOST_CHECK_EQUAL(blockman.CalculateCurrentUsage(), 0);
// Write the first block to a new location.
FlatFilePos pos1{blockman.SaveBlockToDisk(block1, /*nHeight=*/1)};
FlatFilePos pos1{blockman.WriteBlock(block1, /*nHeight=*/1)};
// Write second block
FlatFilePos pos2{blockman.SaveBlockToDisk(block2, /*nHeight=*/2)};
FlatFilePos pos2{blockman.WriteBlock(block2, /*nHeight=*/2)};
// Two blocks in the file
BOOST_CHECK_EQUAL(blockman.CalculateCurrentUsage(), (TEST_BLOCK_SIZE + BLOCK_SERIALIZATION_HEADER_SIZE) * 2);
@@ -171,13 +171,13 @@ BOOST_AUTO_TEST_CASE(blockmanager_flush_block_file)
CBlock read_block;
BOOST_CHECK_EQUAL(read_block.nVersion, 0);
{
ASSERT_DEBUG_LOG("ReadBlockFromDisk: Errors in block header");
BOOST_CHECK(!blockman.ReadBlockFromDisk(read_block, pos1));
ASSERT_DEBUG_LOG("ReadBlock: Errors in block header");
BOOST_CHECK(!blockman.ReadBlock(read_block, pos1));
BOOST_CHECK_EQUAL(read_block.nVersion, 1);
}
{
ASSERT_DEBUG_LOG("ReadBlockFromDisk: Errors in block header");
BOOST_CHECK(!blockman.ReadBlockFromDisk(read_block, pos2));
ASSERT_DEBUG_LOG("ReadBlock: Errors in block header");
BOOST_CHECK(!blockman.ReadBlock(read_block, pos2));
BOOST_CHECK_EQUAL(read_block.nVersion, 2);
}
@@ -194,7 +194,7 @@ BOOST_AUTO_TEST_CASE(blockmanager_flush_block_file)
BOOST_CHECK_EQUAL(blockman.CalculateCurrentUsage(), (TEST_BLOCK_SIZE + BLOCK_SERIALIZATION_HEADER_SIZE) * 2);
// Block 2 was not overwritten:
blockman.ReadBlockFromDisk(read_block, pos2);
blockman.ReadBlock(read_block, pos2);
BOOST_CHECK_EQUAL(read_block.nVersion, 2);
}

View File

@@ -17,12 +17,12 @@ bool ComputeFilter(BlockFilterType filter_type, const CBlockIndex& block_index,
LOCK(::cs_main);
CBlock block;
if (!blockman.ReadBlockFromDisk(block, block_index.GetBlockPos())) {
if (!blockman.ReadBlock(block, block_index.GetBlockPos())) {
return false;
}
CBlockUndo block_undo;
if (block_index.nHeight > 0 && !blockman.UndoReadFromDisk(block_undo, block_index)) {
if (block_index.nHeight > 0 && !blockman.ReadBlockUndo(block_undo, block_index)) {
return false;
}

View File

@@ -88,7 +88,7 @@ BOOST_FIXTURE_TEST_CASE(chainstate_update_tip, TestChain100Setup)
std::shared_ptr<CBlock> pblockone = std::make_shared<CBlock>();
{
LOCK(::cs_main);
chainman.m_blockman.ReadBlockFromDisk(*pblockone, *chainman.ActiveChain()[1]);
chainman.m_blockman.ReadBlock(*pblockone, *chainman.ActiveChain()[1]);
}
BOOST_REQUIRE(CreateAndActivateUTXOSnapshot(