Skip to content

Commit 8ac3ef4

Browse files
committed
add ChainstateManager::MaybeRebalanceCaches()
Aside from in unittests, this method is unused at the moment. It will be used in upcoming commits that enable utxo snapshot activation.
1 parent f36aaa6 commit 8ac3ef4

File tree

4 files changed

+99
-0
lines changed

4 files changed

+99
-0
lines changed

src/init.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1562,6 +1562,9 @@ bool AppInitMain(const util::Ref& context, NodeContext& node)
15621562
try {
15631563
LOCK(cs_main);
15641564
chainman.InitializeChainstate();
1565+
chainman.m_total_coinstip_cache = nCoinCacheUsage;
1566+
chainman.m_total_coinsdb_cache = nCoinDBCache;
1567+
15651568
UnloadBlockIndex();
15661569

15671570
// new CBlockTreeDB tries to delete the existing file, which

src/test/validation_chainstatemanager_tests.cpp

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,4 +103,58 @@ BOOST_AUTO_TEST_CASE(chainstatemanager)
103103
WITH_LOCK(::cs_main, manager.Unload());
104104
}
105105

106+
//! Test rebalancing the caches associated with each chainstate.
107+
BOOST_AUTO_TEST_CASE(chainstatemanager_rebalance_caches)
108+
{
109+
ChainstateManager manager;
110+
size_t max_cache = 10000;
111+
manager.m_total_coinsdb_cache = max_cache;
112+
manager.m_total_coinstip_cache = max_cache;
113+
114+
std::vector<CChainState*> chainstates;
115+
116+
// Create a legacy (IBD) chainstate.
117+
//
118+
ENTER_CRITICAL_SECTION(cs_main);
119+
CChainState& c1 = manager.InitializeChainstate();
120+
LEAVE_CRITICAL_SECTION(cs_main);
121+
chainstates.push_back(&c1);
122+
c1.InitCoinsDB(
123+
/* cache_size_bytes */ 1 << 23, /* in_memory */ true, /* should_wipe */ false);
124+
125+
{
126+
LOCK(::cs_main);
127+
c1.InitCoinsCache(1 << 23);
128+
c1.CoinsTip().SetBestBlock(InsecureRand256());
129+
manager.MaybeRebalanceCaches();
130+
}
131+
132+
BOOST_CHECK_EQUAL(c1.m_coinstip_cache_size_bytes, max_cache);
133+
BOOST_CHECK_EQUAL(c1.m_coinsdb_cache_size_bytes, max_cache);
134+
135+
// Create a snapshot-based chainstate.
136+
//
137+
ENTER_CRITICAL_SECTION(cs_main);
138+
CChainState& c2 = manager.InitializeChainstate(GetRandHash());
139+
LEAVE_CRITICAL_SECTION(cs_main);
140+
chainstates.push_back(&c2);
141+
c2.InitCoinsDB(
142+
/* cache_size_bytes */ 1 << 23, /* in_memory */ true, /* should_wipe */ false);
143+
144+
{
145+
LOCK(::cs_main);
146+
c2.InitCoinsCache(1 << 23);
147+
c2.CoinsTip().SetBestBlock(InsecureRand256());
148+
manager.MaybeRebalanceCaches();
149+
}
150+
151+
// Since both chainstates are considered to be in initial block download,
152+
// the snapshot chainstate should take priority.
153+
BOOST_CHECK_CLOSE(c1.m_coinstip_cache_size_bytes, max_cache * 0.05, 1);
154+
BOOST_CHECK_CLOSE(c1.m_coinsdb_cache_size_bytes, max_cache * 0.05, 1);
155+
BOOST_CHECK_CLOSE(c2.m_coinstip_cache_size_bytes, max_cache * 0.95, 1);
156+
BOOST_CHECK_CLOSE(c2.m_coinsdb_cache_size_bytes, max_cache * 0.95, 1);
157+
158+
}
159+
106160
BOOST_AUTO_TEST_SUITE_END()

src/validation.cpp

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5297,3 +5297,33 @@ void ChainstateManager::Reset()
52975297
m_active_chainstate = nullptr;
52985298
m_snapshot_validated = false;
52995299
}
5300+
5301+
void ChainstateManager::MaybeRebalanceCaches()
5302+
{
5303+
if (m_ibd_chainstate && !m_snapshot_chainstate) {
5304+
LogPrintf("[snapshot] allocating all cache to the IBD chainstate\n");
5305+
// Allocate everything to the IBD chainstate.
5306+
m_ibd_chainstate->ResizeCoinsCaches(m_total_coinstip_cache, m_total_coinsdb_cache);
5307+
}
5308+
else if (m_snapshot_chainstate && !m_ibd_chainstate) {
5309+
LogPrintf("[snapshot] allocating all cache to the snapshot chainstate\n");
5310+
// Allocate everything to the snapshot chainstate.
5311+
m_snapshot_chainstate->ResizeCoinsCaches(m_total_coinstip_cache, m_total_coinsdb_cache);
5312+
}
5313+
else if (m_ibd_chainstate && m_snapshot_chainstate) {
5314+
// If both chainstates exist, determine who needs more cache based on IBD status.
5315+
//
5316+
// Note: shrink caches first so that we don't inadvertently overwhelm available memory.
5317+
if (m_snapshot_chainstate->IsInitialBlockDownload()) {
5318+
m_ibd_chainstate->ResizeCoinsCaches(
5319+
m_total_coinstip_cache * 0.05, m_total_coinsdb_cache * 0.05);
5320+
m_snapshot_chainstate->ResizeCoinsCaches(
5321+
m_total_coinstip_cache * 0.95, m_total_coinsdb_cache * 0.95);
5322+
} else {
5323+
m_snapshot_chainstate->ResizeCoinsCaches(
5324+
m_total_coinstip_cache * 0.05, m_total_coinsdb_cache * 0.05);
5325+
m_ibd_chainstate->ResizeCoinsCaches(
5326+
m_total_coinstip_cache * 0.95, m_total_coinsdb_cache * 0.95);
5327+
}
5328+
}
5329+
}

src/validation.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -794,6 +794,14 @@ class ChainstateManager
794794
//! chainstate to avoid duplicating block metadata.
795795
BlockManager m_blockman GUARDED_BY(::cs_main);
796796

797+
//! The total number of bytes available for us to use across all in-memory
798+
//! coins caches. This will be split somehow across chainstates.
799+
int64_t m_total_coinstip_cache{0};
800+
//
801+
//! The total number of bytes available for us to use across all leveldb
802+
//! coins databases. This will be split somehow across chainstates.
803+
int64_t m_total_coinsdb_cache{0};
804+
797805
//! Instantiate a new chainstate and assign it based upon whether it is
798806
//! from a snapshot.
799807
//!
@@ -881,6 +889,10 @@ class ChainstateManager
881889

882890
//! Clear (deconstruct) chainstate data.
883891
void Reset();
892+
893+
//! Check to see if caches are out of balance and if so, call
894+
//! ResizeCoinsCaches() as needed.
895+
void MaybeRebalanceCaches() EXCLUSIVE_LOCKS_REQUIRED(::cs_main);
884896
};
885897

886898
/** DEPRECATED! Please use node.chainman instead. May only be used in validation.cpp internally */

0 commit comments

Comments
 (0)