Skip to content

Add Vitest bench adapter#889

Open
epompeii wants to merge 1 commit into
develfrom
u/ep/js-vitest-adapter
Open

Add Vitest bench adapter#889
epompeii wants to merge 1 commit into
develfrom
u/ep/js-vitest-adapter

Conversation

@epompeii

@epompeii epompeii commented Jun 6, 2026

Copy link
Copy Markdown
Member

Closes #215.

Adds a js_vitest benchmark adapter that parses the JSON produced by vitest bench --outputJson <file> (verified against Vitest v3.0.5 + tinybench v2.9.0).

Measures

Each benchmark reports both built-in measures:

  • Latency (ns): mean by default, or median via --average. For the mean, lower_value/upper_value are one standard deviation around the value. The median has no bounds, since Vitest provides no interquartile range.
  • Throughput (ops/sec): hz, with lower_value/upper_value derived from the relative margin of error (rme), matching the existing js_benchmark adapter.

Benchmark names

Names join the suite fullName and the benchmark name with Vitest's own > separator (e.g. math > fibonacci > fib(10)), falling back to the leaf name when the suite name is empty or the combined name would exceed the length limit. The absolute filepath is excluded since it is not portable across CI machines.

Usage

bencher run --adapter js_vitest --file results.json "vitest bench --run --outputJson results.json"

Scope

  • New adapter AdapterJsVitest plus a new_measures constructor for multi-measure results; wired into the JS chain, the dispatch table, and magic auto-detection.
  • Adapter::JsVitest enum variant (with Display and the SQL impls), CLI --adapter js_vitest, and regenerated openapi.json + bencher.ts.
  • Console UI: adapter name/command/icon/validation, the benchmark-harness pickers, and the landing page.
  • Docs: a new js-vitest chunk, a magic list entry, and the adapters page render across all nine languages. The non-English chunks currently carry the English copy as a placeholder for later translation.

Tests

  • New unit tests cover the mean, the median (value only, no bounds), the JS language chain, and magic auto-detection.
  • cargo nextest, cargo clippy --no-deps --all-targets --all-features -- -Dwarnings, cargo test --doc, and cargo check --no-default-features all pass; biome is clean; a full astro build renders the Vitest docs in every language.

@epompeii epompeii self-assigned this Jun 6, 2026
@epompeii epompeii added the claude label Jun 6, 2026
@github-actions

github-actions Bot commented Jun 6, 2026

Copy link
Copy Markdown
Contributor

🤖 Claude Code Review

PR: #889
Base: devel
Head: u/ep/js-vitest-adapter
Commit: f84b2d3b6141f6fa6c36df8756cf9410c6830b5a


I have a thorough understanding of the changes. Here's my review.

PR Review: Add Vitest bench adapter

Overall this is a high-quality, well-tested, and well-documented change. It faithfully follows existing conventions (closely modeled on js/benchmark.rs and c_sharp/dot_net.rs), wires the new JsVitest variant through every required layer (enum + ToSql/FromSql, CLI parser/mapping, generated OpenAPI + TS types, console UI, and docs in all locales), and the test fixtures are carefully constructed so the math is verifiable by inspection.

