mirror of
https://github.com/bitcoin/bitcoin.git
synced 2026-01-19 06:43:45 +01:00
Merge #18637: coins: allow cache resize after init
f19fdd47a6test: add test for CChainState::ResizeCoinsCaches() (James O'Beirne)8ac3ef4699add ChainstateManager::MaybeRebalanceCaches() (James O'Beirne)f36aaa6392Add CChainState::ResizeCoinsCaches (James O'Beirne)b223111da2txdb: add CCoinsViewDB::ChangeCacheSize (James O'Beirne) Pull request description: This is part of the [assumeutxo project](https://github.com/bitcoin/bitcoin/projects/11): Parent PR: #15606 Issue: #15605 Specification: https://github.com/jamesob/assumeutxo-docs/tree/master/proposal --- In the assumeutxo implementation draft (#15056), once a UTXO snapshot is loaded, a new chainstate object is created after initialization. This means that we have to reclaim some of the cache that we've allocated to the original chainstate (per `dbcache=`) to repurpose for the snapshot chainstate. Furthermore, it makes sense to have different cache allocations depending on which chainstate is more active. While the snapshot chainstate is working to get to the network tip (and the background validation chainstate is idle), it makes sense that the snapshot chainstate should have the majority of cache allocation. And contrariwise once the snapshot has reached network tip, most of the cache should be given to the background validation chainstate. This set of changes (detailed in the commit messages) allows us to dynamically resize the various coins caches. None of the functionality introduced here is used at the moment, but will be in the next AU PR (which introduces `ActivateSnapshot`). `ChainstateManager::MaybeRebalanceCaches()` defines the (somewhat normative) cache allocations between the snapshot and background validation chainstates. I'd be interested in feedback if anyone has thoughts on the proportions I've set there. ACKs for top commit: ajtowns: weak utACKf19fdd47a6-- didn't find any major problems, but not super confident that I didn't miss anything fjahr: Code review ACKf19fdd4ryanofsky: Code review ACKf19fdd47a6. Only change since last review is constructor cleanup (no change in behavior). I think the suggestions here from ajtowns and others are good, but shouldn't delay merging the PR (and hold up assumeutxo) Tree-SHA512: fffb7847fb6993dd4a1a41cf11179b211b0b20b7eb5f7cf6266442136bfe9d43b830bbefcafd475bfd4af273f5573500594aa41fff03e0ed5c2a1e8562ff9269
This commit is contained in:
@@ -139,7 +139,6 @@ bool fPruneMode = false;
|
||||
bool fRequireStandard = true;
|
||||
bool fCheckBlockIndex = false;
|
||||
bool fCheckpointsEnabled = DEFAULT_CHECKPOINTS_ENABLED;
|
||||
size_t nCoinCacheUsage = 5000 * 300;
|
||||
uint64_t nPruneTarget = 0;
|
||||
int64_t nMaxTipAge = DEFAULT_MAX_TIP_AGE;
|
||||
|
||||
@@ -1272,9 +1271,10 @@ void CChainState::InitCoinsDB(
|
||||
leveldb_name, cache_size_bytes, in_memory, should_wipe);
|
||||
}
|
||||
|
||||
void CChainState::InitCoinsCache()
|
||||
void CChainState::InitCoinsCache(size_t cache_size_bytes)
|
||||
{
|
||||
assert(m_coins_views != nullptr);
|
||||
m_coinstip_cache_size_bytes = cache_size_bytes;
|
||||
m_coins_views->InitCache();
|
||||
}
|
||||
|
||||
@@ -2231,7 +2231,7 @@ CoinsCacheSizeState CChainState::GetCoinsCacheSizeState(const CTxMemPool& tx_poo
|
||||
{
|
||||
return this->GetCoinsCacheSizeState(
|
||||
tx_pool,
|
||||
nCoinCacheUsage,
|
||||
m_coinstip_cache_size_bytes,
|
||||
gArgs.GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000);
|
||||
}
|
||||
|
||||
@@ -4306,7 +4306,7 @@ bool CVerifyDB::VerifyDB(const CChainParams& chainparams, CCoinsView *coinsview,
|
||||
}
|
||||
}
|
||||
// check level 3: check for inconsistencies during memory-only disconnect of tip blocks
|
||||
if (nCheckLevel >= 3 && (coins.DynamicMemoryUsage() + ::ChainstateActive().CoinsTip().DynamicMemoryUsage()) <= nCoinCacheUsage) {
|
||||
if (nCheckLevel >= 3 && (coins.DynamicMemoryUsage() + ::ChainstateActive().CoinsTip().DynamicMemoryUsage()) <= ::ChainstateActive().m_coinstip_cache_size_bytes) {
|
||||
assert(coins.GetBestBlock() == pindex->GetBlockHash());
|
||||
DisconnectResult res = ::ChainstateActive().DisconnectBlock(block, pindex, coins);
|
||||
if (res == DISCONNECT_FAILED) {
|
||||
@@ -4969,6 +4969,39 @@ std::string CChainState::ToString()
|
||||
tip ? tip->nHeight : -1, tip ? tip->GetBlockHash().ToString() : "null");
|
||||
}
|
||||
|
||||
bool CChainState::ResizeCoinsCaches(size_t coinstip_size, size_t coinsdb_size)
|
||||
{
|
||||
if (coinstip_size == m_coinstip_cache_size_bytes &&
|
||||
coinsdb_size == m_coinsdb_cache_size_bytes) {
|
||||
// Cache sizes are unchanged, no need to continue.
|
||||
return true;
|
||||
}
|
||||
size_t old_coinstip_size = m_coinstip_cache_size_bytes;
|
||||
m_coinstip_cache_size_bytes = coinstip_size;
|
||||
m_coinsdb_cache_size_bytes = coinsdb_size;
|
||||
CoinsDB().ResizeCache(coinsdb_size);
|
||||
|
||||
LogPrintf("[%s] resized coinsdb cache to %.1f MiB\n",
|
||||
this->ToString(), coinsdb_size * (1.0 / 1024 / 1024));
|
||||
LogPrintf("[%s] resized coinstip cache to %.1f MiB\n",
|
||||
this->ToString(), coinstip_size * (1.0 / 1024 / 1024));
|
||||
|
||||
BlockValidationState state;
|
||||
const CChainParams& chainparams = Params();
|
||||
|
||||
bool ret;
|
||||
|
||||
if (coinstip_size > old_coinstip_size) {
|
||||
// Likely no need to flush if cache sizes have grown.
|
||||
ret = FlushStateToDisk(chainparams, state, FlushStateMode::IF_NEEDED);
|
||||
} else {
|
||||
// Otherwise, flush state to disk and deallocate the in-memory coins map.
|
||||
ret = FlushStateToDisk(chainparams, state, FlushStateMode::ALWAYS);
|
||||
CoinsTip().ReallocateCache();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::string CBlockFileInfo::ToString() const
|
||||
{
|
||||
return strprintf("CBlockFileInfo(blocks=%u, size=%u, heights=%u...%u, time=%s...%s)", nBlocks, nSize, nHeightFirst, nHeightLast, FormatISO8601Date(nTimeFirst), FormatISO8601Date(nTimeLast));
|
||||
@@ -5277,3 +5310,33 @@ void ChainstateManager::Reset()
|
||||
m_active_chainstate = nullptr;
|
||||
m_snapshot_validated = false;
|
||||
}
|
||||
|
||||
void ChainstateManager::MaybeRebalanceCaches()
|
||||
{
|
||||
if (m_ibd_chainstate && !m_snapshot_chainstate) {
|
||||
LogPrintf("[snapshot] allocating all cache to the IBD chainstate\n");
|
||||
// Allocate everything to the IBD chainstate.
|
||||
m_ibd_chainstate->ResizeCoinsCaches(m_total_coinstip_cache, m_total_coinsdb_cache);
|
||||
}
|
||||
else if (m_snapshot_chainstate && !m_ibd_chainstate) {
|
||||
LogPrintf("[snapshot] allocating all cache to the snapshot chainstate\n");
|
||||
// Allocate everything to the snapshot chainstate.
|
||||
m_snapshot_chainstate->ResizeCoinsCaches(m_total_coinstip_cache, m_total_coinsdb_cache);
|
||||
}
|
||||
else if (m_ibd_chainstate && m_snapshot_chainstate) {
|
||||
// If both chainstates exist, determine who needs more cache based on IBD status.
|
||||
//
|
||||
// Note: shrink caches first so that we don't inadvertently overwhelm available memory.
|
||||
if (m_snapshot_chainstate->IsInitialBlockDownload()) {
|
||||
m_ibd_chainstate->ResizeCoinsCaches(
|
||||
m_total_coinstip_cache * 0.05, m_total_coinsdb_cache * 0.05);
|
||||
m_snapshot_chainstate->ResizeCoinsCaches(
|
||||
m_total_coinstip_cache * 0.95, m_total_coinsdb_cache * 0.95);
|
||||
} else {
|
||||
m_snapshot_chainstate->ResizeCoinsCaches(
|
||||
m_total_coinstip_cache * 0.05, m_total_coinsdb_cache * 0.05);
|
||||
m_ibd_chainstate->ResizeCoinsCaches(
|
||||
m_total_coinstip_cache * 0.95, m_total_coinsdb_cache * 0.95);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user