perf(engine): skip transaction prewarming for small blocks (#22059)

Co-authored-by: yk <yongkang@tempo.xyz>
Co-authored-by: Amp <amp@ampcode.com>
This commit is contained in:
Georgios Konstantopoulos
2026-02-11 15:37:04 -05:00
committed by GitHub
parent aa983b49af
commit 0b7cd60668
2 changed files with 30 additions and 1 deletions

View File

@@ -94,6 +94,17 @@ pub const SPARSE_TRIE_MAX_NODES_SHRINK_CAPACITY: usize = 1_000_000;
/// 144MB.
pub const SPARSE_TRIE_MAX_VALUES_SHRINK_CAPACITY: usize = 1_000_000;
/// Gas used threshold below which prewarming is skipped for small blocks.
///
/// Based on analysis of 100 mainnet blocks (starting at block 24,425,210), reth's `new_payload`
/// winrate drops from 88% on 40-50M gas blocks to 49% on 0-10M gas blocks. The root cause is the
/// fixed overhead of spawning prewarm workers (building state providers, creating EVM instances,
/// wrapping precompiles) which exceeds execution time on small blocks.
///
/// 20M gas is used as the threshold because ~23% of recent mainnet blocks fall under this level
/// where prewarming overhead dominates.
pub const SMALL_BLOCK_GAS_THRESHOLD: u64 = 20_000_000;
/// Type alias for [`PayloadHandle`] returned by payload processor spawn methods.
type IteratorPayloadHandle<Evm, I, N> = PayloadHandle<
WithTxEnv<TxEnvFor<Evm>, <I as ExecutableTxIterator<Evm>>::Recovered>,
@@ -431,7 +442,8 @@ where
where
P: BlockReader + StateProviderFactory + StateReader + Clone + 'static,
{
let skip_prewarm = self.disable_transaction_prewarming;
let skip_prewarm = self.disable_transaction_prewarming ||
(env.gas_used > 0 && env.gas_used < SMALL_BLOCK_GAS_THRESHOLD);
let saved_cache = self.disable_state_cache.not().then(|| self.cache_for(env.parent_hash));
@@ -972,6 +984,10 @@ pub struct ExecutionEnv<Evm: ConfigureEvm> {
/// Used to determine parallel worker count for prewarming.
/// A value of 0 indicates the count is unknown.
pub transaction_count: usize,
/// Total gas used in the block.
/// Used to skip prewarming for small blocks (see [`SMALL_BLOCK_GAS_THRESHOLD`]).
/// A value of 0 indicates the gas used is unknown.
pub gas_used: u64,
/// Withdrawals included in the block.
/// Used to generate prefetch targets for withdrawal addresses.
pub withdrawals: Option<Vec<Withdrawal>>,
@@ -988,6 +1004,7 @@ where
parent_hash: Default::default(),
parent_state_root: Default::default(),
transaction_count: 0,
gas_used: 0,
withdrawals: None,
}
}

View File

@@ -412,6 +412,7 @@ where
parent_hash: input.parent_hash(),
parent_state_root: parent_block.state_root(),
transaction_count: input.transaction_count(),
gas_used: input.gas_used(),
withdrawals: input.withdrawals().map(|w| w.to_vec()),
};
@@ -1563,6 +1564,17 @@ impl<T: PayloadTypes> BlockOrPayload<T> {
}
}
/// Returns the total gas used by all transactions in the payload or block.
pub fn gas_used(&self) -> u64
where
T::ExecutionData: ExecutionPayload,
{
match self {
Self::Payload(payload) => payload.gas_used(),
Self::Block(block) => block.header().gas_used(),
}
}
/// Returns the withdrawals from the payload or block.
pub fn withdrawals(&self) -> Option<&[Withdrawal]>
where