From d07d7999226d5f1657e96189b4bd4f1b86074779 Mon Sep 17 00:00:00 2001 From: sudeepdino008 Date: Mon, 10 Aug 2026 15:58:41 +0200 Subject: [PATCH] execution: drop the per-block worker committed-state cache (#23140) Parallel workers read committed pre-block state through a per-block BlockStateCache tier (TxTask.BlockStateCache). That tier is a pure read cache: the base chain (sd.mem -> StateCache -> files) is frozen for a block's whole execution (sd.mem changes only at blockCache.Flush in completeBlock, after which the next block is scheduled), and intra-block isolation comes from the version map layered on top of the reader. So the tier adds no isolation. It does duplicate StateCache and starve it: a slot read 5000 times in a block reached StateCache once, so StateCache's LRU ranked hot keys as cold. Removing the tier lets workers fill and read StateCache directly, restoring its read stream. Values are unchanged because the base is frozen per block. This removes the worker tier only (TxTask.BlockStateCache and its plumbing). The finalize/apply write buffer (be.blockStateCache) is untouched; later steps of #23140 move it to the version map. --- execution/exec/state.go | 20 +++----------------- execution/exec/txtask.go | 9 --------- execution/stagedsync/exec3.go | 3 --- 3 files changed, 3 insertions(+), 29 deletions(-) diff --git a/execution/exec/state.go b/execution/exec/state.go index 8ef95186554..7960b4c2005 100644 --- a/execution/exec/state.go +++ b/execution/exec/state.go @@ -245,10 +245,9 @@ func (rw *Worker) ResetState(rs *state.StateV3Buffered, chainTx kv.TemporalTx, s if chainTx != nil { getter = rs.Domains().AsGetterMetered(chainTx, rw.readMetrics) } - // Use CachedReaderV3 for parallel workers — caches account data - // on first read per block, providing a stable pre-block committed - // view for GetCommittedState. The blockStateCache is set per block - // via SetBlockStateCache before workers start. + // Parallel workers read the pre-block base directly (sd.mem → StateCache + // → files). The version map on top of this reader gives intra-block + // isolation, so no per-block committed cache is needed here. rw.SetReader(state.NewCachedReaderV3(getter, nil)) } @@ -496,14 +495,6 @@ func (rw *Worker) SetReader(reader state.StateReader) { } } -// SetBlockStateCache updates the block-level account cache on the worker's -// CachedReaderV3. Called before each block's workers start execution. -func (rw *Worker) SetBlockStateCache(cache *state.BlockStateCache) { - if cr, ok := rw.stateReader.(*state.CachedReaderV3); ok { - cr.SetBlockStateCache(cache) - } -} - func (rw *Worker) RunTxTaskNoLock(txTask Task) *TxResult { if txTask.IsHistoric() && !rw.historyMode { // in case if we cancelled execution and commitment happened in the middle of the block, we have to process block @@ -517,11 +508,6 @@ func (rw *Worker) RunTxTaskNoLock(txTask Task) *TxResult { rw.SetReader(state.NewCachedReaderV3(rw.rs.Domains().AsGetterMetered(rw.chainTx, rw.readMetrics), nil)) } - // Set the per-block committed state cache from the task. - if cache := txTask.GetBlockStateCache(); cache != nil { - rw.SetBlockStateCache(cache) - } - if rw.background && rw.chainTx == nil { chainTx, err := rw.chainDb.BeginTemporalRo(rw.ctx) //nolint diff --git a/execution/exec/txtask.go b/execution/exec/txtask.go index 8be793ef8db..d56e4f669ff 100644 --- a/execution/exec/txtask.go +++ b/execution/exec/txtask.go @@ -58,7 +58,6 @@ type Task interface { Version() state.Version VersionMap() *state.VersionMap - GetBlockStateCache() *state.BlockStateCache VersionedReads(ibs *state.IntraBlockState) state.ReadSet VersionedWrites(ibs *state.IntraBlockState) *state.WriteSet Reset(evm *vm.EVM, ibs *state.IntraBlockState, callTracer *calltracer.CallTracer) error @@ -231,10 +230,6 @@ type TxTask struct { signer *types.Signer dependencies []int rules *chain.Rules - - // BlockStateCache holds pre-block account state for stable committed reads. - // Shared across all tasks in the same block. Set by the parallel executor. - BlockStateCache *state.BlockStateCache } func (t *TxTask) compare(other Task) int { @@ -438,10 +433,6 @@ func (t *TxTask) VersionMap() *state.VersionMap { return nil } -func (t *TxTask) GetBlockStateCache() *state.BlockStateCache { - return t.BlockStateCache -} - func (t *TxTask) VersionedReads(ibs *state.IntraBlockState) state.ReadSet { return ibs.VersionedReads() } diff --git a/execution/stagedsync/exec3.go b/execution/stagedsync/exec3.go index afa06e3ae50..c4eed57cdd8 100644 --- a/execution/stagedsync/exec3.go +++ b/execution/stagedsync/exec3.go @@ -718,8 +718,6 @@ func (te *txExecutor) executeBlocks(ctx context.Context, startBlockNum uint64, m }), te.cfg.engine, te.cfg.author, te.cfg.chainConfig) var txTasks []exec.Task - // Per-block committed state cache for parallel workers' GetCommittedState. - blockStateCache := state.NewBlockStateCache() blockStartTxNum := inputTxNum for txIndex := -1; txIndex <= len(txs); txIndex++ { @@ -744,7 +742,6 @@ func (te *txExecutor) executeBlocks(ctx context.Context, startBlockNum uint64, m Trace: dbg.TraceTx(blockNum, txIndex), Hooks: te.hooks, Logger: te.logger, - BlockStateCache: blockStateCache, } txTasks = append(txTasks, txTask)