Reactive EVM stack: repeated benchmark evidence

Measured 8 September 2026. This report replaces the single-run route-search headline with distributions over an explicitly bounded workload. It tests released crates and public historical Ethereum state; no transaction was signed or broadcast.

Results

The 117-pool basket loaded in 1,993.8 ms p50 across 50 fresh processes (p95 4,334.9 ms, min 1,789.2 ms, max 5,186.9 ms). This times pool cold-loading only: cache construction, discovery, graph construction, liquidity-index refresh, and priming searches are separate. It is not total process-to-readiness latency.

Warm search results, in milliseconds:

Route Measured runs Heuristic p50 Heuristic p95 Heuristic max Exhaustive completion p50
10 WETH -> USDC 300 3.77 4.29 47.73 151.03
100 LINK -> AAVE 300 8.43 16.51 117.90 353.71
1000 DAI -> UNI 300 7.06 10.88 50.20 847.57

Each heuristic winner matched the exhaustive reference in all 900/900 measured iterations, with zero measured-loop RPC requests and zero failed searches. These are repeated timings of nine route/block combinations, not 900 independent market opportunities or a general proof of optimality. Heuristic timing ends at heuristic completion; the exhaustive continuation runs afterward and is reported separately. Do not label the heuristic timing as exhaustive-search completion or event-to-submission latency. All measured outliers remain in the dataset.

Full-range V3 extraction loads globals, every initialized tick found by scanning the full bitmap, and the observation ring. Each row has 90 measured repetitions and one eth_call per extraction:

Pool Initialized ticks Observations p50 ms p95 ms Max ms
USDC/WETH 0.05% 1,552 723 74.75 99.21 1303.43
USDC/WETH 0.3% 686 1,440 50.16 68.91 1056.99
DAI/WETH 0.3% 492 1,500 47.11 65.51 123.01
All three in one call 2,730 3,663 121.01 157.81 213.02

Individual and batched decoded states matched exactly in 99/99 checks, including warmups. This checks batching equivalence against the individual full extraction path; it is not an independent proof of every storage value. The measured transport recorded one HTTP packet and one eth_call for each single or three-pool extraction. It does not establish a one-call capacity for 117 pools.

Environment and sampling

Provider limits and exclusions

The pre-collection smoke test found that one 117-pool extraction returned 2,458,400 bytes against this endpoint's 1,000,000-byte return limit. The final collection therefore uses batches of at most 16 pools. The published cold-load numbers include this practical batching configuration, not a hypothetical single request. Rate-limited smoke tests and an exploratory second-provider check were configuration diagnostics and are excluded from the declared main collection.

Across the 50 measured cold-load phases, the transport counted 800 eth_calls, 50 eth_getAccountInfo probes, and 300 standard account-read requests in 1,150 HTTP packets. Thirty probes returned method-unavailable responses; the supported fallback completed successfully. There were no failed pool initializations or liquidity-refresh failures in the formal run. Capability fallbacks are retained in the timings and raw logs.

The older 997.2 ms cold-load / 4.37–9.78 ms warm-search observation used an earlier release and environment. It remains historical evidence, not an apples-to-apples speedup baseline. The separate Aave liquidation fixture was not rerun here. These infrastructure timings do not measure transaction submission, inclusion, settlement, or strategy return.

Reproduce and inspect

The route harness adapts the published evm-amm-search 0.2.0 examples/docs_route_benchmark.rs; the full-sync harness uses public evm-amm-state / evm-fork-cache APIs. Source and the locked dependency graph are included. The runner needs an archive endpoint supporting state overrides. It reads the URL from the environment and redacts it from retained logs.

cargo build --release --locked --bins
# Set E2E_RPC_URL in your environment; do not commit credentials.
python3 run_benchmarks.py
python3 summarize.py

Use a copy of this directory to rerun without overwriting the retained results. The runner fixes sampling and workload before collection. The summarizer checks sample counts, unchanged pool membership, pool readiness, warm-search success and RPC counts, batch parity, and single-call accounting before writing summaries. results/measurements.jsonl contains all measured rows plus warmups; results/*.log and their metadata retain the original redacted output and hashes. successful-build-binaries.json identifies the actual tested release binaries. SHA256SUMS binds the published evidence files.