Benchmarking — contributor guide¶
This page is for contributors who want to add a new benchmark or re-run an existing one without re-deriving the methodology from scratch.
For the published numbers themselves, see docs/benchmarks/. For
interpretation calls (why each comparator was chosen, what's missing),
see BENCHMARKS_V0_6_NOTES.md at the repo root.
Layout¶
crates/mty-bench/
├── Cargo.toml # the bench crate
├── src/
│ ├── lib.rs # shared fixtures + http helpers
│ ├── fixtures.rs # synth_source, echo_sir_program
│ ├── http.rs # single_get / sequential_get
│ ├── metrics.rs # percentiles / mean
│ └── bin/
│ └── mty-bench-runner.rs # CLI driver (criterion-less)
├── benches/
│ ├── parse_throughput.rs # criterion harness
│ ├── agent_send_latency.rs
│ ├── mailbox_throughput.rs
│ ├── http_server_throughput.rs
│ ├── compile_to_native.rs
│ └── wasm_size.rs
└── tests/
├── fixture_load.rs # smoke: 10 KLOC parses cleanly
└── criterion_smoke.rs # smoke: each bench runs ≥1 iter
benches/ # cross-language comparators
├── parse_throughput/{mighty,rust,go,cpp}/
├── agent_send_latency/{...}/
├── mailbox_throughput/{...}/
├── http_server_throughput/{...}/
├── compile_to_native/ # generator script + READMEs
├── wasm_size/ # README only
└── run.sh # toolchain-aware runner
What goes where¶
| Type of impl | Location |
|---|---|
| Pure-Mighty benchmark | crates/mty-bench/benches/<name>.rs |
| Shared fixture / helper | crates/mty-bench/src/<name>.rs |
| Cross-language comparator | benches/<category>/<lang>/ |
| CI-friendly script | benches/run.sh |
If you only need a tight microbenchmark of one crate's internals,
you can also put benches/*.rs inside that crate (e.g.
crates/mty-runtime/benches/). Use the top-level benches/ only
for cross-language comparative benchmarks; per-crate benches are
fine for in-language tuning.
Adding a new category¶
- Add a shared fixture in
crates/mty-bench/src/fixtures.rsif you need new test data. - Add the criterion bench at
crates/mty-bench/benches/<name>.rswithharness = falseinCargo.toml. UseBenchmarkId::newto keep the report structure consistent. - Add the runner integration in
crates/mty-bench/src/bin/mty-bench-runner.rsby extending theCategoryenum + adding arun_<name>(iters)function. - Add cross-language comparators in
benches/<name>/<lang>/— at minimum a Rust comparator so the on-host number has a peer. Use the same source shape (same struct/fn count, same arithmetic) so the comparison is meaningful. - Add the doc at
docs/benchmarks/<name>.mdfollowing the template (overview → numbers → interpretation → v0.7+ targets). - Update
docs/benchmarks/index.mdto list the new category.
Running locally¶
# Full criterion suite (HTML report at target/criterion/report/index.html):
cargo bench -p mty-bench
# Single category:
cargo bench -p mty-bench --bench parse_throughput
# CLI runner (faster, no HTML):
cargo build --release -p mty-bench
./target/release/mty-bench-runner --category parse-throughput --iters 30
./target/release/mty-bench-runner --all --iters 30 --out target/bench.json
# Cross-language (auto-detects toolchains):
./benches/run.sh
What statistics matter¶
For a publication-quality number, report median / p95 / p99. Mean
is misleading on skewed distributions — tokio scheduler jitter alone
can pull the mean by 2-5x relative to the median.
For relative comparisons across languages, prefer median ratios ("Mighty is 1.4x slower than Rust at median") over mean ratios which are noisy.
For throughput (msgs/sec, bytes/sec), divide by the median latency rather than the mean. This corresponds to "the rate you'd see on a typical request" rather than "the rate amortised across worst-case spikes".
Honesty rules¶
- Don't cherry-pick the best run. Run 20-30 iterations and report the median.
- Don't omit losing benchmarks. If Mighty is 5x slower than Rust on a category, the doc says so + flags a v0.7+ issue.
- Label numbers by environment. Use "(This host)" vs "(Reference env)" — never let a reader mistake a reference-env number for an on-host measurement.
CI¶
.github/workflows/bench.yml runs the lightweight criterion suite
on every push to main. It does not run the cross-language
comparators (the CI runner usually lacks Go/C++ toolchains). PR
comment posting + historical trend tracking are stub TODOs.
Reproducibility checklist¶
- Fixture is deterministic (seeded, same output on rerun).
- Comparator runs the same shape of operation.
- Sample count documented in
methodology.md. - Environment recorded ("This host" vs "Reference env").
- Each category page links back to the comparator code path.