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.
|
// 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 {
|
func (s *stateObject) updateTrie(db Database) Trie {
|
||||||
// Make sure all dirty slots are finalized into the pending storage area
|
// Make sure all dirty slots are finalized into the pending storage area
|
||||||
s.finalise()
|
s.finalise()
|
||||||
|
if len(s.pendingStorage) == 0{
|
||||||
|
return s.trie
|
||||||
|
}
|
||||||
// Track the amount of time wasted on updating the storge trie
|
// Track the amount of time wasted on updating the storge trie
|
||||||
if metrics.EnabledExpensive {
|
if metrics.EnabledExpensive {
|
||||||
defer func(start time.Time) { s.db.StorageUpdates += time.Since(start) }(time.Now())
|
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
|
// UpdateRoot sets the trie root to the current root hash of
|
||||||
func (s *stateObject) updateRoot(db Database) {
|
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
|
// Track the amount of time wasted on hashing the storge trie
|
||||||
if metrics.EnabledExpensive {
|
if metrics.EnabledExpensive {
|
||||||
defer func(start time.Time) { s.db.StorageHashes += time.Since(start) }(time.Now())
|
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.
|
// CommitTrie the storage trie of the object to db.
|
||||||
// This updates the trie root.
|
// This updates the trie root.
|
||||||
func (s *stateObject) CommitTrie(db Database) error {
|
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 {
|
if s.dbErr != nil {
|
||||||
return s.dbErr
|
return s.dbErr
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -330,7 +330,8 @@ func (s *StateDB) StorageTrie(addr common.Address) Trie {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
cpy := stateObject.deepCopy(s)
|
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 {
|
func (s *StateDB) HasSuicided(addr common.Address) bool {
|
||||||
|
|
|
||||||
|
|
@ -67,6 +67,12 @@ func returnCommitterToPool(h *committer) {
|
||||||
committerPool.Put(h)
|
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
|
// 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.
|
// original node initialized with the computed hash to replace the original one.
|
||||||
func (h *committer) commit(n node, db *Database, force bool) (node, error) {
|
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()
|
rootHash := t.Hash()
|
||||||
h := newCommitter(onleaf)
|
h := newCommitter(onleaf)
|
||||||
defer returnCommitterToPool(h)
|
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
|
var wg sync.WaitGroup
|
||||||
if onleaf != nil {
|
if onleaf != nil {
|
||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue