mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-23 05:06:43 +00:00
core/state: paralleize the account trie hash along with storages
This commit is contained in:
parent
cfa3b96103
commit
03a4b24aca
1 changed files with 18 additions and 8 deletions
|
|
@ -818,8 +818,11 @@ func (s *StateDB) IntermediateRoot(deleteEmptyObjects bool) common.Hash {
|
||||||
// method will internally call a blocking trie fetch from the prefetcher,
|
// method will internally call a blocking trie fetch from the prefetcher,
|
||||||
// so there's no need to explicitly wait for the prefetchers to finish.
|
// so there's no need to explicitly wait for the prefetchers to finish.
|
||||||
var (
|
var (
|
||||||
start = time.Now()
|
|
||||||
workers errgroup.Group
|
workers errgroup.Group
|
||||||
|
start = time.Now()
|
||||||
|
|
||||||
|
storageUpdates atomic.Int64
|
||||||
|
pendingAccounts = make(chan *stateObject, len(s.mutations))
|
||||||
)
|
)
|
||||||
if s.db.TrieDB().IsVerkle() {
|
if s.db.TrieDB().IsVerkle() {
|
||||||
// Whilst MPT storage tries are independent, Verkle has one single trie
|
// Whilst MPT storage tries are independent, Verkle has one single trie
|
||||||
|
|
@ -846,6 +849,8 @@ func (s *StateDB) IntermediateRoot(deleteEmptyObjects bool) common.Hash {
|
||||||
s.witness.AddState(obj.trie.Witness())
|
s.witness.AddState(obj.trie.Witness())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
pendingAccounts <- obj
|
||||||
|
storageUpdates.Store(time.Since(start).Nanoseconds()) // overwrite with the longest storage update runtime
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
@ -898,9 +903,6 @@ func (s *StateDB) IntermediateRoot(deleteEmptyObjects bool) common.Hash {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
workers.Wait()
|
|
||||||
s.StorageUpdates += time.Since(start)
|
|
||||||
|
|
||||||
// Now we're about to start to write changes to the trie. The trie is so far
|
// Now we're about to start to write changes to the trie. The trie is so far
|
||||||
// _untouched_. We can check with the prefetcher, if it can give us a trie
|
// _untouched_. We can check with the prefetcher, if it can give us a trie
|
||||||
// which has the same root, but also has some content loaded into it.
|
// which has the same root, but also has some content loaded into it.
|
||||||
|
|
@ -908,7 +910,6 @@ func (s *StateDB) IntermediateRoot(deleteEmptyObjects bool) common.Hash {
|
||||||
// Don't check prefetcher if verkle trie has been used. In the context of verkle,
|
// Don't check prefetcher if verkle trie has been used. In the context of verkle,
|
||||||
// only a single trie is used for state hashing. Replacing a non-nil verkle tree
|
// only a single trie is used for state hashing. Replacing a non-nil verkle tree
|
||||||
// here could result in losing uncommitted changes from storage.
|
// here could result in losing uncommitted changes from storage.
|
||||||
start = time.Now()
|
|
||||||
if s.prefetcher != nil {
|
if s.prefetcher != nil {
|
||||||
if trie := s.prefetcher.trie(common.Hash{}, s.originalRoot); trie == nil {
|
if trie := s.prefetcher.trie(common.Hash{}, s.originalRoot); trie == nil {
|
||||||
log.Error("Failed to retrieve account pre-fetcher trie")
|
log.Error("Failed to retrieve account pre-fetcher trie")
|
||||||
|
|
@ -927,8 +928,9 @@ func (s *StateDB) IntermediateRoot(deleteEmptyObjects bool) common.Hash {
|
||||||
// into a shortnode. This requires `B` to be resolved from disk.
|
// into a shortnode. This requires `B` to be resolved from disk.
|
||||||
// Whereas if the created node is handled first, then the collapse is avoided, and `B` is not resolved.
|
// Whereas if the created node is handled first, then the collapse is avoided, and `B` is not resolved.
|
||||||
var (
|
var (
|
||||||
usedAddrs []common.Address
|
usedAddrs []common.Address
|
||||||
deletedAddrs []common.Address
|
deletedAddrs []common.Address
|
||||||
|
pendingUpdates int
|
||||||
)
|
)
|
||||||
for addr, op := range s.mutations {
|
for addr, op := range s.mutations {
|
||||||
if op.applied {
|
if op.applied {
|
||||||
|
|
@ -939,16 +941,24 @@ func (s *StateDB) IntermediateRoot(deleteEmptyObjects bool) common.Hash {
|
||||||
if op.isDelete() {
|
if op.isDelete() {
|
||||||
deletedAddrs = append(deletedAddrs, addr)
|
deletedAddrs = append(deletedAddrs, addr)
|
||||||
} else {
|
} else {
|
||||||
s.updateStateObject(s.stateObjects[addr])
|
pendingUpdates += 1
|
||||||
s.AccountUpdated += 1
|
s.AccountUpdated += 1
|
||||||
}
|
}
|
||||||
usedAddrs = append(usedAddrs, addr) // Copy needed for closure
|
usedAddrs = append(usedAddrs, addr) // Copy needed for closure
|
||||||
}
|
}
|
||||||
|
for pendingUpdates > 0 {
|
||||||
|
select {
|
||||||
|
case obj := <-pendingAccounts:
|
||||||
|
s.updateStateObject(obj)
|
||||||
|
pendingUpdates--
|
||||||
|
}
|
||||||
|
}
|
||||||
for _, deletedAddr := range deletedAddrs {
|
for _, deletedAddr := range deletedAddrs {
|
||||||
s.deleteStateObject(deletedAddr)
|
s.deleteStateObject(deletedAddr)
|
||||||
s.AccountDeleted += 1
|
s.AccountDeleted += 1
|
||||||
}
|
}
|
||||||
s.AccountUpdates += time.Since(start)
|
s.AccountUpdates += time.Since(start)
|
||||||
|
s.StorageUpdates += time.Duration(storageUpdates.Load())
|
||||||
|
|
||||||
if s.prefetcher != nil {
|
if s.prefetcher != nil {
|
||||||
s.prefetcher.used(common.Hash{}, s.originalRoot, usedAddrs, nil)
|
s.prefetcher.used(common.Hash{}, s.originalRoot, usedAddrs, nil)
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue