Skip to content

Commit

Permalink
refactor trie_prefetcher to be similar to upstream structurally (#727)
Browse files Browse the repository at this point in the history
Co-authored-by: Quentin McGaw <[email protected]>
Co-authored-by: Arran Schlosberg <[email protected]>
  • Loading branch information
3 people authored Jan 3, 2025
1 parent c167754 commit cf1dd75
Show file tree
Hide file tree
Showing 10 changed files with 585 additions and 418 deletions.
1 change: 1 addition & 0 deletions RELEASES.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
## [v0.14.1](https://github.com/ava-labs/coreth/releases/tag/v0.14.1)
- Remove API eth_getAssetBalance that was used to query ANT balances (deprecated since v0.10.0)
- Remove legacy gossip handler and metrics (deprecated since v0.10.0)
- Refactored trie_prefetcher.go to be structurally similar to [upstream](https://github.com/ethereum/go-ethereum/tree/v1.13.14).

## [v0.14.0](https://github.com/ava-labs/coreth/releases/tag/v0.14.0)
- Minor version update to correspond to avalanchego v1.12.0 / Etna.
Expand Down
20 changes: 4 additions & 16 deletions core/blockchain.go
Original file line number Diff line number Diff line change
Expand Up @@ -1288,16 +1288,6 @@ func (bc *BlockChain) insertBlock(block *types.Block, writes bool) error {
blockContentValidationTimer.Inc(time.Since(substart).Milliseconds())

// No validation errors for the block
var activeState *state.StateDB
defer func() {
// The chain importer is starting and stopping trie prefetchers. If a bad
// block or other error is hit however, an early return may not properly
// terminate the background threads. This defer ensures that we clean up
// and dangling prefetcher, without deferring each and holding on live refs.
if activeState != nil {
activeState.StopPrefetcher()
}
}()

// Retrieve the parent block to determine which root to build state on
substart = time.Now()
Expand All @@ -1316,8 +1306,8 @@ func (bc *BlockChain) insertBlock(block *types.Block, writes bool) error {
blockStateInitTimer.Inc(time.Since(substart).Milliseconds())

// Enable prefetching to pull in trie node paths while processing transactions
statedb.StartPrefetcher("chain", bc.cacheConfig.TriePrefetcherParallelism)
activeState = statedb
statedb.StartPrefetcher("chain", state.WithConcurrentWorkers(bc.cacheConfig.TriePrefetcherParallelism))
defer statedb.StopPrefetcher()

// Process block using the parent state as reference point
pstart := time.Now()
Expand Down Expand Up @@ -1675,10 +1665,8 @@ func (bc *BlockChain) reprocessBlock(parent *types.Block, current *types.Block)
}

// Enable prefetching to pull in trie node paths while processing transactions
statedb.StartPrefetcher("chain", bc.cacheConfig.TriePrefetcherParallelism)
defer func() {
statedb.StopPrefetcher()
}()
statedb.StartPrefetcher("chain", state.WithConcurrentWorkers(bc.cacheConfig.TriePrefetcherParallelism))
defer statedb.StopPrefetcher()

// Process previously stored block
receipts, _, usedGas, err := bc.processor.Process(current, parent.Header(), statedb, vm.Config{})
Expand Down
22 changes: 20 additions & 2 deletions core/state/statedb.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ import (
"github.com/ava-labs/coreth/trie"
"github.com/ava-labs/coreth/trie/trienode"
"github.com/ava-labs/coreth/trie/triestate"
"github.com/ava-labs/coreth/utils"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/log"
Expand Down Expand Up @@ -201,16 +202,33 @@ func NewWithSnapshot(root common.Hash, db Database, snap snapshot.Snapshot) (*St
return sdb, nil
}

type workerPool struct {
*utils.BoundedWorkers
}

func (wp *workerPool) Done() {
// Done is guaranteed to only be called after all work is already complete,
// so Wait()ing is redundant, but it also releases resources.
wp.BoundedWorkers.Wait()
}

func WithConcurrentWorkers(prefetchers int) PrefetcherOption {
pool := &workerPool{
BoundedWorkers: utils.NewBoundedWorkers(prefetchers),
}
return WithWorkerPools(func() WorkerPool { return pool })
}

// StartPrefetcher initializes a new trie prefetcher to pull in nodes from the
// state trie concurrently while the state is mutated so that when we reach the
// commit phase, most of the needed data is already hot.
func (s *StateDB) StartPrefetcher(namespace string, maxConcurrency int) {
func (s *StateDB) StartPrefetcher(namespace string, opts ...PrefetcherOption) {
if s.prefetcher != nil {
s.prefetcher.close()
s.prefetcher = nil
}
if s.snap != nil {
s.prefetcher = newTriePrefetcher(s.db, s.originalRoot, namespace, maxConcurrency)
s.prefetcher = newTriePrefetcher(s.db, s.originalRoot, namespace, opts...)
}
}

Expand Down
Loading

0 comments on commit cf1dd75

Please sign in to comment.