# 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

- Apple M1 Pro, 10 logical CPUs, 16 GiB RAM; macOS 26.6.2 arm64; Rust 1.90.0;
  optimized release builds. Four search workers.
- Published `evm-amm-search 0.2.0`, `evm-amm-state 0.3.0`, and
  `evm-fork-cache 0.4.0`; exact dependencies in `Cargo.lock`.
- Fixed blocks: 25,494,941; 25,495,041; 25,496,041. The same 117 pools comprise
  28 Uniswap V2 and 89 Uniswap V3 pools, eight tokens, and 234 directed edges.
- Cold starts: 30 fresh processes at the first block and 10 at each subsequent
  block. Local persistent caching disabled; every run initialized all 117 pools.
- Warm searches: 100 measured iterations per route per block, after five excluded
  warmups. Balanced liquidity-aware search, at most three hops, final-candidate
  EVM simulation enabled. Warmups and individual measurements remain in raw data.
- Full V3 extraction: 30 measured repetitions per block after three warmups;
  individual-versus-batch ordering alternates to avoid always favoring one path.
- Paid QuickNode archive HTTP with gzip. A counted transport caps HTTP packets
  at 20 requests/second; pacing is included in network acquisition timings.
  Provider-side cache state and background OS scheduling were uncontrolled.
- p50 is the sample median; p95 uses linear interpolation at `(n-1)*0.95`.
  Per-block breakdowns, minima, maxima, and RPC totals are in `results/summary.json`.

## 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_call`s,
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.

```sh
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.
