Bottlenecks Methodology

Repricing only makes sense for operations that can keep up with the throughput anchor. The Bottleneck page measures each compute operation's worst-case throughput directly from the benchmarks and flags the ones already too slow to be priced any cheaper. Two stages turn the raw benchmark runs into that verdict:

  1. Benchmark data collection — synthetic blocks stress one operation at a time; Benchmarkoor records each block's runtime, opcode counts, and throughput (test_mgas_s).
  2. Bottleneck analysis — the worst-case megagas/second per operation is taken across fixtures and clients and compared against the anchor's throughput ceiling.

The companion Repricing Methodology covers how those same benchmarks are turned into proposed gas numbers.

1. Benchmark data collection

The bottleneck verdict is grounded in the actual time each execution client takes to run a specific set of benchmarks. Similar to the methodology of the Gas Cost Estimator project, we generate synthetic blocks that isolate and stress individual EVM operations and use them to derive each operation's throughput.

Concretely, to benchmark a single operation, different blocks are created by varying the number of times the target operation is executed and by changing the parameter values passed to it. These test blocks come from the EEST benchmark suite. The raw data that feeds this analysis was queried from the following two Benchmarkoor suites:

The Benchmarkoor tool then runs each block and collects the metrics we need: the block's total execution time, its throughput in megagas/second, and the number of times each operation was executed. Each block is run multiple times on every client to account for variability in execution time. Runtimes and throughput are pulled from the Benchmarkoor API by benchmarkoor-fetch; the benchmarks ran on the amsterdam fork and runs are selected by the .*-full.* run-id pattern. The bottleneck analysis uses the test_mgas_s (megagas/second) metric recorded alongside the runtimes.

2. Bottleneck analysis (throughput)

The Bottleneck page measures each compute operation's worst-case throughput directly from the benchmarks, using the test_mgas_s (megagas/second) metric. Everything is "slowest binds":

The throughput ceiling is taken to be 100 Mgas/s, the rate a plain ETH transfer sustains — an assumption, not a measurement (a transfer benchmark actually clocks lower). An operation below it is a bottleneck: it already runs slower than a transfer, so it cannot be priced cheaper, and it is dropped from the Repricing view. In practice the genuine sub-ceiling ops are all state/IO (storage, calls, transfers), which are out of this dashboard's scope, so the compute set typically shows none.

Scope & coverage

This analysis covers the EVM's compute operations: arithmetic, bitwise, comparison, stack, control-flow, hashing (KECCAK256), memory, block/transaction and call context, and every precompile (including BLS12-381). The genuinely state- and IO-bound families — storage (SLOAD/SSTORE), account access, transient storage, CREATE, and BLOCKHASH — are deliberately excluded, as their runtime is dominated by state access rather than compute. The op set is the corresponding evm-gasfit presets, declared in fit.yaml.

Reproducibility

Re-run the parts of the pipeline this page depends on:

make fetch        # → data/raw/    (needs a Benchmarkoor token in secrets.json)
make bottlenecks  # → data/bottlenecks.csv   (worst-case Mgas/s per op)
make site         # renders this site into docs/

The committed data/ directory makes the published site self-contained: every figure and table on these pages traces back to those artifacts.