Skip to content

bench: add VM-level mega-evm vs revm benchmarks#330

Open
RealiCZ wants to merge 5 commits into
mainfrom
cz/feat/bench-coverage-vs-revm
Open

bench: add VM-level mega-evm vs revm benchmarks#330
RealiCZ wants to merge 5 commits into
mainfrom
cz/feat/bench-coverage-vs-revm

Conversation

@RealiCZ

@RealiCZ RealiCZ commented Jun 30, 2026

Copy link
Copy Markdown
Collaborator

Summary

Adds VM-level benchmarks that measure mega-evm's overhead over vanilla revm in areas the existing suite did not cover. All changes are additive: the existing subjects and prior bench numbers are unchanged.

What this adds

  • SALT dynamic-gas isolation — for SSTORE and CREATE workloads, three rows per spec: revm_pinned (floor), mega over EmptyExternalEnv (the SALT bucket path short-circuits to a constant), and mega over a crowded TestExternalEnvs (real FNV-hash + map-lookup + multiply per touched bucket). The active − baseline gap is the SALT bucket-multiplier path cost, which no prior bench exercised. LOG is intentionally excluded — its storage gas uses a fixed 10× multiplier unrelated to SALT buckets.
  • REX5 comparison rows — REX5 is added to the shared spec list (so transact / revm_bench / mega_bench all gain a rex5 vs revm row) and the three block-executor benches now run at both REX4 and REX5.
  • Precompile vs revm baselines — every precompile group in comp_cost gains a vanilla-revm baseline row (revm at PRAGUE, which has BLS12-381 and predates the EIP-7825 tx-gas cap), so each precompile shows a mega-vs-revm gap. The revm row is assert-guarded, so a precompile that does not actually execute fails loudly.
  • Oracle real-data bench — drives the oracle get_oracle_storage path with populated storage. The gap is the oracle SLOAD hit-vs-miss structural cost (hit early-returns; miss falls through to the journal SLOAD), not an isolated lookup — the path forks structurally so the lookup cannot be isolated further.
  • Test-utils enablers — a test-utils-gated MegaContext constructor over a configurable external env (with a unit test), a TestExternalEnvs uniform-bucket-capacity setter, a MegaWithEnv subject, and the shared env-isolation registration helpers.

Scope

VM-level only. Comparing against other clients (geth / reth / nethermind / erigon / besu / nimbus) and full-node load testing require the complete MegaETH node and are out of scope here. The comparison page (per-commit trigger, time-series storage, regression alerting) and its MGas/s data source are a follow-up — the per-row gas signal that was initially included here is deferred to that work, where the output format can be pinned to a real consumer.

Testing

  • All affected bench targets smoke-pass (cargo bench -p mega-evm --bench <target> -- --test): mega_bench, comp_cost, block_bench, transact.
  • Lib unit tests pass, including the new new_with_ext_envs constructor coverage test.
  • cargo fmt --all --check and cargo clippy --workspace --benches --all-features --locked are clean.

RealiCZ added 5 commits June 30, 2026 15:58
…les, oracle)

Add four VM-level criterion benchmarks isolating mega-evm's overhead over vanilla revm where it was previously unmeasured:

- SALT dynamic-gas isolation (sstore/create): revm_pinned floor, rex5 over EmptyExternalEnv (SALT short-circuits to a constant), rex5_salt over a crowded TestExternalEnvs; the rex5_salt-rex5 gap is the SALT bucket-multiplier path cost.
- REX5 rows added to the default comparison workloads (SPEC_IDS) and the three block-executor benches (now run at REX4 and REX5).
- Vanilla-revm baseline (PRAGUE) added to all precompile groups in comp_cost so each precompile shows a mega-vs-revm gap.
- Oracle real-data bench measuring the oracle SLOAD hit-vs-miss path.

Supporting test-utils-gated additions: MegaContext::new_with_ext_envs, TestExternalEnvs::with_default_bucket_capacity, the MegaWithEnv subject, and the register_env_isolation helpers. Existing Mega/EmptyExternalEnv rows and all prior bench numbers are unchanged.
Each Subject::run now returns the total gas_used over the workload (threaded
through run_workload), and run_subjects prints one 'gas\t<row>\t<gas_used>' line
per row so a downstream page can derive MGas/s = gas / median-ns.

The gas run lives inside the bench_function closure, so it executes only for rows
Criterion's name/--test filter selects -- never in the registration path (which
would run unfiltered work and could fail on a skipped row). Criterion invokes that
closure many times (per warmup batch and per sample), so a Cell guard emits the
gas line exactly once per row. Criterion Throughput is not used: it must be set
before bench_function, and the bencher text output the CI parses carries no
throughput field. Covers the shared register_* path (transact, revm_bench,
mega_bench, and the SALT/oracle isolation benches); comp_cost already prints gas
and the block-executor benches are out of scope.
The test/bench-only constructor was exercised only by benches (not counted by
coverage), leaving its 8 lines uncovered. Add a unit test that builds a
MegaContext over a TestExternalEnvs via new_with_ext_envs and checks the spec
and that the supplied SALT env is wired through the dynamic-gas cache.
Removes the gas-per-row signal added for a future comparison page. With no
consumer yet, its output format is undefined (group key, units, comp_cost revm
row), so it is deferred to the page work where the format will be pinned down.
The benchmark coverage itself is unaffected; Subject::run returns to (), and
run_subjects no longer prints gas lines.
@github-actions

Copy link
Copy Markdown

🧬 Mutation testing — ✅ PASS

Nothing to test — no mutants were generated on the changed lines.

@RealiCZ RealiCZ added comp:core Changes to the `mega-evm` core crate spec:unchanged No change to any `mega-evm`'s behavior rust Pull requests that update rust code api:compatible Only new interface or API is introduced. Existing software is compatible. labels Jun 30, 2026
@github-actions

Copy link
Copy Markdown

🧬 Mutation testing — ✅ PASS

Nothing to test — no mutants were generated (1 unviable, 0 timed out).

@claude claude Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Clean

  • Reviewed VM-level bench additions: SALT dynamic-gas isolation, REX5 rows, precompile vs revm baselines, oracle real-data bench, and the MegaWithEnv + new_with_ext_envs + with_default_bucket_capacity enablers.
  • Production code change is limited to a #[cfg(any(test, feature = "test-utils"))] thin wrapper around the existing new_with_shared_ext_envs, and the TestExternalEnvs::default_bucket_capacity field is additive (None preserves prior behavior). Both are covered by new unit tests.
  • Bench wiring is internally consistent: SPEC_IDS gains rex5; register_env_isolation / register_env_isolation_mega_only correctly avoid duplicate criterion IDs; bench_precompile_group keeps the revm row symmetric with the mega rows via black_box(r) and an is_success assert, with bytecode-level assert_stack_value(0, 1) already guarding precompile execution.
  • No new actionable findings. No prior automated review threads to recap.

@flyq flyq left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

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

Labels

api:compatible Only new interface or API is introduced. Existing software is compatible. comp:core Changes to the `mega-evm` core crate rust Pull requests that update rust code spec:unchanged No change to any `mega-evm`'s behavior

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants