Benchmarks

Performance is a release gate, not a marketing page. Every selected report keeps the host, toolchain, and OXC identity, corpus hash, raw timing or RSS samples, sampling policy, distributions, and every assertion. Everything below is generated at build time from the reports listed in docs/acceptance/performance-report.json, so this page cannot silently pick up a newer failed or incomplete run.

How to read the results:

  • MiB/s is throughput: mebibytes of source processed per second. Higher is better.
  • p95 is the nearest-rank 95th percentile of the retained samples. It shows tail behavior, not just the average.
  • Ratios like 1.004× divide by the denominator named in that row.
  • One chart per gate. Every numeric release gate gets its own small chart with the gate's name on top and a one-line summary under it, including a plain "pass" or "FAIL" word.
  • The top strip shows the checked value as a diamond on an axis that starts at zero. The dashed vertical line is the frozen budget, named in the strip's left label, and the lightly shaded area is the failing side of that budget. The release fails if the diamond ever lands in the shaded area.
  • The bottom strip zooms in on the retained samples from the selected report, one dot per sample. Its axis is zoomed to the spread, so read its tick labels; it usually covers a much smaller range than the top strip. The solid vertical line is the median sample and the dotted vertical line is the p95 sample.
  • Ratio charts. The diamond in the top strip is the asserted ratio, which is the value the release gate checks. The bottom strip shows the raw samples of the two runs that ratio divides, on one shared milliseconds (or MiB) axis, each run with its own median tick. The two runs are sampled independently, so dividing sample pairs would invent data; only the asserted ratio is plotted against the budget.
  • Single-value charts. Some gates record exactly one number per report, like cold starts and editor memory. Those charts show only the top strip and say "single measurement per report".
  • Hover or focus any table row for the exact result, the budget, the sample count, the median, and the p95.

Three results need extra care:

  • The matched CLI lane gives ESLint, official Oxlint, and OXC for TSRX the same byte-identical 1,000-file TSX corpus, one rule, and identical run conditions. The separate mixed-file-types result only compares the product against itself on a different workload.
  • The native cold-start ratios compare a direct Rust executable with the official npm launcher, so they are diagnostic, not tool-speed claims.
  • The formatter's 16.6 MiB/s floor is a regression threshold derived from an older 1.66 MiB/s measurement on a different corpus, not a like-for-like Prettier comparison. The same-build canonical OXC controls are the comparable overhead measurements.

Noise is handled by a fail-closed rerun policy instead of picking a favorable sample:

  • Each invocation creates exactly one fresh report.
  • A first report inside the 3% near-threshold band requires exactly two additional fresh reports. Only the assertions that triggered get two-of-three tolerance; everything else must pass in all three.
  • Any failure more than 3% beyond its threshold is definitive.
  • The representative report is selected by median normalized budget pressure with a stable report-path tie-break, never by picking the fastest run. The aggregate fails if the selected representative is red.

Make the authoritative release decision with:

node tests/acceptance/run-performance.mjs

The individual commands below produce diagnostic raw reports without the aggregate admission, rerun, and selection policy:

cargo run --release --locked -p oxc_tsrx_benchmark -- \
  --assert benchmarks/native-lint/budgets.json
cargo run --release --locked -p oxc_tsrx_format_benchmark -- \
  --assert benchmarks/native-format/budgets.json
node benchmarks/vite/run.mjs
pnpm run benchmark:type-aware
pnpm run benchmark:editor
pnpm run benchmark:comparative

Matched 1,000-file CLI comparison

ESLint, official Oxlint, and OXC for TSRX lint the same byte-identical TSX files with one no-debugger rule, the same explicit file list, zero-diagnostic default output, 5 warmups, and 20 measured processes. Every lane runs through its npm CLI entry point. The ordinary oxlint-tsrx lane imports the exact declared official Oxlint launcher in the same Node process; only the separate mixed-file-types lane enters the native TSRX path. That mixed row is a paired internal workload ratio, not a cross-tool comparison. Report: benchmarks/comparative/results-1784321699288.json (2026-07-17), every budget passed.

BoundaryResultBudgetStatus
OXC for TSRX / official Oxlint (matched TSX lane)1.129 ×≤ 1.250 ×✓ pass
ESLint / OXC for TSRX (matched TSX lane)13.264 ×≥ 2 ×✓ pass
Paired mixed-file-types / all-TSX product workload1.489 ×≤ 1.500 ×✓ pass

Near-threshold adjudication. mixedNoBlowup entered the unchanged 3% band, so the aggregate required exactly 2 additional fresh identity-matched reports. Only triggering assertions receive two-of-three tolerance; every other assertion and invariant must pass in every report. The representative is selected by median normalized budget pressure with a stable report-path tie-break, never by choosing the fastest passing sample. Any failure more than 3% beyond its threshold, or a red selected representative, fails the aggregate. Retained reports: benchmarks/comparative/results-1784321699288.json, benchmarks/comparative/results-1784321719516.json, benchmarks/comparative/results-1784321739730.json.

Native lint

Frozen release gate: throughput, same-build ordinary-path overhead, cold start, memory, and batch invariants. The npm-launcher ratio is a diagnostic boundary, not a speed claim. Report: benchmarks/native-lint/results-1784321646022.json (2026-07-17), every budget passed.

BoundaryResultBudgetStatus
P01 median standard-path latency ratio1.003≤ 1.050✓ pass
P01 p95 standard-path latency ratio1.020≤ 1.080✓ pass
P01 diagnostic parity1exactly 1✓ pass
P01 direct standard bypass1exactly 1✓ pass
P02 median scan+copy+parse throughput260.28≥ 75✓ pass
P02 p95 scan+copy+parse throughput251.05≥ 60✓ pass
P02 equivalent-TSX throughput ratio0.563≥ 0.500✓ pass
P02 warm 10 KiB p95 scan+copy+parse latency0.041≤ 1✓ pass
P03 in-process one-thread lint throughput134.91≥ 35✓ pass
P03 CLI one-thread lint throughput80.241≥ 35✓ pass
P03 end-to-end CLI latency ratio1.141≤ 1.350✓ pass
P03 diagnostic parity1exactly 1✓ pass
P03 config compiled once1exactly 1✓ pass
P03 config one parse per file1exactly 1✓ pass
P03 configured rule applied1exactly 1✓ pass
P05 fresh-process TSRX p95 latency3.155≤ 50✓ pass
Direct Rust / official Oxlint npm-launcher p95 ratio0.056≤ 1.250✓ pass
P05 startup-rule diagnostic parity1exactly 1✓ pass
P07 TSRX peak RSS232980480≤ 252690432✓ pass

Native format

Frozen release gate: formatter throughput, convergence scaling, memory, and batch invariants. The historical 16.6 MiB/s value is an absolute cross-corpus-derived floor, not a speedup claim. Report: benchmarks/native-format/results-1784321655592.json (2026-07-17), every budget passed.

BoundaryResultBudgetStatus
p04 direct median ratio0.982≤ 1.050✓ pass
p04 direct p95 ratio1.003≤ 1.080✓ pass
p04 direct output parity1exactly 1✓ pass
p04 direct bypass1exactly 1✓ pass
p04 sequential median mib s134.78≥ 15✓ pass
p04 sequential p95 mib s127.00≥ 12✓ pass
Sequential throughput vs absolute 16.6 MiB/s floor134.78≥ 16.600✓ pass
p04 default thread mib s823.10≥ 100✓ pass
p04 generalized control median mib s21.790≥ 15✓ pass
p04 generalized control p95 mib s21.135≥ 12✓ pass
p04 generalized control linear scaling1.000≤ 1.350✓ pass
p04 generalized control idempotent1exactly 1✓ pass
p04 generalized control one parse1exactly 1✓ pass
p04 generalized dynamic style coverage1exactly 1✓ pass
p04 generalized style metadata1exactly 1✓ pass
p04 generalized no hidden embedded parse1exactly 1✓ pass
p04 idempotent1exactly 1✓ pass
p04 one parse1exactly 1✓ pass
p04 config compiled once1exactly 1✓ pass
p04 config one parse per file1exactly 1✓ pass
p04 config options applied1exactly 1✓ pass
p05 stdin p95 ms3.156≤ 110✓ pass
Direct Rust / official Oxfmt npm-launcher p95 ratio0.036≤ 1.250✓ pass
p05 complete output1exactly 1✓ pass
p07 rss ratio1.143≤ 1.150✓ pass