Strengths

  • Complete plumbing. The new adapter is threaded through all the right places: Adapter enum with a fresh int (73), Display, Diesel to_sql/try_from, the to_base() mapping, AdapterJs/AdapterMagic fallback chains, CLI CliReportAdapter + From impl, gen-types output (openapi.json, bencher.ts), console (adapter.ts, name.ts, ViewCard.tsx, BencherRun.astro, harness lists), and changelog. I checked each mapping match and none are missing an arm (they'd fail to compile otherwise given the exhaustive matches).
  • Good tests. Mean/median/explicit-mean paths are covered, plus magic-adapter and combined-AdapterJs routing. The two/four fixtures encode clean numbers (sd/mean = 25% = rme) so bounds are easy to validate, and the median case correctly asserts no spread.
  • Strong typing & destructuring. Benchmark is fully destructured (so a new field forces a compile error), uses the validated BenchmarkName type, and the new AdapterResults::new_measures is a clean generalization of new for multi-measure benchmarks. The filepath-ignored rationale is documented well.
  • Docs. Clear explanation of latency mean/median semantics and throughput RME bounds; the --file requirement and --run flag are correctly surfaced.

Issues / discussion points

  1. A single invalid benchmark name discards the entire report (medium). Benchmark.name is typed BenchmarkName, so if any one benchmark's name fails validation (empty, or exceeds MAX_LEN), serde_json::from_str::<Vitest> fails for the whole input. Under js_vitest that silently yields zero results; under magic it silently falls through. Most other adapters parse the name as a raw string and validate per-benchmark, degrading more gracefully. Worth a deliberate decision; at minimum it's a sharp edge worth a test.

  2. combine_name MAX_LEN fallback can silently collide (low). When "{full_name} > {name}" exceeds BenchmarkName::MAX_LEN, it falls back to the bare leaf name. Two benchmarks sharing a leaf name in different groups/files would then map to the same BenchmarkName and the second silently overwrites the first in the results HashMap (new_measures uses .entry(...) then insert). Rare, but truncation/hashing would be safer than a lossy fallback.

  3. Negative lower bounds possible (low, pre-existing pattern). For mean latency, value - spread (sd) and for throughput value - error (RME) can go negative when variance/RME is large. This mirrors c_sharp/dot_net.rs:105 and js/benchmark.rs:81, so it's consistent with the codebase rather than a new defect, but flagging in case clamping at zero is desired project-wide.

  4. Throughput reported even under --average median (intentional?). Latency switches on the average setting but throughput is always emitted from hz/rme. This is documented in the mdx, so likely intended (hz has no median analog), just calling it out.

Compliance with CLAUDE.md

  • No emdashes; comments use the project's punctuation style. ✅
  • thiserror/error conventions: N/A (parse returns Option, matching sibling adapters). ✅
  • Strong types, destructuring-on-consume, parser module separation all honored. ✅
  • Generated artifacts (openapi.json, bencher.ts) regenerated and contain js_vitest. ✅

One verification gap: I couldn't run cargo nextest / clippy (sandbox blocked the cargo invocations), so please confirm cargo nextest run -p bencher_adapter, cargo test --doc, and cargo clippy --all-features are green locally before merge.

Net: solid, mergeable work. I'd consider addressing #1 (graceful per-benchmark name handling) before merge; #2#4 are optional follow-ups.


Model: claude-opus-4-8

@github-actions

github-actions Bot commented Jun 6, 2026

Copy link
Copy Markdown
Contributor

🐰 Bencher Report

Branchu/ep/js-vitest-adapter
Testbedintel-v1
Click to view all benchmark results
BenchmarkLatencyBenchmark Result
microseconds (µs)
(Result Δ%)
Upper Boundary
microseconds (µs)
(Limit %)
Adapter::Json📈 view plot
🚷 view threshold
4.68 µs
(+2.15%)Baseline: 4.59 µs
4.82 µs
(97.12%)
Adapter::Magic (JSON)📈 view plot
🚷 view threshold
4.55 µs
(+1.97%)Baseline: 4.47 µs
4.68 µs
(97.37%)
Adapter::Magic (Rust)📈 view plot
🚷 view threshold
25.96 µs
(+2.03%)Baseline: 25.45 µs
26.42 µs
(98.27%)
Adapter::Rust📈 view plot
🚷 view threshold
3.53 µs
(+1.82%)Baseline: 3.47 µs
3.59 µs
(98.48%)
Adapter::RustBench📈 view plot
🚷 view threshold
3.53 µs
(+1.78%)Baseline: 3.47 µs
3.58 µs
(98.62%)
🐰 View full continuous benchmarking report in Bencher

@epompeii epompeii force-pushed the u/ep/js-vitest-adapter branch from ee35821 to 581178d Compare June 6, 2026 04:50
@epompeii epompeii force-pushed the u/ep/js-vitest-adapter branch from 581178d to 753065c Compare June 15, 2026 06:11
Add a `js_vitest` benchmark adapter that parses `vitest bench --outputJson` output. Each benchmark reports both a `latency` measure (mean by default, or median via `--average`) and a `throughput` measure (operations per second). For the mean, the latency bounds come from the standard deviation; the median has no bounds because Vitest does not provide an interquartile range. The throughput bounds come from the relative margin of error. The benchmark name joins the suite `fullName` and the benchmark `name`.

Wire `js_vitest` through the `Adapter` enum, the CLI, magic auto-detection, the console UI, and the adapters documentation in all nine languages.
@epompeii epompeii force-pushed the u/ep/js-vitest-adapter branch from 753065c to f84b2d3 Compare June 16, 2026 04:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant