From 8ea52f50367c64ee99ccf340b4a407368a2dcc14 Mon Sep 17 00:00:00 2001 From: Manav Darji Date: Wed, 30 Apr 2025 14:51:46 -0400 Subject: [PATCH] core: avoid starting prefetcher before process block to avoid duplication We moved the starting of prefetcher to process block function as we need to copy the state for block-stm (and hence we need separate prefetchers for both). The witness generation code from upstream starts the prefetcher early as the witness object is constructed. This lead to OOM issues as we would be starting duplicate prefetchers per block leading to increase in go routines with time (eventually OOM). This commit skips starting the prefetcher earlier and instead pass the witness to process block to start it later. --- core/blockchain.go | 13 ++++++++----- core/blockchain_test.go | 2 +- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/core/blockchain.go b/core/blockchain.go index f124caee91..e00fb8fddc 100644 --- a/core/blockchain.go +++ b/core/blockchain.go @@ -577,7 +577,7 @@ func NewParallelBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis return bc, nil } -func (bc *BlockChain) ProcessBlock(block *types.Block, parent *types.Header) (_ types.Receipts, _ []*types.Log, _ uint64, _ *state.StateDB, vtime time.Duration, blockEndErr error) { +func (bc *BlockChain) ProcessBlock(block *types.Block, parent *types.Header, witness *stateless.Witness) (_ types.Receipts, _ []*types.Log, _ uint64, _ *state.StateDB, vtime time.Duration, blockEndErr error) { // Process the block using processor and parallelProcessor at the same time, take the one which finishes first, cancel the other, and return the result ctx, cancel := context.WithCancel(context.Background()) defer cancel() @@ -629,7 +629,7 @@ func (bc *BlockChain) ProcessBlock(block *types.Block, parent *types.Header) (_ processorCount++ go func() { - parallelStatedb.StartPrefetcher("chain", nil) + parallelStatedb.StartPrefetcher("chain", witness) pstart := time.Now() res, err := bc.parallelProcessor.Process(block, parallelStatedb, bc.vmConfig, ctx) blockExecutionParallelTimer.UpdateSince(pstart) @@ -654,7 +654,7 @@ func (bc *BlockChain) ProcessBlock(block *types.Block, parent *types.Header) (_ processorCount++ go func() { - statedb.StartPrefetcher("chain", nil) + statedb.StartPrefetcher("chain", witness) pstart := time.Now() res, err := bc.processor.Process(block, statedb, bc.vmConfig, ctx) blockExecutionSerialTimer.UpdateSince(pstart) @@ -2344,7 +2344,10 @@ func (bc *BlockChain) insertChain(chain types.Blocks, setHead bool, makeWitness return nil, it.index, err } } - statedb.StartPrefetcher("chain", witness) + // Bor: We start the prefetcher in process block function called below + // and not here as we copy state for block-stm in that function. Also, + // we don't want to start duplicate prefetchers per block. + // statedb.StartPrefetcher("chain", witness) } activeState = statedb @@ -2373,7 +2376,7 @@ func (bc *BlockChain) insertChain(chain types.Blocks, setHead bool, makeWitness // Process block using the parent state as reference point pstart := time.Now() - receipts, logs, usedGas, statedb, vtime, err := bc.ProcessBlock(block, parent) + receipts, logs, usedGas, statedb, vtime, err := bc.ProcessBlock(block, parent, witness) activeState = statedb if err != nil { diff --git a/core/blockchain_test.go b/core/blockchain_test.go index 19a9975e5d..cf026e8198 100644 --- a/core/blockchain_test.go +++ b/core/blockchain_test.go @@ -176,7 +176,7 @@ func testBlockChainImport(chain types.Blocks, blockchain *BlockChain) error { if err != nil { return err } - receipts, logs, usedGas, statedb, _, err := blockchain.ProcessBlock(block, blockchain.GetBlockByHash(block.ParentHash()).Header()) + receipts, logs, usedGas, statedb, _, err := blockchain.ProcessBlock(block, blockchain.GetBlockByHash(block.ParentHash()).Header(), nil) res := &ProcessResult{ Receipts: receipts, Logs: logs,