core, eth, trie: streaming GC for the trie cache (#16810)
* core, eth, trie: streaming GC for the trie cache * trie: track memcache statistics
This commit is contained in:
@ -674,7 +674,7 @@ func (bc *BlockChain) Stop() {
|
||||
for !bc.triegc.Empty() {
|
||||
triedb.Dereference(bc.triegc.PopItem().(common.Hash), common.Hash{})
|
||||
}
|
||||
if size := triedb.Size(); size != 0 {
|
||||
if size, _ := triedb.Size(); size != 0 {
|
||||
log.Error("Dangling trie nodes after full cleanup")
|
||||
}
|
||||
}
|
||||
@ -916,33 +916,29 @@ func (bc *BlockChain) WriteBlockWithState(block *types.Block, receipts []*types.
|
||||
bc.triegc.Push(root, -float32(block.NumberU64()))
|
||||
|
||||
if current := block.NumberU64(); current > triesInMemory {
|
||||
// If we exceeded our memory allowance, flush matured singleton nodes to disk
|
||||
var (
|
||||
nodes, imgs = triedb.Size()
|
||||
limit = common.StorageSize(bc.cacheConfig.TrieNodeLimit) * 1024 * 1024
|
||||
)
|
||||
if nodes > limit || imgs > 4*1024*1024 {
|
||||
triedb.Cap(limit - ethdb.IdealBatchSize)
|
||||
}
|
||||
// Find the next state trie we need to commit
|
||||
header := bc.GetHeaderByNumber(current - triesInMemory)
|
||||
chosen := header.Number.Uint64()
|
||||
|
||||
// Only write to disk if we exceeded our memory allowance *and* also have at
|
||||
// least a given number of tries gapped.
|
||||
var (
|
||||
size = triedb.Size()
|
||||
limit = common.StorageSize(bc.cacheConfig.TrieNodeLimit) * 1024 * 1024
|
||||
)
|
||||
if size > limit || bc.gcproc > bc.cacheConfig.TrieTimeLimit {
|
||||
// If we exceeded out time allowance, flush an entire trie to disk
|
||||
if bc.gcproc > bc.cacheConfig.TrieTimeLimit {
|
||||
// If we're exceeding limits but haven't reached a large enough memory gap,
|
||||
// warn the user that the system is becoming unstable.
|
||||
if chosen < lastWrite+triesInMemory {
|
||||
switch {
|
||||
case size >= 2*limit:
|
||||
log.Warn("State memory usage too high, committing", "size", size, "limit", limit, "optimum", float64(chosen-lastWrite)/triesInMemory)
|
||||
case bc.gcproc >= 2*bc.cacheConfig.TrieTimeLimit:
|
||||
log.Info("State in memory for too long, committing", "time", bc.gcproc, "allowance", bc.cacheConfig.TrieTimeLimit, "optimum", float64(chosen-lastWrite)/triesInMemory)
|
||||
}
|
||||
}
|
||||
// If optimum or critical limits reached, write to disk
|
||||
if chosen >= lastWrite+triesInMemory || size >= 2*limit || bc.gcproc >= 2*bc.cacheConfig.TrieTimeLimit {
|
||||
triedb.Commit(header.Root, true)
|
||||
lastWrite = chosen
|
||||
bc.gcproc = 0
|
||||
if chosen < lastWrite+triesInMemory && bc.gcproc >= 2*bc.cacheConfig.TrieTimeLimit {
|
||||
log.Info("State in memory for too long, committing", "time", bc.gcproc, "allowance", bc.cacheConfig.TrieTimeLimit, "optimum", float64(chosen-lastWrite)/triesInMemory)
|
||||
}
|
||||
// Flush an entire trie and restart the counters
|
||||
triedb.Commit(header.Root, true)
|
||||
lastWrite = chosen
|
||||
bc.gcproc = 0
|
||||
}
|
||||
// Garbage collect anything below our required write retention
|
||||
for !bc.triegc.Empty() {
|
||||
@ -1181,7 +1177,9 @@ func (bc *BlockChain) insertChain(chain types.Blocks) (int, []interface{}, []*ty
|
||||
}
|
||||
stats.processed++
|
||||
stats.usedGas += usedGas
|
||||
stats.report(chain, i, bc.stateCache.TrieDB().Size())
|
||||
|
||||
cache, _ := bc.stateCache.TrieDB().Size()
|
||||
stats.report(chain, i, cache)
|
||||
}
|
||||
// Append a single chain head event if we've progressed the chain
|
||||
if lastCanon != nil && bc.CurrentBlock().Hash() == lastCanon.Hash() {
|
||||
|
Reference in New Issue
Block a user