Skip to content

Fetch EVM block headers in parallel for faster sync#668

Open
acedward wants to merge 2 commits intov-nextfrom
feature/parallel-evm-block-fetch
Open

Fetch EVM block headers in parallel for faster sync#668
acedward wants to merge 2 commits intov-nextfrom
feature/parallel-evm-block-fetch

Conversation

@acedward
Copy link
Copy Markdown
Contributor

@acedward acedward commented Apr 8, 2026

Summary

  • The EVM fetcher's readData was calling eth_getBlockByNumber sequentially for each block in the step range. With stepSize=9, that's 9 serial RPC round-trips per batch, making the fetcher the bottleneck for the entire sync pipeline.
  • Switch from genOnDemandPageRequests (lazy/sequential) to genImmediatePageRequests (eager/parallel via Promise.all), so all block headers in the range are fetched concurrently.
  • Adds ISO timestamp to the finalized-block log line for profiling.
  • Adds e2e/performance/ benchmark that syncs NTP + Arbitrum + Midnight (PGLite or real PostgreSQL).

Benchmark results (Arbitrum mainnet + Midnight mainnet, real PostgreSQL)

stepSize Before (sequential) After (parallel) Speedup
9 1.48 blocks/s 6.37 blocks/s 4.3×
18 1.61 blocks/s 9.10 blocks/s 5.7×
36 1.67 blocks/s 22.5 blocks/s 13.5×

Test plan

  • Ran e2e/performance/perf-test.ts with PGLite (in-memory) — all 120 blocks finalize in <0.5s
  • Ran with real PostgreSQL + both primitives (EVM PaimaL2 + Midnight Generic) — confirmed 4.3× speedup at stepSize=9
  • Verified doubling stepSize now actually scales throughput (previously flat due to sequential fetch)
  • Run existing e2e test suite to confirm no regressions

🤖 Generated with Claude Code

acedward and others added 2 commits April 7, 2026 23:16
The EVM fetcher's readData loop was fetching each block header one at a
time via individual eth_getBlockByNumber RPC calls. With stepSize=9 this
meant 9 sequential round-trips per batch, making the fetcher the
bottleneck for the entire sync pipeline (~1.5 blocks/s).

Switch from genOnDemandPageRequests (lazy, sequential) to
genImmediatePageRequests (eager, parallel via Promise.all). This fires
all getBlock calls concurrently, reducing per-batch latency from
~N×RTT to ~1×RTT.

Benchmarked with Arbitrum mainnet + Midnight mainnet + real PostgreSQL:
  stepSize=9:  1.48 → 6.37 blocks/s  (4.3× faster)
  stepSize=36: 1.67 → 22.5 blocks/s  (13.5× faster)

Also adds:
- Timestamp to finalized-block log line for easier profiling
- e2e/performance/ benchmark (NTP + Arbitrum + Midnight, PGLite or real PG)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
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