Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

code: remove accountTrieCache and storageTrieCache #1949

Merged
merged 2 commits into from
Oct 30, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
134 changes: 6 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,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
brilliant-lx marked this conversation as resolved.
Show resolved Hide resolved
)

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 +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
}
Expand Down Expand Up @@ -191,65 +171,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 +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 {
Expand All @@ -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 {
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
Loading