Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
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
23 changes: 23 additions & 0 deletions core/state/statedb.go
Original file line number Diff line number Diff line change
Expand Up @@ -786,6 +786,18 @@ func (s *StateDB) Finalise(deleteEmptyObjects bool) {
// It is called in between transactions to get the root hash that
// goes into transaction receipts.
func (s *StateDB) IntermediateRoot(deleteEmptyObjects bool) common.Hash {
return s.intermediateRoot(deleteEmptyObjects, false)
}

// IntermediateRootPrefetch triggers trie loading for cache warming without
// computing the actual root hash, optimized for prefetching.
func (s *StateDB) IntermediateRootPrefetch(deleteEmptyObjects bool) {
s.intermediateRoot(deleteEmptyObjects, true)
}

// intermediateRoot is the internal implementation that supports both normal
// and prefetch modes to reduce memory allocations in prefetching scenarios.
func (s *StateDB) intermediateRoot(deleteEmptyObjects bool, prefetchMode bool) common.Hash {
// Finalise all the dirty storage states and write them into the tries
s.Finalise(deleteEmptyObjects)

Expand Down Expand Up @@ -835,6 +847,10 @@ func (s *StateDB) IntermediateRoot(deleteEmptyObjects bool) common.Hash {
workers.Go(func() error {
if s.db.TrieDB().IsVerkle() {
obj.updateTrie()
} else if prefetchMode {
// In prefetch mode, flushes cached storage mutations to trie
// for cache warming without computing the expensive root hash
obj.updateTrie()
} else {
obj.updateRoot()

Expand Down Expand Up @@ -935,6 +951,13 @@ func (s *StateDB) IntermediateRoot(deleteEmptyObjects bool) common.Hash {
if s.prefetcher != nil {
s.prefetcher.used(common.Hash{}, s.originalRoot, usedAddrs, nil)
}

// In prefetch mode, skip expensive hash computation since we only want
// the side effects of trie loading for cache warming
if prefetchMode {
return common.Hash{}
}

// Track the amount of time wasted on hashing the account trie
defer func(start time.Time) { s.AccountHashes += time.Since(start) }(time.Now())

Expand Down
10 changes: 3 additions & 7 deletions core/state_prefetcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -111,18 +111,14 @@ func (p *statePrefetcher) Prefetch(block *types.Block, statedb *state.StateDB, c
fails.Add(1)
return nil // Ugh, something went horribly wrong, bail out
}
// Pre-load trie nodes for the intermediate root.
//
// This operation incurs significant memory allocations due to
// trie hashing and node decoding. TODO(rjl493456442): investigate
// ways to mitigate this overhead.
stateCpy.IntermediateRoot(true)
// Pre-load trie nodes for cache warming without computing the actual
// intermediate root hash, reducing memory allocations and cpu cost from hashing.
stateCpy.IntermediateRootPrefetch(true)
return nil
})
}
workers.Wait()

blockPrefetchTxsValidMeter.Mark(int64(len(block.Transactions())) - fails.Load())
blockPrefetchTxsInvalidMeter.Mark(fails.Load())
return
}