Skip to content

Commit

Permalink
code: remove accountTrieCache and storageTrieCache (#1949)
Browse files Browse the repository at this point in the history
accountTrieCache and storageTrieCache were introduced in this PR:
#257, which is to improve performance.
Actually the performance gain is quite limited, 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.
  • Loading branch information
brilliant-lx authored Oct 30, 2023
1 parent fd6e7bb commit 3bf998f
Show file tree
Hide file tree
Showing 4 changed files with 5 additions and 139 deletions.
133 changes: 5 additions & 128 deletions core/state/database.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ package state
import (
"errors"
"fmt"
"time"

"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/lru"
Expand All @@ -29,25 +28,14 @@ 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
)

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.
Expand All @@ -73,15 +61,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
}
Expand Down Expand Up @@ -191,65 +170,19 @@ 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.
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
Expand All @@ -262,16 +195,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 {
Expand All @@ -280,56 +203,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 {
Expand Down
3 changes: 0 additions & 3 deletions core/state/state_object.go
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down
3 changes: 0 additions & 3 deletions core/state/statedb.go
Original file line number Diff line number Diff line change
Expand Up @@ -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{}) {
Expand Down
5 changes: 0 additions & 5 deletions light/trie.go
Original file line number Diff line number Diff line change
Expand Up @@ -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")
}
Expand Down

0 comments on commit 3bf998f

Please sign in to comment.