Near-threshold adjudication. p07_rss_ratio entered the unchanged 3% band, so the aggregate required exactly 2 additional fresh identity-matched reports. Only triggering assertions receive two-of-three tolerance; every other assertion and invariant must pass in every report. The representative is selected by median normalized budget pressure with a stable report-path tie-break, never by choosing the fastest passing sample. Any failure more than 3% beyond its threshold, or a red selected representative, fails the aggregate. Retained reports: benchmarks/native-format/results-1784321650912.json, benchmarks/native-format/results-1784321655592.json, benchmarks/native-format/results-1784321660260.json.

Opt-in type-aware lint

The opt-in TypeScript-Go lane. The default lane stays syntax-only with zero type processes. Report: benchmarks/type-aware/results-1784321661795.json (2026-07-17), every budget passed.

BoundaryResultBudgetStatus
Default syntax lint p952.646 ms≤ 10 ms✓ pass
Single-file type-aware p9524.777 ms≤ 60 ms✓ pass
Two-file project type-aware p9524.040 ms≤ 70 ms✓ pass
Single-file type-aware cold start60.611 ms≤ 100 ms✓ pass
Two-file project cold start26.455 ms≤ 120 ms✓ pass
Type-aware vs default p95 ratio9.363 ×≤ 12 ×✓ pass
Type processes per batch1exactly 1✓ pass
Default path parse count per file1exactly 1✓ pass

Vite/Vite+ command boundary

Fresh companion processes at the ecosystem seam. Vite build and HMR carry zero OXC for TSRX transforms. Report: benchmarks/vite/results-1784321678410.json (2026-07-17), every budget passed.

BoundaryResultBudgetStatus
Mixed companion lint p9557.915 ms≤ 150 ms✓ pass
Mixed lint vs canonical p95 ratio1.813 ×≤ 2.500 ×✓ pass
Mixed companion format-check p95127.11 ms≤ 220 ms✓ pass
Mixed format vs canonical p95 ratio1.234 ×≤ 2 ×✓ pass
Ordinary npm formatter p95113.44 ms≤ 150 ms✓ pass
Ordinary npm formatter vs canonical p95 ratio1.101 ×≤ 1.250 ×✓ pass
Vite+ 0.2.4 mixed lint p95237.08 ms≤ 750 ms✓ pass
Native TSRX parses per file1exactly 1✓ pass

Native editor server

Syntax-only local language-server round trips on the retained Markless fixture. Report: benchmarks/editor/results-1784321679056.json (2026-07-17), every budget passed.

BoundaryResultBudgetStatus
Server start to first diagnostics2.591 ms≤ 50 ms✓ pass
Edit-to-diagnostics p950.115 ms≤ 25 ms✓ pass
Formatting p950.125 ms≤ 15 ms✓ pass
Safe code-action p950.114 ms≤ 25 ms✓ pass
RSS after 1,000-edit soak10.984 MiB≤ 96 MiB✓ pass
RSS growth through soak0 MiB≤ 8 MiB✓ pass

Measurement hygiene#

  • Harnesses are release-only.
  • memory-stats is linked only into benchmark executables, never the distributed CLI.
  • Normal source metadata excludes configuration time; aggregate metadata and dedicated configuration lanes report it separately.
  • Formatter reports keep scan, projection, canonical parse, canonical format, and checked-lift timing arrays separately.
  • Thresholds never change during adjudication.