perf: skip AccessListInspector when blocklist is empty#902
Open
vbuilder69420 wants to merge 1 commit intoflashbots:developfrom
Open
perf: skip AccessListInspector when blocklist is empty#902vbuilder69420 wants to merge 1 commit intoflashbots:developfrom
vbuilder69420 wants to merge 1 commit intoflashbots:developfrom
Conversation
7c06c20 to
3d30409
Compare
…klist check Remove the AccessListInspector entirely from RBuilderEVMInspector. Replace the per-opcode blocklist tracking with a post-execution check against ResultAndState.state (EvmState = HashMap<Address, Account>), which already contains every address touched during EVM execution. The AccessListInspector called step() on every EVM opcode to build an access list, solely used to check addresses against the blocklist. Profiling showed this inspector overhead consumed ~52% of CPU time. The EVM execution result already contains the same information in its state diff, making the inspector entirely redundant. Changes: - order_commit.rs: Use create_evm() (NoOpInspector) when no used_state_tracer is needed. Check blocklist via res.state.keys() after execution instead of via access list. - evm_inspector.rs: Remove AccessListInspector from RBuilderEVMInspector. The inspector now only wraps the optional UsedStateEVMInspector (used by parallel builder / EVM caching). This optimization works regardless of whether a blocklist is configured. Benchmark (builder-lab, 100 TPS, seed=42, 60s profiling window): | Metric | Before | After | Change | |---------------------|----------|----------|--------| | Block fill p50 | 96.8ms | 58.9ms | -39% | | Block fill p95 | 129.2ms | 87.1ms | -33% | | E2E latency p50 | 98ms | 61ms | -38% | | E2E latency p95 | 134ms | 92ms | -31% | | Blocks submitted | 255 | 342 | +34% | | Txs included | 17,882 | 23,449 | +31% | Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
3d30409 to
1dd3fe6
Compare
4 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
AccessListInspectorwith a post-execution blocklist check againstResultAndState.state(which isHashMap<Address, Account>containing every address touched during execution)Motivation
Profiling rbuilder under load (100 TPS via builder-playground contender) revealed that ~52% of CPU time is spent in the
AccessListInspectorcall chain:Evm::transactinspect_instructionsInspector::step(combined)AccessListInspector::stepThe
AccessListInspectorcallsstep()on every EVM opcode to track which addresses are accessed, then checks them against the blocklist. However,ResultAndState.state(EvmState = HashMap<Address, Account>) already contains every address touched during execution — the inspector is redundant.What changed
Fast path (no
used_state_tracer): Usecreate_evm()withNoOpInspector, checkres.state.keys()against blocklist after execution.Slow path (
used_state_traceractive, e.g. parallel builder): Still attachRBuilderEVMInspectorforUsedStateEVMInspector, but replace the access-list blocklist check with the same state-diff check.Benchmark Results
Tested with builder-lab using the
rbuilder/binrecipe,debug-fastbuild profile, seed=42 for deterministic transactions across runs:Correctness note
The
EvmStateinResultAndStatecontains all accounts that were read or written during execution — this is a superset of whatAccessListInspectortracks (which only records storage slot access patterns). Usingstate.keys()for the blocklist check is actually more conservative (catches more addresses) than the previous approach.Test plan
🤖 Generated with Claude Code