From 0b0c9646543d5371743aadf2ba543ed0d1eedf09 Mon Sep 17 00:00:00 2001 From: "larry.lx" Date: Fri, 27 Oct 2023 15:39:42 +0800 Subject: [PATCH 1/2] code: remove accountTrieCache and storageTrieCache accountTrieCache and storageTrieCache were introduced in this PR: https://github.com/bnb-chain/bsc/pull/257, which is to improve performance. Actually the performance gain is quite limitted, as there is already dirty and clean cache for trie node. And after big merge, these 2 cache can not be used when PBSS is enabled. So remove these code to simplify the logic. --- core/state/database.go | 134 ++----------------------------------- core/state/state_object.go | 3 - core/state/statedb.go | 3 - light/trie.go | 5 -- 4 files changed, 6 insertions(+), 139 deletions(-) diff --git a/core/state/database.go b/core/state/database.go index cc5dc73c77..d5263658e9 100644 --- a/core/state/database.go +++ b/core/state/database.go @@ -19,7 +19,6 @@ package state import ( "errors" "fmt" - "time" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/lru" @@ -29,25 +28,15 @@ import ( "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/trie" "github.com/ethereum/go-ethereum/trie/trienode" - exlru "github.com/hashicorp/golang-lru" //ex: external + //ex: external ) const ( // Number of codehash->size associations to keep. codeSizeCacheSize = 100000 - // Number of state trie in cache - accountTrieCacheSize = 32 - - // Number of storage Trie in cache - storageTrieCacheSize = 2000 - // Cache size granted for caching clean code. codeCacheSize = 64 * 1024 * 1024 - - purgeInterval = 600 - - maxAccountTrieSize = 1024 * 1024 ) // Database wraps access to tries and contract code. @@ -73,15 +62,6 @@ type Database interface { // TrieDB returns the underlying trie database for managing trie nodes. TrieDB() *trie.Database - // Cache the account trie tree - CacheAccount(root common.Hash, t Trie) - - // Cache the storage trie tree - CacheStorage(addrHash common.Hash, root common.Hash, t Trie) - - // Purge cache - Purge() - // NoTries returns whether the database has tries storage. NoTries() bool } @@ -191,53 +171,12 @@ func NewDatabaseWithNodeDB(db ethdb.Database, triedb *trie.Database) Database { } } -func NewDatabaseWithConfigAndCache(db ethdb.Database, config *trie.Config) Database { - atc, _ := exlru.New(accountTrieCacheSize) - stc, _ := exlru.New(storageTrieCacheSize) - noTries := config != nil && config.NoTries - - database := &cachingDB{ - disk: db, - codeSizeCache: lru.NewCache[common.Hash, int](codeSizeCacheSize), - codeCache: lru.NewSizeConstrainedCache[common.Hash, []byte](codeCacheSize), - triedb: trie.NewDatabase(db, config), - accountTrieCache: atc, - storageTrieCache: stc, - noTries: noTries, - } - if !noTries { - go database.purgeLoop() - } - return database -} - type cachingDB struct { - disk ethdb.KeyValueStore - codeSizeCache *lru.Cache[common.Hash, int] - codeCache *lru.SizeConstrainedCache[common.Hash, []byte] - triedb *trie.Database - accountTrieCache *exlru.Cache - storageTrieCache *exlru.Cache - noTries bool -} - -type triePair struct { - root common.Hash - trie Trie -} - -func (db *cachingDB) purgeLoop() { - for { - time.Sleep(purgeInterval * time.Second) - _, accounts, ok := db.accountTrieCache.GetOldest() - if !ok { - continue - } - tr := accounts.(*trie.SecureTrie).GetRawTrie() - if tr.Size() > maxAccountTrieSize { - db.Purge() - } - } + disk ethdb.KeyValueStore + codeSizeCache *lru.Cache[common.Hash, int] + codeCache *lru.SizeConstrainedCache[common.Hash, []byte] + triedb *trie.Database + noTries bool } // OpenTrie opens the main account trie at a specific root hash. @@ -245,11 +184,6 @@ func (db *cachingDB) OpenTrie(root common.Hash) (Trie, error) { if db.noTries { return trie.NewEmptyTrie(), nil } - if db.accountTrieCache != nil { - if tr, exist := db.accountTrieCache.Get(root); exist { - return tr.(Trie).(*trie.SecureTrie).Copy(), nil - } - } tr, err := trie.NewStateTrie(trie.StateTrieID(root), db.triedb) if err != nil { return nil, err @@ -262,16 +196,6 @@ func (db *cachingDB) OpenStorageTrie(stateRoot common.Hash, address common.Addre if db.noTries { return trie.NewEmptyTrie(), nil } - if db.storageTrieCache != nil { - if tries, exist := db.storageTrieCache.Get(crypto.Keccak256Hash(address.Bytes())); exist { - triesPairs := tries.([3]*triePair) - for _, triePair := range triesPairs { - if triePair != nil && triePair.root == root { - return triePair.trie.(*trie.SecureTrie).Copy(), nil - } - } - } - } tr, err := trie.NewStateTrie(trie.StorageTrieID(stateRoot, crypto.Keccak256Hash(address.Bytes()), root), db.triedb) if err != nil { @@ -280,56 +204,10 @@ func (db *cachingDB) OpenStorageTrie(stateRoot common.Hash, address common.Addre return tr, nil } -func (db *cachingDB) CacheAccount(root common.Hash, t Trie) { - // only the hash scheme trie db support account cache, because the path scheme trie db - // account trie bind the previous layer, touch the dirty data when next access. This is - // related to the implementation of the Reader interface of pathdb. - if db.TrieDB().Scheme() == rawdb.PathScheme { - return - } - if db.accountTrieCache == nil { - return - } - tr := t.(*trie.SecureTrie) - db.accountTrieCache.Add(root, tr.ResetCopy()) -} - -func (db *cachingDB) CacheStorage(addrHash common.Hash, root common.Hash, t Trie) { - // ditto `CacheAccount` - if db.TrieDB().Scheme() == rawdb.PathScheme { - return - } - if db.storageTrieCache == nil { - return - } - tr := t.(*trie.SecureTrie) - if tries, exist := db.storageTrieCache.Get(addrHash); exist { - triesArray := tries.([3]*triePair) - newTriesArray := [3]*triePair{ - {root: root, trie: tr.ResetCopy()}, - triesArray[0], - triesArray[1], - } - db.storageTrieCache.Add(addrHash, newTriesArray) - } else { - triesArray := [3]*triePair{{root: root, trie: tr.ResetCopy()}, nil, nil} - db.storageTrieCache.Add(addrHash, triesArray) - } -} - func (db *cachingDB) NoTries() bool { return db.noTries } -func (db *cachingDB) Purge() { - if db.storageTrieCache != nil { - db.storageTrieCache.Purge() - } - if db.accountTrieCache != nil { - db.accountTrieCache.Purge() - } -} - // CopyTrie returns an independent copy of the given trie. func (db *cachingDB) CopyTrie(t Trie) Trie { if t == nil { diff --git a/core/state/state_object.go b/core/state/state_object.go index ed67fceefb..1478e434ab 100644 --- a/core/state/state_object.go +++ b/core/state/state_object.go @@ -464,9 +464,6 @@ func (s *stateObject) commit() (*trienode.NodeSet, error) { return nil, err } s.data.Root = root - if s.data.Root != types.EmptyRootHash { - s.db.db.CacheStorage(s.addrHash, s.data.Root, s.trie) - } // Update original account data after commit s.origin = s.data.Copy() diff --git a/core/state/statedb.go b/core/state/statedb.go index 80bf3bf715..dddd05dabc 100644 --- a/core/state/statedb.go +++ b/core/state/statedb.go @@ -1691,9 +1691,6 @@ func (s *StateDB) Commit(block uint64, failPostCommitFunc func(), postCommitFunc return err } } - if root != types.EmptyRootHash { - s.db.CacheAccount(root, s.trie) - } origin := s.originalRoot if origin == (common.Hash{}) { diff --git a/light/trie.go b/light/trie.go index 529f1e5d89..66472edf85 100644 --- a/light/trie.go +++ b/light/trie.go @@ -100,11 +100,6 @@ func (db *odrDatabase) TrieDB() *trie.Database { return nil } -func (db *odrDatabase) CacheAccount(_ common.Hash, _ state.Trie) {} - -func (db *odrDatabase) CacheStorage(_ common.Hash, _ common.Hash, _ state.Trie) {} - -func (db *odrDatabase) Purge() {} func (db *odrDatabase) DiskDB() ethdb.KeyValueStore { panic("not implemented") } From 623488441c228fd20a123818dcc46f8600997d85 Mon Sep 17 00:00:00 2001 From: "larry.lx" Date: Fri, 27 Oct 2023 16:20:04 +0800 Subject: [PATCH 2/2] code: minor code update --- core/state/database.go | 1 - 1 file changed, 1 deletion(-) diff --git a/core/state/database.go b/core/state/database.go index d5263658e9..071881b43e 100644 --- a/core/state/database.go +++ b/core/state/database.go @@ -28,7 +28,6 @@ import ( "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/trie" "github.com/ethereum/go-ethereum/trie/trienode" - //ex: external ) const (