Skip to content

perf(anvil): prefetch system call slots on forks - #18360

Open
sembrestels wants to merge 1 commit into
foundry-rs:masterfrom
sembrestels:perf/anvil-system-call-prefetch
Open

sembrestels wants to merge 1 commit into
foundry-rs:masterfrom
sembrestels:perf/anvil-system-call-prefetch

Conversation

@sembrestels

Copy link
Copy Markdown

Since #15975, every block anvil mines on a fork runs the EIP-2935, EIP-4788 and EIP-7002/7251 system calls. Their storage slots are new for each block, so on a fork each call makes a cold eth_getStorageAt round trip, and the EVM makes them one after another: three round trips of latency per mined block before the first transaction runs. Before executing a block, anvil now computes the slots these calls will read from the block number and timestamp ((number - 1) % 8191 for the block hash history, timestamp % 8191 and + 8191 for the beacon roots, slots 0 to 3 of the request queues) and starts fetching them at once through the fork backend, the same way fork_prefetch warms a new fork block. The EVM's reads then join the requests in flight or hit the cache, so it gets the same values as before and sends no extra requests. Keys held locally are skipped, a key the calls end up not reading stays out of the disk cache, and a database without a fork does nothing.

Results

Gnosis fork at block 49194000 through a logging proxy, --no-storage-caching, profiling builds, three alternating runs each.

master this PR
20 × evm_mine 16.28 s (15.65 / 16.00 / 17.18) 5.94 s (5.95 / 5.97 / 5.89)
upstream requests 60 60
a script's fork test (stake lifecycle, ~10 blocks) 41.4 s (42.6 / 40.6 / 41.1) 32.8 s (32.2 / 31.8 / 34.5)
upstream requests 233–237 223–229

For reference, v1.7.1 (before the system calls) takes 5.14 s for the 20 blocks with 20 requests, and 30.7–35.4 s for the test.

The EIP-2935, EIP-4788 and EIP-7002/7251 system calls read slots that are new
for each block, so on a fork each one was a cold storage round trip, made one
after another. Fetch them all at once before the block executes.

20 evm_mine calls on a Gnosis fork: 16.3s on master, 5.9s with this change,
with the same 60 upstream requests.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant