From 236438d799eb7de497ae8c7a2f509b7212b2c770 Mon Sep 17 00:00:00 2001 From: Roman Khimov Date: Thu, 4 Jun 2020 17:25:57 +0300 Subject: [PATCH] core: do MPT compaction every once in a while We need to compact our in-memory MPT from time to time, otherwise it quickly fills up all available memory. This raises two obvious quesions --- when to do that and to what level do that. As for 'when', I think it's quite easy to use our regular persistence interval as an anchor (and it also frees up some memory), but we can't do that in the persistence routine itself because of synchronization issues (adding some synchronization primitives would add some cost that I'd also like to avoid), so do it indirectly by comparing persisted and current height in `storeBlock`. Choosing proper level is another problem, but if we're to roughly estimate one full branch node to use 1K of memory (usually it's way less than that) then we can easily store 1K of these nodes and that gives us a depth of 10 for our trie. Signed-off-by: Evgenii Stratonikov --- pkg/core/blockchain.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/pkg/core/blockchain.go b/pkg/core/blockchain.go index 7b2b45064..c140ec561 100644 --- a/pkg/core/blockchain.go +++ b/pkg/core/blockchain.go @@ -674,6 +674,12 @@ func (bc *Blockchain) storeBlock(block *block.Block) error { } bc.contracts.Policy.OnPersistEnd(bc.dao) bc.dao.MPT.Flush() + // Every persist cycle we also compact our in-memory MPT. + persistedHeight := atomic.LoadUint32(&bc.persistedHeight) + if persistedHeight == block.Index-1 { + // 10 is good and roughly estimated to fit remaining trie into 1M of memory. + bc.dao.MPT.Collapse(10) + } bc.topBlock.Store(block) atomic.StoreUint32(&bc.blockHeight, block.Index) bc.memPool.RemoveStale(bc.isTxStillRelevant, bc)