mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-20 10:52:25 +00:00
core/state, trie: avoid unnecessary storage trie load+commit
This commit is contained in:
parent
853a69141a
commit
d76431b8df
4 changed files with 28 additions and 5 deletions
|
|
@ -272,10 +272,15 @@ func (s *stateObject) finalise() {
|
|||
}
|
||||
|
||||
// updateTrie writes cached storage modifications into the object's storage trie.
|
||||
// It will return nil if the trie has not been loaded and no changes have been made
|
||||
// Note: It may return non-nil if the trie is already loaded due to previous changes
|
||||
// in the same block
|
||||
func (s *stateObject) updateTrie(db Database) Trie {
|
||||
// Make sure all dirty slots are finalized into the pending storage area
|
||||
s.finalise()
|
||||
|
||||
if len(s.pendingStorage) == 0{
|
||||
return s.trie
|
||||
}
|
||||
// Track the amount of time wasted on updating the storge trie
|
||||
if metrics.EnabledExpensive {
|
||||
defer func(start time.Time) { s.db.StorageUpdates += time.Since(start) }(time.Now())
|
||||
|
|
@ -305,8 +310,10 @@ func (s *stateObject) updateTrie(db Database) Trie {
|
|||
|
||||
// UpdateRoot sets the trie root to the current root hash of
|
||||
func (s *stateObject) updateRoot(db Database) {
|
||||
s.updateTrie(db)
|
||||
|
||||
if s.updateTrie(db) == nil{
|
||||
// No changes, storage trie is not even loaded
|
||||
return
|
||||
}
|
||||
// Track the amount of time wasted on hashing the storge trie
|
||||
if metrics.EnabledExpensive {
|
||||
defer func(start time.Time) { s.db.StorageHashes += time.Since(start) }(time.Now())
|
||||
|
|
@ -317,7 +324,10 @@ func (s *stateObject) updateRoot(db Database) {
|
|||
// CommitTrie the storage trie of the object to db.
|
||||
// This updates the trie root.
|
||||
func (s *stateObject) CommitTrie(db Database) error {
|
||||
s.updateTrie(db)
|
||||
if s.updateTrie(db) == nil{
|
||||
// No changes, storage trie is not even loaded
|
||||
return nil
|
||||
}
|
||||
if s.dbErr != nil {
|
||||
return s.dbErr
|
||||
}
|
||||
|
|
|
|||
|
|
@ -330,7 +330,8 @@ func (s *StateDB) StorageTrie(addr common.Address) Trie {
|
|||
return nil
|
||||
}
|
||||
cpy := stateObject.deepCopy(s)
|
||||
return cpy.updateTrie(s.db)
|
||||
cpy.updateTrie(s.db)
|
||||
return cpy.getTrie(s.db)
|
||||
}
|
||||
|
||||
func (s *StateDB) HasSuicided(addr common.Address) bool {
|
||||
|
|
|
|||
|
|
@ -67,6 +67,12 @@ func returnCommitterToPool(h *committer) {
|
|||
committerPool.Put(h)
|
||||
}
|
||||
|
||||
// commitNeeded returns 'false' if the given node is already in sync with db
|
||||
func (h *committer) commitNeeded(n node) bool {
|
||||
hash, dirty := n.cache()
|
||||
return hash == nil || dirty
|
||||
}
|
||||
|
||||
// hash collapses a node down into a hash node, also returning a copy of the
|
||||
// original node initialized with the computed hash to replace the original one.
|
||||
func (h *committer) commit(n node, db *Database, force bool) (node, error) {
|
||||
|
|
|
|||
|
|
@ -441,6 +441,12 @@ func (t *Trie) Commit(onleaf LeafCallback) (root common.Hash, err error) {
|
|||
rootHash := t.Hash()
|
||||
h := newCommitter(onleaf)
|
||||
defer returnCommitterToPool(h)
|
||||
// Do a quick check if we really need to commit, before we spin
|
||||
// up goroutines. This can happen e.g. if we load a trie for reading storage
|
||||
// values, but don't write to it.
|
||||
if !h.commitNeeded(t.root) {
|
||||
return rootHash, nil
|
||||
}
|
||||
var wg sync.WaitGroup
|
||||
if onleaf != nil {
|
||||
wg.Add(1)
|
||||
|
|
|
|||
Loading…
Reference in a new issue