mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-04-29 14:59:39 -04:00
refactor: Delegate to LevelDB for CDBBatch size estimation
Serialized batch size can be queried via the underlying LevelDB implementation calling the native `leveldb::WriteBatch::ApproximateSize()`. The previous manual calculation was added ine66dbde6d1
as part of https://github.com/bitcoin/bitcoin/pull/10195. At that time (April 2017), the version of LevelDB used by Bitcoin Core (and even the latest source) lacked a native function for this. LevelDB added this capability in69e2bd224b
, merged later that year. The old manual estimation method (`SizeEstimate()`) is kept temporarily in this commit, and assertions are added in `txdb.cpp` to verify its results against `ApproximateSize()` during batch writes. This ensures the native function behaves as expected before removing the manual calculation in the subsequent commit.
This commit is contained in:
parent
751077c6e2
commit
8b5e19d8b5
3 changed files with 28 additions and 3 deletions
|
@ -200,6 +200,11 @@ void CDBBatch::EraseImpl(std::span<const std::byte> key)
|
|||
size_estimate += 2 + (slKey.size() > 127) + slKey.size();
|
||||
}
|
||||
|
||||
size_t CDBBatch::ApproximateSize() const
|
||||
{
|
||||
return m_impl_batch->batch.ApproximateSize();
|
||||
}
|
||||
|
||||
struct LevelDBContext {
|
||||
//! custom environment this database is using (may be nullptr in case of default environment)
|
||||
leveldb::Env* penv;
|
||||
|
|
|
@ -119,7 +119,8 @@ public:
|
|||
ssKey.clear();
|
||||
}
|
||||
|
||||
size_t SizeEstimate() const { return size_estimate; }
|
||||
size_t ApproximateSize() const;
|
||||
size_t SizeEstimate() const { return size_estimate; } // TODO replace with ApproximateSize
|
||||
};
|
||||
|
||||
class CDBIterator
|
||||
|
|
23
src/txdb.cpp
23
src/txdb.cpp
|
@ -113,24 +113,39 @@ bool CCoinsViewDB::BatchWrite(CoinsViewCacheCursor& cursor, const uint256 &hashB
|
|||
// transition from old_tip to hashBlock.
|
||||
// A vector is used for future extensibility, as we may want to support
|
||||
// interrupting after partial writes from multiple independent reorgs.
|
||||
assert(batch.ApproximateSize() == batch.SizeEstimate()); // TODO remove
|
||||
batch.Erase(DB_BEST_BLOCK);
|
||||
assert(batch.ApproximateSize() == batch.SizeEstimate()); // TODO remove
|
||||
batch.Write(DB_HEAD_BLOCKS, Vector(hashBlock, old_tip));
|
||||
assert(batch.ApproximateSize() == batch.SizeEstimate()); // TODO remove
|
||||
|
||||
for (auto it{cursor.Begin()}; it != cursor.End();) {
|
||||
if (it->second.IsDirty()) {
|
||||
CoinEntry entry(&it->first);
|
||||
if (it->second.coin.IsSpent())
|
||||
if (it->second.coin.IsSpent()) {
|
||||
assert(batch.ApproximateSize() == batch.SizeEstimate()); // TODO remove
|
||||
batch.Erase(entry);
|
||||
else
|
||||
assert(batch.ApproximateSize() == batch.SizeEstimate()); // TODO remove
|
||||
} else {
|
||||
assert(batch.ApproximateSize() == batch.SizeEstimate()); // TODO remove
|
||||
batch.Write(entry, it->second.coin);
|
||||
assert(batch.ApproximateSize() == batch.SizeEstimate()); // TODO remove
|
||||
}
|
||||
|
||||
changed++;
|
||||
}
|
||||
count++;
|
||||
it = cursor.NextAndMaybeErase(*it);
|
||||
assert(batch.ApproximateSize() == batch.SizeEstimate()); // TODO remove
|
||||
if (batch.SizeEstimate() > m_options.batch_write_bytes) {
|
||||
LogDebug(BCLog::COINDB, "Writing partial batch of %.2f MiB\n", batch.SizeEstimate() * (1.0 / 1048576.0));
|
||||
|
||||
assert(batch.ApproximateSize() == batch.SizeEstimate()); // TODO remove
|
||||
m_db->WriteBatch(batch);
|
||||
assert(batch.ApproximateSize() == batch.SizeEstimate()); // TODO remove
|
||||
batch.Clear();
|
||||
assert(batch.ApproximateSize() == batch.SizeEstimate()); // TODO remove
|
||||
|
||||
if (m_options.simulate_crash_ratio) {
|
||||
static FastRandomContext rng;
|
||||
if (rng.randrange(m_options.simulate_crash_ratio) == 0) {
|
||||
|
@ -142,11 +157,15 @@ bool CCoinsViewDB::BatchWrite(CoinsViewCacheCursor& cursor, const uint256 &hashB
|
|||
}
|
||||
|
||||
// In the last batch, mark the database as consistent with hashBlock again.
|
||||
assert(batch.ApproximateSize() == batch.SizeEstimate()); // TODO remove
|
||||
batch.Erase(DB_HEAD_BLOCKS);
|
||||
assert(batch.ApproximateSize() == batch.SizeEstimate()); // TODO remove
|
||||
batch.Write(DB_BEST_BLOCK, hashBlock);
|
||||
assert(batch.ApproximateSize() == batch.SizeEstimate()); // TODO remove
|
||||
|
||||
LogDebug(BCLog::COINDB, "Writing final batch of %.2f MiB\n", batch.SizeEstimate() * (1.0 / 1048576.0));
|
||||
bool ret = m_db->WriteBatch(batch);
|
||||
assert(batch.ApproximateSize() == batch.SizeEstimate()); // TODO remove
|
||||
LogDebug(BCLog::COINDB, "Committed %u changed transaction outputs (out of %u) to coin database...\n", (unsigned int)changed, (unsigned int)count);
|
||||
return ret;
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue