mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-06-12 01:41:36 +00:00
core/state: invoke prefetcher
This commit is contained in:
parent
1ae462f08d
commit
38c7021c73
3 changed files with 32 additions and 2 deletions
|
|
@ -80,10 +80,10 @@ type Hasher interface {
|
||||||
// asynchronously warm up trie/state data ahead of mutations or hashing.
|
// asynchronously warm up trie/state data ahead of mutations or hashing.
|
||||||
type Prefetcher interface {
|
type Prefetcher interface {
|
||||||
// PrefetchAccount schedules the account for prefetching.
|
// PrefetchAccount schedules the account for prefetching.
|
||||||
PrefetchAccount(addresses []common.Address)
|
PrefetchAccount(addresses []common.Address, read bool)
|
||||||
|
|
||||||
// PrefetchStorage schedules the storage slot for prefetching.
|
// PrefetchStorage schedules the storage slot for prefetching.
|
||||||
PrefetchStorage(addr common.Address, keys []common.Hash)
|
PrefetchStorage(addr common.Address, keys []common.Hash, read bool)
|
||||||
}
|
}
|
||||||
|
|
||||||
// WitnessCollector is an optional extension implemented by hashers that can
|
// WitnessCollector is an optional extension implemented by hashers that can
|
||||||
|
|
|
||||||
|
|
@ -191,6 +191,12 @@ func (s *stateObject) GetCommittedState(key common.Hash) common.Hash {
|
||||||
s.db.StorageReads += time.Since(start)
|
s.db.StorageReads += time.Since(start)
|
||||||
|
|
||||||
s.originStorage[key] = value
|
s.originStorage[key] = value
|
||||||
|
|
||||||
|
// Schedule the resolved storage slots for prefetching if it's enabled.
|
||||||
|
prefetch, ok := s.db.hasher.(Prefetcher)
|
||||||
|
if ok {
|
||||||
|
prefetch.PrefetchStorage(s.address, []common.Hash{key}, true)
|
||||||
|
}
|
||||||
return value
|
return value
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -223,6 +229,7 @@ func (s *stateObject) setState(key common.Hash, value common.Hash, origin common
|
||||||
// finalise moves all dirty storage slots into the pending area to be hashed or
|
// finalise moves all dirty storage slots into the pending area to be hashed or
|
||||||
// committed later. It is invoked at the end of every transaction.
|
// committed later. It is invoked at the end of every transaction.
|
||||||
func (s *stateObject) finalise() {
|
func (s *stateObject) finalise() {
|
||||||
|
slotsToPrefetch := make([]common.Hash, 0, len(s.dirtyStorage))
|
||||||
for key, value := range s.dirtyStorage {
|
for key, value := range s.dirtyStorage {
|
||||||
if origin, exist := s.uncommittedStorage[key]; exist && origin == value {
|
if origin, exist := s.uncommittedStorage[key]; exist && origin == value {
|
||||||
// The slot is reverted to its original value, delete the entry
|
// The slot is reverted to its original value, delete the entry
|
||||||
|
|
@ -235,6 +242,7 @@ func (s *stateObject) finalise() {
|
||||||
// The slot is different from its original value and hasn't been
|
// The slot is different from its original value and hasn't been
|
||||||
// tracked for commit yet.
|
// tracked for commit yet.
|
||||||
s.uncommittedStorage[key] = s.GetCommittedState(key)
|
s.uncommittedStorage[key] = s.GetCommittedState(key)
|
||||||
|
slotsToPrefetch = append(slotsToPrefetch, key)
|
||||||
}
|
}
|
||||||
// Aggregate the dirty storage slots into the pending area. It might
|
// Aggregate the dirty storage slots into the pending area. It might
|
||||||
// be possible that the value of tracked slot here is same with the
|
// be possible that the value of tracked slot here is same with the
|
||||||
|
|
@ -251,6 +259,12 @@ func (s *stateObject) finalise() {
|
||||||
// of the newly-created object as it's no longer eligible for self-destruct
|
// of the newly-created object as it's no longer eligible for self-destruct
|
||||||
// by EIP-6780. For non-newly-created objects, it's a no-op.
|
// by EIP-6780. For non-newly-created objects, it's a no-op.
|
||||||
s.newContract = false
|
s.newContract = false
|
||||||
|
|
||||||
|
// Schedule the resolved storage slots for prefetching if it's enabled.
|
||||||
|
prefetch, ok := s.db.hasher.(Prefetcher)
|
||||||
|
if ok {
|
||||||
|
prefetch.PrefetchStorage(s.address, slotsToPrefetch, false)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// updateTrie is responsible for persisting cached storage changes into the
|
// updateTrie is responsible for persisting cached storage changes into the
|
||||||
|
|
|
||||||
|
|
@ -555,6 +555,12 @@ func (s *StateDB) getStateObject(addr common.Address) *stateObject {
|
||||||
// Insert into the live set
|
// Insert into the live set
|
||||||
obj := newObject(s, addr, acct)
|
obj := newObject(s, addr, acct)
|
||||||
s.setStateObject(obj)
|
s.setStateObject(obj)
|
||||||
|
|
||||||
|
// Schedule the resolved account for prefetching if it's enabled.
|
||||||
|
prefetcher, ok := s.hasher.(Prefetcher)
|
||||||
|
if ok {
|
||||||
|
prefetcher.PrefetchAccount([]common.Address{addr}, true)
|
||||||
|
}
|
||||||
return obj
|
return obj
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -725,6 +731,7 @@ func (s *StateDB) LogsForBurnAccounts() []*types.Log {
|
||||||
// the journal as well as the refunds. Finalise, however, will not push any updates
|
// the journal as well as the refunds. Finalise, however, will not push any updates
|
||||||
// into the tries just yet. Only IntermediateRoot or Commit will do that.
|
// into the tries just yet. Only IntermediateRoot or Commit will do that.
|
||||||
func (s *StateDB) Finalise(deleteEmptyObjects bool) {
|
func (s *StateDB) Finalise(deleteEmptyObjects bool) {
|
||||||
|
addressesToPrefetch := make([]common.Address, 0, len(s.journal.dirties))
|
||||||
for addr := range s.journal.dirties {
|
for addr := range s.journal.dirties {
|
||||||
obj, exist := s.stateObjects[addr]
|
obj, exist := s.stateObjects[addr]
|
||||||
if !exist {
|
if !exist {
|
||||||
|
|
@ -749,9 +756,18 @@ func (s *StateDB) Finalise(deleteEmptyObjects bool) {
|
||||||
obj.finalise()
|
obj.finalise()
|
||||||
s.markUpdate(addr)
|
s.markUpdate(addr)
|
||||||
}
|
}
|
||||||
|
// At this point, also ship the address off to the prefetcher. The prefetcher
|
||||||
|
// will start loading tries, and when the change is eventually committed,
|
||||||
|
// the commit-phase will be a lot faster
|
||||||
|
addressesToPrefetch = append(addressesToPrefetch, addr)
|
||||||
}
|
}
|
||||||
// Invalidate journal because reverting across transactions is not allowed.
|
// Invalidate journal because reverting across transactions is not allowed.
|
||||||
s.clearJournalAndRefund()
|
s.clearJournalAndRefund()
|
||||||
|
|
||||||
|
prefetcher, ok := s.hasher.(Prefetcher)
|
||||||
|
if ok {
|
||||||
|
prefetcher.PrefetchAccount(addressesToPrefetch, false)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// IntermediateRoot computes the current root hash of the state trie.
|
// IntermediateRoot computes the current root hash of the state trie.
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue