aboutsummaryrefslogtreecommitdiffstats
path: root/core
diff options
context:
space:
mode:
authorPéter Szilágyi <peterke@gmail.com>2018-06-04 15:47:43 +0800
committerGitHub <noreply@github.com>2018-06-04 15:47:43 +0800
commit143c4341d8a2231deade6d7341c668d609bd3486 (patch)
treededba70251f89989fbdd1fdc91f0c9348af551e3 /core
parent3f33a7c8ceeefd769a68bbcc2ed3e4ce74ddaef8 (diff)
downloaddexon-143c4341d8a2231deade6d7341c668d609bd3486.tar
dexon-143c4341d8a2231deade6d7341c668d609bd3486.tar.gz
dexon-143c4341d8a2231deade6d7341c668d609bd3486.tar.bz2
dexon-143c4341d8a2231deade6d7341c668d609bd3486.tar.lz
dexon-143c4341d8a2231deade6d7341c668d609bd3486.tar.xz
dexon-143c4341d8a2231deade6d7341c668d609bd3486.tar.zst
dexon-143c4341d8a2231deade6d7341c668d609bd3486.zip
core, eth, trie: streaming GC for the trie cache (#16810)
* core, eth, trie: streaming GC for the trie cache * trie: track memcache statistics
Diffstat (limited to 'core')
-rw-r--r--core/blockchain.go42
1 files changed, 20 insertions, 22 deletions
diff --git a/core/blockchain.go b/core/blockchain.go
index f74a0f5b2..3eee75df7 100644
--- a/core/blockchain.go
+++ b/core/blockchain.go
@@ -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() {