mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-04-29 23:09:44 -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_estimate += 2 + (slKey.size() > 127) + slKey.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t CDBBatch::ApproximateSize() const
|
||||||
|
{
|
||||||
|
return m_impl_batch->batch.ApproximateSize();
|
||||||
|
}
|
||||||
|
|
||||||
struct LevelDBContext {
|
struct LevelDBContext {
|
||||||
//! custom environment this database is using (may be nullptr in case of default environment)
|
//! custom environment this database is using (may be nullptr in case of default environment)
|
||||||
leveldb::Env* penv;
|
leveldb::Env* penv;
|
||||||
|
|
|
@ -119,7 +119,8 @@ public:
|
||||||
ssKey.clear();
|
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
|
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.
|
// transition from old_tip to hashBlock.
|
||||||
// A vector is used for future extensibility, as we may want to support
|
// A vector is used for future extensibility, as we may want to support
|
||||||
// interrupting after partial writes from multiple independent reorgs.
|
// interrupting after partial writes from multiple independent reorgs.
|
||||||
|
assert(batch.ApproximateSize() == batch.SizeEstimate()); // TODO remove
|
||||||
batch.Erase(DB_BEST_BLOCK);
|
batch.Erase(DB_BEST_BLOCK);
|
||||||
|
assert(batch.ApproximateSize() == batch.SizeEstimate()); // TODO remove
|
||||||
batch.Write(DB_HEAD_BLOCKS, Vector(hashBlock, old_tip));
|
batch.Write(DB_HEAD_BLOCKS, Vector(hashBlock, old_tip));
|
||||||
|
assert(batch.ApproximateSize() == batch.SizeEstimate()); // TODO remove
|
||||||
|
|
||||||
for (auto it{cursor.Begin()}; it != cursor.End();) {
|
for (auto it{cursor.Begin()}; it != cursor.End();) {
|
||||||
if (it->second.IsDirty()) {
|
if (it->second.IsDirty()) {
|
||||||
CoinEntry entry(&it->first);
|
CoinEntry entry(&it->first);
|
||||||
if (it->second.coin.IsSpent())
|
if (it->second.coin.IsSpent()) {
|
||||||
|
assert(batch.ApproximateSize() == batch.SizeEstimate()); // TODO remove
|
||||||
batch.Erase(entry);
|
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);
|
batch.Write(entry, it->second.coin);
|
||||||
|
assert(batch.ApproximateSize() == batch.SizeEstimate()); // TODO remove
|
||||||
|
}
|
||||||
|
|
||||||
changed++;
|
changed++;
|
||||||
}
|
}
|
||||||
count++;
|
count++;
|
||||||
it = cursor.NextAndMaybeErase(*it);
|
it = cursor.NextAndMaybeErase(*it);
|
||||||
|
assert(batch.ApproximateSize() == batch.SizeEstimate()); // TODO remove
|
||||||
if (batch.SizeEstimate() > m_options.batch_write_bytes) {
|
if (batch.SizeEstimate() > m_options.batch_write_bytes) {
|
||||||
LogDebug(BCLog::COINDB, "Writing partial batch of %.2f MiB\n", batch.SizeEstimate() * (1.0 / 1048576.0));
|
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);
|
m_db->WriteBatch(batch);
|
||||||
|
assert(batch.ApproximateSize() == batch.SizeEstimate()); // TODO remove
|
||||||
batch.Clear();
|
batch.Clear();
|
||||||
|
assert(batch.ApproximateSize() == batch.SizeEstimate()); // TODO remove
|
||||||
|
|
||||||
if (m_options.simulate_crash_ratio) {
|
if (m_options.simulate_crash_ratio) {
|
||||||
static FastRandomContext rng;
|
static FastRandomContext rng;
|
||||||
if (rng.randrange(m_options.simulate_crash_ratio) == 0) {
|
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.
|
// In the last batch, mark the database as consistent with hashBlock again.
|
||||||
|
assert(batch.ApproximateSize() == batch.SizeEstimate()); // TODO remove
|
||||||
batch.Erase(DB_HEAD_BLOCKS);
|
batch.Erase(DB_HEAD_BLOCKS);
|
||||||
|
assert(batch.ApproximateSize() == batch.SizeEstimate()); // TODO remove
|
||||||
batch.Write(DB_BEST_BLOCK, hashBlock);
|
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));
|
LogDebug(BCLog::COINDB, "Writing final batch of %.2f MiB\n", batch.SizeEstimate() * (1.0 / 1048576.0));
|
||||||
bool ret = m_db->WriteBatch(batch);
|
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);
|
LogDebug(BCLog::COINDB, "Committed %u changed transaction outputs (out of %u) to coin database...\n", (unsigned int)changed, (unsigned int)count);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue