mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-03-20 01:50:40 +00:00
## Summary - Avoid allocating a `map[common.Address]*constructionAccountAccess` on every `enterScope()` call in the BAL access list builder - Push `nil` onto the stack and lazily allocate via `currentScope()` only when a state change occurs - `exitScope()` short-circuits when child scope is nil (no merge needed) - Adds correctness test (`TestLazyScopeCorrectness`) and benchmark (`BenchmarkPrecompileScopes`) ## Context The [execution-specs benchmark tests](https://github.com/ethereum/execution-specs/blob/tests-benchmark@v0.0.7/tests/benchmark/compute/precompile/test_alt_bn128.py) for `bn128_add` (line 19) and `bn128_pairing` (line 496) create blocks with transactions that loop `STATICCALL` to precompiles thousands of times. Each STATICCALL triggers `EnterScope()`/`ExitScope()` in the BAL tracer, but precompile calls produce empty scopes since they don't touch state (`AddBalance(0)` is filtered by `!amount.IsZero()`). The previous implementation eagerly allocated a map on every `enterScope()`, creating ~200K unnecessary heap allocations per transaction for `bn128_add` (150 gas, ~200K calls per 30M gas block). **Note:** For benchmark-only workloads that don't need BAL validation, `--bal.executionmode=sequential` can be used to skip the parallel processor entirely and avoid all tracing overhead. ## Benchmark results Precompile calls with no state changes per scope: | Calls | Before (ns/op) | After (ns/op) | Speedup | Allocs Before → After | |---|---|---|---|---| | 100 | 5,073 | 1,499 | **3.4x** | 119 → 19 | | 1,000 | 47,392 | 3,199 | **14.8x** | 1,019 → 19 | | 10,000 | 493,651 | 20,644 | **23.9x** | 10,019 → 19 | | 100,000 | 4,526,165 | 192,502 | **23.5x** | 100,019 → 19 | ## Test plan - [x] `TestLazyScopeCorrectness` — mixed workload: precompile scopes + state-changing scopes + reverted scopes - [x] `BenchmarkPrecompileScopes` — measures scope tracking overhead for 100 to 100K empty scopes - [x] All `core/vm/` tests pass - [x] All `core/types/bal/` tests pass (pre-existing failures in `TestBALEncoding` and `TestBlockAccessListValidation` unrelated) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> |
||
|---|---|---|
| .. | ||
| filtermaps | ||
| forkid | ||
| history | ||
| overlay | ||
| rawdb | ||
| state | ||
| stateless | ||
| tracing | ||
| txpool | ||
| types | ||
| vm | ||
| .gitignore | ||
| bench_test.go | ||
| bintrie_witness_test.go | ||
| block_access_list_tracer.go | ||
| block_validator.go | ||
| block_validator_test.go | ||
| blockchain.go | ||
| blockchain_insert.go | ||
| blockchain_reader.go | ||
| blockchain_repair_test.go | ||
| blockchain_sethead_test.go | ||
| blockchain_snapshot_test.go | ||
| blockchain_stats.go | ||
| blockchain_test.go | ||
| chain_makers.go | ||
| chain_makers_test.go | ||
| dao_test.go | ||
| error.go | ||
| eth_transfer_logs_test.go | ||
| events.go | ||
| evm.go | ||
| gaspool.go | ||
| gen_genesis.go | ||
| genesis.go | ||
| genesis_alloc.go | ||
| genesis_test.go | ||
| headerchain.go | ||
| headerchain_test.go | ||
| mkalloc.go | ||
| parallel_state_processor.go | ||
| rlp_test.go | ||
| sender_cacher.go | ||
| state_prefetcher.go | ||
| state_processor.go | ||
| state_processor_test.go | ||
| state_transition.go | ||
| stateless.go | ||
| txindexer.go | ||
| txindexer_test.go | ||
| types.go | ||