From eb6ab5f5fcb07e9249ec96cbd470867bcb44afa3 Mon Sep 17 00:00:00 2001 From: Ryan Atkinson Date: Fri, 26 Jun 2026 13:59:10 -0400 Subject: [PATCH 001/218] chore: update benchmarks for v0.2 --- CLAUDE.md | 4 +- package-lock.json | 40 +- package.json | 23 +- src/routes/docs/benchmarks/+page.svelte | 39 +- .../benchmarks/BenchmarksCrossRuntime.svelte | 105 ++ .../docs/benchmarks/BenchmarksSizes.svelte | 12 +- src/routes/docs/benchmarks/benchmark_data.ts | 109 +- src/routes/docs/benchmarks/benchmarks.json | 1035 +++++++++-------- .../benchmarks/benchmarks_cross_runtime.json | 628 ++++++++++ .../benchmarks/benchmarks_cross_runtime.ts | 5 + src/routes/docs/introduction/+page.svelte | 7 +- src/routes/docs/playground/+page.svelte | 3 +- src/test/benchmark_data.test.ts | 38 +- tsconfig.json | 4 +- 14 files changed, 1485 insertions(+), 567 deletions(-) create mode 100644 src/routes/docs/benchmarks/BenchmarksCrossRuntime.svelte create mode 100644 src/routes/docs/benchmarks/benchmarks_cross_runtime.json create mode 100644 src/routes/docs/benchmarks/benchmarks_cross_runtime.ts diff --git a/CLAUDE.md b/CLAUDE.md index bc31ca9..789c65b 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -28,7 +28,7 @@ IMPORTANT for AI agents: Do NOT run `gro dev` - the developer will manage the de - fuz_util (`@fuzdev/fuz_util`) - utility functions - fuz_code (`@fuzdev/fuz_code`) - syntax highlighting - Gro (`@fuzdev/gro`) - build system and task runner -- prettier + prettier-plugin-svelte - code formatting +- tsv (via Gro) - code formatting - mdz (`@fuzdev/mdz`) - markdown preprocessor wired into `svelte.config.js` - `@fuzdev/tsv_wasm` - tsv's formatter + parser as WASM; powers the playground, loaded lazily in the browser @@ -117,7 +117,7 @@ Deploys to `https://tsv.fuz.dev/` via `gro deploy` (builds and pushes to deploy - TypeScript strict mode - Svelte 5 with runes API -- Prettier with tabs, 100 char width +- tsv with tabs, 100 char width - Node >= 24.14 - Private package (not published to npm) diff --git a/package-lock.json b/package-lock.json index 2d3b1cb..d930d2f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,7 +14,7 @@ "@fuzdev/fuz_css": "^0.63.2", "@fuzdev/fuz_ui": "^0.205.1", "@fuzdev/fuz_util": "^0.65.2", - "@fuzdev/gro": "^0.205.1", + "@fuzdev/gro": "^0.206.0", "@fuzdev/mdz": "^0.1.0", "@fuzdev/tsv_wasm": "^0.1.0", "@ryanatkn/eslint-config": "^0.12.1", @@ -29,8 +29,6 @@ "eslint-plugin-svelte": "^3.13.1", "esm-env": "^1.2.2", "magic-string": "^0.30.21", - "prettier": "^3.7.4", - "prettier-plugin-svelte": "^3.4.1", "svelte": "^5.56.0", "svelte-check": "^4.3.6", "svelte-docinfo": "^0.5.3", @@ -887,18 +885,17 @@ } }, "node_modules/@fuzdev/gro": { - "version": "0.205.1", - "resolved": "https://registry.npmjs.org/@fuzdev/gro/-/gro-0.205.1.tgz", - "integrity": "sha512-o5WBXWSH/UlN1BsDnpBNIi0WHR7lj7UFGltH/JctSP7oSB2ojvmoXD5OLCEeVdRVcDaSQKl48xcXKUwHKqVSmQ==", + "version": "0.206.0", + "resolved": "https://registry.npmjs.org/@fuzdev/gro/-/gro-0.206.0.tgz", + "integrity": "sha512-11nkTAEWDOvkgzynRChQS+bj3tc7R0NduB+eHLXzXZJqz66nc/oop8Ttvz0UkjTBPX/zzgtU8QuDDNyA7buf5A==", "dev": true, "license": "MIT", "dependencies": { + "@fuzdev/tsv_wasm": "^0.1.0", "chokidar": "^5.0.0", "dotenv": "^17.2.3", "esm-env": "^1.2.2", "oxc-parser": "^0.99.0", - "prettier": "^3.7.4", - "prettier-plugin-svelte": "^3.5.1", "ts-blank-space": "^0.6.2", "tslib": "^2.8.1" }, @@ -3625,33 +3622,6 @@ "node": ">= 0.8.0" } }, - "node_modules/prettier": { - "version": "3.7.4", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.7.4.tgz", - "integrity": "sha512-v6UNi1+3hSlVvv8fSaoUbggEM5VErKmmpGA7Pl3HF8V6uKY7rvClBOJlH6yNwQtfTueNkGVpOv/mtWL9L4bgRA==", - "dev": true, - "license": "MIT", - "bin": { - "prettier": "bin/prettier.cjs" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/prettier/prettier?sponsor=1" - } - }, - "node_modules/prettier-plugin-svelte": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/prettier-plugin-svelte/-/prettier-plugin-svelte-3.5.1.tgz", - "integrity": "sha512-65+fr5+cgIKWKiqM1Doum4uX6bY8iFCdztvvp2RcF+AJoieaw9kJOFMNcJo/bkmKYsxFaM9OsVZK/gWauG/5mg==", - "dev": true, - "license": "MIT", - "peerDependencies": { - "prettier": "^3.0.0", - "svelte": "^3.2.0 || ^4.0.0-next.0 || ^5.0.0-next.0" - } - }, "node_modules/punycode": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", diff --git a/package.json b/package.json index e90a884..f0f071e 100644 --- a/package.json +++ b/package.json @@ -16,7 +16,7 @@ "test": "gro test", "preview": "vite preview", "deploy": "gro deploy", - "update-benchmarks": "cp ../tsv/benches/deno/results/report.json src/routes/docs/benchmarks/benchmarks.json" + "update-benchmarks": "cp ../tsv/benches/js/results/report.node.json src/routes/docs/benchmarks/benchmarks.json && cp ../tsv/benches/js/results/report.json src/routes/docs/benchmarks/benchmarks_cross_runtime.json && gro format" }, "type": "module", "engines": { @@ -28,7 +28,7 @@ "@fuzdev/fuz_css": "^0.63.2", "@fuzdev/fuz_ui": "^0.205.1", "@fuzdev/fuz_util": "^0.65.2", - "@fuzdev/gro": "^0.205.1", + "@fuzdev/gro": "^0.206.0", "@fuzdev/mdz": "^0.1.0", "@fuzdev/tsv_wasm": "^0.1.0", "@ryanatkn/eslint-config": "^0.12.1", @@ -43,8 +43,6 @@ "eslint-plugin-svelte": "^3.13.1", "esm-env": "^1.2.2", "magic-string": "^0.30.21", - "prettier": "^3.7.4", - "prettier-plugin-svelte": "^3.4.1", "svelte": "^5.56.0", "svelte-check": "^4.3.6", "svelte-docinfo": "^0.5.3", @@ -57,23 +55,6 @@ "zimmerframe": "^1.1.4", "zod": "^4.3.6" }, - "prettier": { - "plugins": [ - "prettier-plugin-svelte" - ], - "useTabs": true, - "printWidth": 100, - "singleQuote": true, - "bracketSpacing": false, - "overrides": [ - { - "files": "package.json", - "options": { - "useTabs": false - } - } - ] - }, "sideEffects": [ "**/*.css" ], diff --git a/src/routes/docs/benchmarks/+page.svelte b/src/routes/docs/benchmarks/+page.svelte index 052f018..0e00105 100644 --- a/src/routes/docs/benchmarks/+page.svelte +++ b/src/routes/docs/benchmarks/+page.svelte @@ -5,6 +5,7 @@ import {tome_get_by_slug} from '@fuzdev/fuz_ui/tome.ts'; import {benchmarks_json} from './benchmarks.ts'; + import {benchmarks_cross_runtime_json} from './benchmarks_cross_runtime.ts'; import { category_color, derive_benchmark_groups, @@ -14,6 +15,7 @@ import BenchmarksGroup from './BenchmarksGroup.svelte'; import BenchmarksSizes from './BenchmarksSizes.svelte'; import BenchmarksMeta from './BenchmarksMeta.svelte'; + import BenchmarksCrossRuntime from './BenchmarksCrossRuntime.svelte'; const LIBRARY_ITEM_NAME = 'benchmarks'; @@ -40,11 +42,13 @@
tsv native tsv native json tsv native + json tsv wasm tsv wasm json tsv wasm + json biome oxc @@ -73,8 +77,8 @@
  • oxfmt has no wasm build as of June 2026
  • - tsv doesn't publish native artifacts yet, but it builds them for benchmarking over FFI - with Deno + tsv doesn't publish native artifacts yet, but it builds them for benchmarking - an N-API + addon for Node and Bun, and a C-FFI library for Deno
  • @@ -166,6 +170,33 @@

    + + + +

    + The same benchmark harness runs under three JS runtimes - Node, Deno, and Bun. The headline + numbers above are the Node run. The native row differs by runtime: Node and Bun load tsv's + N-API addon, while Deno loads its C-FFI library. They share code but have a different binding + boundary. A per-runtime delta on the same implementation is a runtime or binding-boundary + effect, not an engine difference. +

    + + +
    diff --git a/src/routes/docs/benchmarks/BenchmarksSizes.svelte b/src/routes/docs/benchmarks/BenchmarksSizes.svelte index ad9df5f..610c93b 100644 --- a/src/routes/docs/benchmarks/BenchmarksSizes.svelte +++ b/src/routes/docs/benchmarks/BenchmarksSizes.svelte @@ -21,13 +21,13 @@ const sorted = items.toSorted((a, b) => a.bytes - b.bytes); const max = Math.max(0, ...items.map((s) => s.bytes)); // anchor "vs tsv" ratios on the headline build per kind - `tsv_wasm` (the - // flagship full build the bench executes) for wasm, `tsv (native)` for native — - // matching the report.md table; `tsv_format_wasm` covers reports generated - // before shape v2 added the third build, then any tsv-prefixed label. - // Without this the wasm group anchors on whatever sorts largest and every - // ratio disagrees with the report. + // flagship full build the bench executes) for wasm, `tsv (napi)` for native + // (the N-API addon, the flagship's native path) — matching the node report's + // own anchor; `tsv_format_wasm` covers reports generated before shape v2 added + // the third build, then any tsv-prefixed label. Without this the wasm group + // anchors on whatever sorts largest and every ratio disagrees with the report. const tsv = - sorted.find((s) => s.label === 'tsv_wasm' || s.label === 'tsv (native)') ?? + sorted.find((s) => s.label === 'tsv_wasm' || s.label === 'tsv (napi)') ?? sorted.find((s) => s.label === 'tsv_format_wasm') ?? sorted.find((s) => s.label.startsWith('tsv')); return sorted.map((s) => ({ diff --git a/src/routes/docs/benchmarks/benchmark_data.ts b/src/routes/docs/benchmarks/benchmark_data.ts index 9bf0958..5569939 100644 --- a/src/routes/docs/benchmarks/benchmark_data.ts +++ b/src/routes/docs/benchmarks/benchmark_data.ts @@ -115,7 +115,8 @@ const CATEGORY_BY_NAME: Record = { oxfmt: 'oxc', }; -const categorize_name = (name: string): ImplementationCategory => CATEGORY_BY_NAME[name] ?? 'oxc'; +export const categorize_name = (name: string): ImplementationCategory => + CATEGORY_BY_NAME[name] ?? 'oxc'; export const categorize_size = (label: string): ImplementationCategory => { // covers `tsv_wasm` plus the `tsv_format_wasm`/`tsv_parse_wasm` subsets @@ -236,6 +237,96 @@ export const derive_speedup_summary = (groups: Array): Array>; + mean_ns: Partial>; + files_iterated: Partial>; +} + +export interface CrossRuntimeReport { + version: number; + kind: 'combined'; + generated: string; + runtimes: Array; + sources: Array<{ + runtime: BenchmarkRuntime; + timestamp: string; + git_commit: string | null; + tsv: string | null; + }>; + rows: Array; +} + +export interface CrossRuntimeDisplayRow { + name: string; + category: ImplementationCategory; + ops_per_second: Partial>; + // ratio of each runtime vs the base (first present) runtime; `> 1` = faster + ratio_vs_base: Partial>; +} + +export interface CrossRuntimeGroup { + group: string; + operation: string; + language: string; + rows: Array; +} + +const CROSS_RUNTIME_LANG_ORDER: Record = {svelte: 0, typescript: 1, css: 2}; +const CROSS_RUNTIME_OP_ORDER: Record = {format: 0, parse: 1}; + +/** + * Groups the combined report's rows by benchmark group, in the same display + * order as `derive_benchmark_groups` (format before parse, then svelte / + * typescript / css). The ratio base is the first runtime in `report.runtimes` + * (deno in a full run), matching the bench's `report.md`. + */ +export const derive_cross_runtime_groups = ( + report: CrossRuntimeReport, +): Array => { + const base = report.runtimes[0]; + const grouped: Map> = new Map(); + for (const row of report.rows) { + let rows = grouped.get(row.group); + if (!rows) { + rows = []; + grouped.set(row.group, rows); + } + const base_ops = base ? row.ops_per_second[base] : undefined; + const ratio_vs_base: Partial> = {}; + for (const runtime of report.runtimes) { + const ops = row.ops_per_second[runtime]; + if (ops != null && base_ops != null && base_ops > 0) { + ratio_vs_base[runtime] = ops / base_ops; + } + } + rows.push({ + name: row.name, + category: categorize_name(row.name), + ops_per_second: row.ops_per_second, + ratio_vs_base, + }); + } + + const result: Array = []; + for (const [group, rows] of grouped) { + const [operation, language] = group.split('/'); + result.push({group, operation: operation!, language: language!, rows}); + } + result.sort( + (a, b) => + (CROSS_RUNTIME_OP_ORDER[a.operation] ?? 9) - (CROSS_RUNTIME_OP_ORDER[b.operation] ?? 9) || + (CROSS_RUNTIME_LANG_ORDER[a.language] ?? 9) - (CROSS_RUNTIME_LANG_ORDER[b.language] ?? 9), + ); + return result; +}; + // Formatting utilities export interface FormattedUnit { @@ -334,3 +425,19 @@ export const speedup_color = (ratio: number): string => { if (ratio < 5) return 'var(--color_b_50)'; // green — fast return 'var(--color_j_50)'; // teal — exceptional }; + +/** + * Cross-runtime ratio cell background: a stable fuz_css red (`color_c`) / green + * (`color_b`) whose ALPHA varies with distance from parity. Fully transparent at ratio + * `1.0` (parity recedes), ramping to `0.3` alpha at ratio `0.8` and below (red) or `1.2` + * and above (green). The hue stays constant — only opacity moves — so it reads + * consistently in light and dark themes while the cell's text keeps the default color. + * Deliberately its own scale — NOT the shared `speedup_color` — because cross-runtime + * deltas cluster tightly near 1.0 and this must not bleed into the other displays. + */ +export const cross_runtime_ratio_background = (ratio: number): string => { + // 0 alpha at ratio 1.0, up to 0.3 at ratio ≤ 0.8 (red) or ≥ 1.2 (green) + const alpha = Math.min(1, Math.abs(ratio - 1) / 0.2) * 0.3; + const color = ratio < 1 ? 'var(--color_c_50)' : 'var(--color_b_50)'; + return `color-mix(in srgb, ${color} ${(alpha * 100).toFixed(1)}%, transparent)`; +}; diff --git a/src/routes/docs/benchmarks/benchmarks.json b/src/routes/docs/benchmarks/benchmarks.json index bf56417..9fe5387 100644 --- a/src/routes/docs/benchmarks/benchmarks.json +++ b/src/routes/docs/benchmarks/benchmarks.json @@ -1,11 +1,12 @@ { - "version": 4, - "timestamp": "2026-06-12T09:22:00.588Z", - "git_commit": "98918f9", + "version": 5, + "runtime": "node", + "timestamp": "2026-06-26T16:05:52.967Z", + "git_commit": "e4c23f8e", "corpus": { - "svelte": 1240, - "typescript": 4025, - "css": 193 + "svelte": 1259, + "typescript": 4521, + "css": 182 }, "versions": { "tsv": "0.1.0", @@ -13,35 +14,53 @@ "acorn": "8.16.0", "acorn_ts": "1.0.10", "prettier": "3.8.3", - "prettier_svelte": "3.5.2", + "prettier_svelte": "4.1.1", "oxc_parser": "0.134.0", "oxfmt": "0.53.0", "biome": "2.4.16" }, "binary_sizes": [ { - "label": "tsv (native)", - "bytes": 3861760, + "label": "tsv (ffi)", + "bytes": 3717440, "kind": "native", - "gzip_bytes": 1622771 + "gzip_bytes": 1550897 + }, + { + "label": "tsv format (ffi)", + "bytes": 2935520, + "kind": "native", + "gzip_bytes": 1251205 + }, + { + "label": "tsv parse (ffi)", + "bytes": 2068624, + "kind": "native", + "gzip_bytes": 867280 + }, + { + "label": "tsv (napi)", + "bytes": 3841744, + "kind": "native", + "gzip_bytes": 1591977 }, { "label": "tsv_format_wasm", - "bytes": 2196292, + "bytes": 2213824, "kind": "wasm", - "gzip_bytes": 715422 + "gzip_bytes": 735053 }, { "label": "tsv_parse_wasm", - "bytes": 1699625, + "bytes": 1565374, "kind": "wasm", - "gzip_bytes": 526578 + "gzip_bytes": 492040 }, { "label": "tsv_wasm", - "bytes": 2888918, + "bytes": 2881851, "kind": "wasm", - "gzip_bytes": 911323 + "gzip_bytes": 920193 }, { "label": "biome (wasm)", @@ -50,13 +69,13 @@ "gzip_bytes": 8187702 }, { - "label": "oxc-parser (native)", + "label": "oxc-parser (napi)", "bytes": 2658008, "kind": "native", "gzip_bytes": 1032774 }, { - "label": "oxfmt (native)", + "label": "oxfmt (napi)", "bytes": 8016464, "kind": "native", "gzip_bytes": 3224684 @@ -72,610 +91,642 @@ { "name": "svelte/compiler", "group": "parse/svelte", - "mean_ns": 353647929.8666667, - "p50_ns": 351794280, - "p75_ns": 355710613.5, - "p90_ns": 358757843.8, - "p95_ns": 359832344.1, - "p99_ns": 361455435.21999997, - "min_ns": 349590498, - "max_ns": 361861208, - "std_dev_ns": 3732468.9277879535, - "cv": 0.010554194193064213, - "ops_per_second": 2.8276710127414653, - "sample_size": 15, - "files_processed": 1193, - "files_total": 1240, - "files_iterated": 1192 + "mean_ns": 460519821.6363636, + "p50_ns": 460422814, + "p75_ns": 463332024, + "p90_ns": 465071237, + "p95_ns": 468095849.5, + "p99_ns": 470515539.5, + "min_ns": 452885544, + "max_ns": 471120462, + "std_dev_ns": 5248688.184362533, + "cv": 0.01139731220626375, + "ops_per_second": 2.171459192454959, + "sample_size": 11, + "files_processed": 1212, + "files_total": 1259, + "files_iterated": 1210, + "runtime": "node" }, { "name": "tsv-json", "group": "parse/svelte", - "mean_ns": 485025992.4444444, - "p50_ns": 485086813, - "p75_ns": 487644066, - "p90_ns": 491656222, - "p95_ns": 494258617.5, - "p99_ns": 496340533.9, - "min_ns": 481783564, - "max_ns": 496861013, - "std_dev_ns": 1892163.1540198317, - "cv": 0.0039011582543930627, - "ops_per_second": 2.061745175676418, - "sample_size": 9, - "files_processed": 1202, - "files_total": 1240, - "files_iterated": 1192 + "mean_ns": 549611779, + "p50_ns": 549186590.5, + "p75_ns": 554153198.25, + "p90_ns": 561714720.5, + "p95_ns": 562045063.25, + "p99_ns": 562309337.45, + "min_ns": 538345222, + "max_ns": 562375406, + "std_dev_ns": 8379151.02838542, + "cv": 0.01524558124214696, + "ops_per_second": 1.8194660999068581, + "sample_size": 10, + "files_processed": 1220, + "files_total": 1259, + "files_iterated": 1210, + "runtime": "node" }, { "name": "tsv_wasm-json", "group": "parse/svelte", - "mean_ns": 515988848.71428573, - "p50_ns": 516072939.5, - "p75_ns": 517319991, - "p90_ns": 519264292.5, - "p95_ns": 520772636.25, - "p99_ns": 521979311.25, - "min_ns": 515560589, - "max_ns": 522280980, - "std_dev_ns": 253147.57598596797, - "cv": 0.0004906066800023837, - "ops_per_second": 1.9380263788485899, - "sample_size": 7, - "files_processed": 1202, - "files_total": 1240, - "files_iterated": 1192 + "mean_ns": 542348822.7777778, + "p50_ns": 543610598, + "p75_ns": 544628795.25, + "p90_ns": 547038258, + "p95_ns": 555039433.5, + "p99_ns": 561440373.9, + "min_ns": 537453841, + "max_ns": 563040609, + "std_dev_ns": 2621528.985338793, + "cv": 0.004833658478157957, + "ops_per_second": 1.8438317886968851, + "sample_size": 9, + "files_processed": 1220, + "files_total": 1259, + "files_iterated": 1210, + "runtime": "node" }, { "name": "tsv-internal", "group": "parse/svelte", - "mean_ns": 37041735.949579835, - "p50_ns": 36817941, - "p75_ns": 38031003.5, - "p90_ns": 39745595, - "p95_ns": 49374707.5, - "p99_ns": 70563356.69999997, - "min_ns": 35490755, - "max_ns": 73560234, - "std_dev_ns": 1041838.039960544, - "cv": 0.02812605870790355, - "ops_per_second": 26.996574927297463, - "sample_size": 119, - "files_processed": 1202, - "files_total": 1240, - "files_iterated": 1192 + "mean_ns": 27825114.72067039, + "p50_ns": 27652418.5, + "p75_ns": 28329825.5, + "p90_ns": 28792367.4, + "p95_ns": 29096448.15, + "p99_ns": 29372411.430000003, + "min_ns": 26674830, + "max_ns": 29907294, + "std_dev_ns": 657412.7169118039, + "cv": 0.023626595020772113, + "ops_per_second": 35.93875569027329, + "sample_size": 179, + "files_processed": 1220, + "files_total": 1259, + "files_iterated": 1210, + "runtime": "node" }, { "name": "tsv_wasm-internal", "group": "parse/svelte", - "mean_ns": 45254932.2745098, - "p50_ns": 45241227, - "p75_ns": 45348407.5, - "p90_ns": 45449227, - "p95_ns": 45624719, - "p99_ns": 45694463.7, - "min_ns": 45087137, - "max_ns": 45720491, - "std_dev_ns": 94029.59204496059, - "cv": 0.0020777755554817943, - "ops_per_second": 22.097038924600444, - "sample_size": 102, - "files_processed": 1202, - "files_total": 1240, - "files_iterated": 1192 + "mean_ns": 38555138.608333334, + "p50_ns": 38377422, + "p75_ns": 39482445, + "p90_ns": 41706393.4, + "p95_ns": 43308276.8, + "p99_ns": 46579972.44, + "min_ns": 36633395, + "max_ns": 48316300, + "std_dev_ns": 1317496.0561682512, + "cv": 0.03417173699081156, + "ops_per_second": 25.936879910058455, + "sample_size": 120, + "files_processed": 1220, + "files_total": 1259, + "files_iterated": 1210, + "runtime": "node" }, { "name": "prettier", "group": "format/svelte", - "mean_ns": 3156053205.2, - "p50_ns": 3153333425, - "p75_ns": 3161183958, - "p90_ns": 3191384359.8, - "p95_ns": 3201451160.4, - "p99_ns": 3209504600.88, - "min_ns": 3116677318, - "max_ns": 3211517961, - "std_dev_ns": 35365115.51584766, - "cv": 0.011205487745763958, - "ops_per_second": 0.316851439117811, - "sample_size": 5, - "files_processed": 1201, - "files_total": 1240, - "files_iterated": 1194 + "mean_ns": 4416266211.142858, + "p50_ns": 4431401386, + "p75_ns": 4437882394, + "p90_ns": 4450122432, + "p95_ns": 4454561856, + "p99_ns": 4458113395.2, + "min_ns": 4376027750, + "max_ns": 4459001280, + "std_dev_ns": 33108087.900384482, + "cv": 0.007496850578628649, + "ops_per_second": 0.2264356250709842, + "sample_size": 7, + "files_processed": 1220, + "files_total": 1259, + "files_iterated": 1209, + "runtime": "node" }, { "name": "tsv", "group": "format/svelte", - "mean_ns": 253589550.66666666, - "p50_ns": 250899714, - "p75_ns": 261502311.75, - "p90_ns": 270307677.1, - "p95_ns": 291692469.25, - "p99_ns": 299630277.84999996, - "min_ns": 247143299, - "max_ns": 301614730, - "std_dev_ns": 6469364.524097994, - "cv": 0.02551116363860637, - "ops_per_second": 3.9433801486342004, + "mean_ns": 242260228.05555555, + "p50_ns": 242438319, + "p75_ns": 246252188, + "p90_ns": 251444127, + "p95_ns": 254724943, + "p99_ns": 258228837.4, + "min_ns": 236306398, + "max_ns": 259104811, + "std_dev_ns": 3365180.125239911, + "cv": 0.013890765943092409, + "ops_per_second": 4.127792696416839, "sample_size": 18, - "files_processed": 1202, - "files_total": 1240, - "files_iterated": 1194 + "files_processed": 1220, + "files_total": 1259, + "files_iterated": 1209, + "runtime": "node" }, { "name": "tsv_wasm", "group": "format/svelte", - "mean_ns": 348305291.1666667, - "p50_ns": 348407825, - "p75_ns": 349005457.5, - "p90_ns": 351966927.4, - "p95_ns": 353359477.1, - "p99_ns": 355469057.02, - "min_ns": 347712508, - "max_ns": 355996452, - "std_dev_ns": 403574.7899962474, - "cv": 0.0011586811921359351, - "ops_per_second": 2.8710445272032703, - "sample_size": 12, - "files_processed": 1202, - "files_total": 1240, - "files_iterated": 1194 + "mean_ns": 352891975.53333336, + "p50_ns": 352505929, + "p75_ns": 356387978, + "p90_ns": 367242866.8, + "p95_ns": 369188364.09999996, + "p99_ns": 372514488.02, + "min_ns": 333204891, + "max_ns": 373346019, + "std_dev_ns": 10801366.20274057, + "cv": 0.030608137763450782, + "ops_per_second": 2.8337283625922014, + "sample_size": 15, + "files_processed": 1220, + "files_total": 1259, + "files_iterated": 1209, + "runtime": "node" }, { "name": "oxfmt", "group": "format/svelte", - "mean_ns": 3363123440.8, - "p50_ns": 3355465187, - "p75_ns": 3380464215, - "p90_ns": 3387858512.4, - "p95_ns": 3390323278.2, - "p99_ns": 3392295090.84, - "min_ns": 3336319057, - "max_ns": 3392788044, - "std_dev_ns": 22995300.045456335, - "cv": 0.006837483205786329, - "ops_per_second": 0.2973426392467253, - "sample_size": 5, - "files_processed": 1201, - "files_total": 1240, - "files_iterated": 1194 + "mean_ns": 4346654087.857142, + "p50_ns": 4329093407, + "p75_ns": 4374756750, + "p90_ns": 4392431088.6, + "p95_ns": 4397181613.8, + "p99_ns": 4400982033.96, + "min_ns": 4310719296, + "max_ns": 4401932139, + "std_dev_ns": 37121981.576470226, + "cv": 0.00854035789969452, + "ops_per_second": 0.23006201546923422, + "sample_size": 7, + "files_processed": 1217, + "files_total": 1259, + "files_iterated": 1209, + "runtime": "node" }, { "name": "biome-wasm", "group": "format/svelte", - "mean_ns": 651628305.75, - "p50_ns": 651348032.5, - "p75_ns": 652776746.25, - "p90_ns": 655602311.7, - "p95_ns": 657068072.85, - "p99_ns": 658240681.77, - "min_ns": 646287594, - "max_ns": 658533834, - "std_dev_ns": 3695077.8107031505, - "cv": 0.005670529929558927, - "ops_per_second": 1.5346171907757093, + "mean_ns": 696247855.625, + "p50_ns": 696021053.5, + "p75_ns": 698726481.5, + "p90_ns": 700920667.4, + "p95_ns": 701746768.2, + "p99_ns": 702407648.84, + "min_ns": 691423120, + "max_ns": 702572869, + "std_dev_ns": 4053900.7516915267, + "cv": 0.005822496570639297, + "ops_per_second": 1.4362701327134877, "sample_size": 8, - "files_processed": 1238, - "files_total": 1240, - "files_iterated": 1194 + "files_processed": 1257, + "files_total": 1259, + "files_iterated": 1209, + "runtime": "node" }, { "name": "acorn-typescript", "group": "parse/typescript", - "mean_ns": 2213405912.6, - "p50_ns": 2212095774, - "p75_ns": 2213405114, - "p90_ns": 2218802607.8, - "p95_ns": 2220601772.4, - "p99_ns": 2222041104.08, - "min_ns": 2209487030, - "max_ns": 2222400937, - "std_dev_ns": 5295312.414249306, - "cv": 0.0023923819775240017, - "ops_per_second": 0.4517924138123132, + "mean_ns": 3076358260.8, + "p50_ns": 3081831315, + "p75_ns": 3085922639, + "p90_ns": 3087326909.6, + "p95_ns": 3087794999.8, + "p99_ns": 3088169471.96, + "min_ns": 3058750622, + "max_ns": 3088263090, + "std_dev_ns": 12848353.375428025, + "cv": 0.004176481503843716, + "ops_per_second": 0.32505966965627475, "sample_size": 5, - "files_processed": 3693, - "files_total": 4025, - "files_iterated": 3603 + "files_processed": 4189, + "files_total": 4521, + "files_iterated": 4120, + "runtime": "node" }, { "name": "tsv-json", "group": "parse/typescript", - "mean_ns": 2049624429.8, - "p50_ns": 2046277896, - "p75_ns": 2052475955, - "p90_ns": 2062325034.8, - "p95_ns": 2065608061.4, - "p99_ns": 2068234482.68, - "min_ns": 2036381168, - "max_ns": 2068891088, - "std_dev_ns": 12211486.98364508, - "cv": 0.005957914438420635, - "ops_per_second": 0.4878942627052796, + "mean_ns": 2700459663.8, + "p50_ns": 2693962807, + "p75_ns": 2717046507, + "p90_ns": 2724142026, + "p95_ns": 2726507199, + "p99_ns": 2728399337.4, + "min_ns": 2680058864, + "max_ns": 2728872372, + "std_dev_ns": 21612992.219434742, + "cv": 0.008003449379066685, + "ops_per_second": 0.3703073270840239, "sample_size": 5, - "files_processed": 3743, - "files_total": 4025, - "files_iterated": 3603 + "files_processed": 4260, + "files_total": 4521, + "files_iterated": 4120, + "runtime": "node" }, { "name": "tsv_wasm-json", "group": "parse/typescript", - "mean_ns": 2223665077.4, - "p50_ns": 2223809451, - "p75_ns": 2224511693, - "p90_ns": 2224643608.4, - "p95_ns": 2224687580.2, - "p99_ns": 2224722757.64, - "min_ns": 2222334633, - "max_ns": 2224731552, - "std_dev_ns": 1021470.6667904371, - "cv": 0.0004593635422762416, - "ops_per_second": 0.44970801141026184, - "sample_size": 5, - "files_processed": 3743, - "files_total": 4025, - "files_iterated": 3603 + "mean_ns": 2920718620.5, + "p50_ns": 2915295577, + "p75_ns": 2921635900, + "p90_ns": 2929537027.6, + "p95_ns": 2932170736.8, + "p99_ns": 2934277704.16, + "min_ns": 2911138559, + "max_ns": 2934804446, + "std_dev_ns": 10335035.249806762, + "cv": 0.003538524792243595, + "ops_per_second": 0.3423814923427335, + "sample_size": 4, + "files_processed": 4260, + "files_total": 4521, + "files_iterated": 4120, + "runtime": "node" }, { "name": "tsv-internal", "group": "parse/typescript", - "mean_ns": 236250428.1875, - "p50_ns": 235985787, - "p75_ns": 239292380, - "p90_ns": 262673433, - "p95_ns": 263116119, - "p99_ns": 263948169.4, - "min_ns": 234967322, - "max_ns": 264156182, - "std_dev_ns": 1336552.468610353, - "cv": 0.005657354692917632, - "ops_per_second": 4.232796561140413, - "sample_size": 16, - "files_processed": 3743, - "files_total": 4025, - "files_iterated": 3603 + "mean_ns": 207661643.6, + "p50_ns": 207910263, + "p75_ns": 208788219, + "p90_ns": 209654355.8, + "p95_ns": 209901368.6, + "p99_ns": 210464396, + "min_ns": 204851227, + "max_ns": 210633548, + "std_dev_ns": 1627416.2355404045, + "cv": 0.007836864850569855, + "ops_per_second": 4.815525788316548, + "sample_size": 25, + "files_processed": 4260, + "files_total": 4521, + "files_iterated": 4120, + "runtime": "node" }, { "name": "tsv_wasm-internal", "group": "parse/typescript", - "mean_ns": 292595892.125, - "p50_ns": 292647736.5, - "p75_ns": 292773388.75, - "p90_ns": 293666035.6, - "p95_ns": 294709175.9, - "p99_ns": 294963799.18, - "min_ns": 292266142, - "max_ns": 295027455, - "std_dev_ns": 262236.36256371846, - "cv": 0.0008962407525929597, - "ops_per_second": 3.4176829781765687, - "sample_size": 16, - "files_processed": 3743, - "files_total": 4025, - "files_iterated": 3603 + "mean_ns": 264986878.31578946, + "p50_ns": 264872314, + "p75_ns": 265371800.5, + "p90_ns": 266146419.4, + "p95_ns": 266467473, + "p99_ns": 266669965.8, + "min_ns": 263622989, + "max_ns": 266720589, + "std_dev_ns": 868840.6711757439, + "cv": 0.0032788063948597916, + "ops_per_second": 3.7737717669487116, + "sample_size": 19, + "files_processed": 4260, + "files_total": 4521, + "files_iterated": 4120, + "runtime": "node" }, { "name": "oxc-parser", "group": "parse/typescript", - "mean_ns": 864942821.5, - "p50_ns": 863969686.5, - "p75_ns": 878826551, - "p90_ns": 884913960, - "p95_ns": 887896262.5, - "p99_ns": 890282104.5, - "min_ns": 845083325, - "max_ns": 890878565, - "std_dev_ns": 20069394.017162047, - "cv": 0.023203145362091483, - "ops_per_second": 1.1561457880716106, - "sample_size": 6, - "files_processed": 3833, - "files_total": 4025, - "files_iterated": 3603 + "mean_ns": 1285272706.6, + "p50_ns": 1284306062, + "p75_ns": 1290462919, + "p90_ns": 1298897336.8, + "p95_ns": 1301708809.4, + "p99_ns": 1303957987.48, + "min_ns": 1271248715, + "max_ns": 1304520282, + "std_dev_ns": 13079209.447332447, + "cv": 0.010176213483854002, + "ops_per_second": 0.7780449976607323, + "sample_size": 5, + "files_processed": 4329, + "files_total": 4521, + "files_iterated": 4120, + "runtime": "node" }, { "name": "oxc-parser-wasm", "group": "parse/typescript", - "mean_ns": 976785685.3333334, - "p50_ns": 975594108.5, - "p75_ns": 979113434.75, - "p90_ns": 982226200, - "p95_ns": 983362576, - "p99_ns": 984271676.8, - "min_ns": 971966753, - "max_ns": 984498952, - "std_dev_ns": 4714293.024074751, - "cv": 0.004826333037902754, - "ops_per_second": 1.023766026688592, - "sample_size": 6, - "files_processed": 4025, - "files_total": 4025, - "files_iterated": 3603 + "mean_ns": 1337305811, + "p50_ns": 1333881007, + "p75_ns": 1337935981, + "p90_ns": 1345591239.4, + "p95_ns": 1348142992.2, + "p99_ns": 1350184394.44, + "min_ns": 1330452412, + "max_ns": 1350694745, + "std_dev_ns": 7942817.013954716, + "cv": 0.005939417109101843, + "ops_per_second": 0.747772118968232, + "sample_size": 5, + "files_processed": 4521, + "files_total": 4521, + "files_iterated": 4120, + "runtime": "node" }, { "name": "prettier", "group": "format/typescript", - "mean_ns": 8773944013.666666, - "p50_ns": 8784008051, - "p75_ns": 8807150369, - "p90_ns": 8902301987.4, - "p95_ns": 8961594658.2, - "p99_ns": 9009028794.84, - "min_ns": 8712430383, - "max_ns": 9020887329, - "std_dev_ns": 36684367.115987, - "cv": 0.004181057806939032, - "ops_per_second": 0.1139738296075696, - "sample_size": 6, - "files_processed": 3855, - "files_total": 4025, - "files_iterated": 3701 + "mean_ns": 13530175349.571428, + "p50_ns": 13565356847, + "p75_ns": 13608654437, + "p90_ns": 13685762982.8, + "p95_ns": 13718048651.9, + "p99_ns": 13743877187.18, + "min_ns": 13337759540, + "max_ns": 13750334321, + "std_dev_ns": 144670076.113311, + "cv": 0.010692402158549516, + "ops_per_second": 0.07390887214419399, + "sample_size": 7, + "files_processed": 4351, + "files_total": 4521, + "files_iterated": 4219, + "runtime": "node" }, { "name": "tsv", "group": "format/typescript", - "mean_ns": 854559033.5, - "p50_ns": 856988296.5, - "p75_ns": 860171191.5, - "p90_ns": 861313209, - "p95_ns": 861398115.5, - "p99_ns": 861466040.7, - "min_ns": 838541329, - "max_ns": 861483022, - "std_dev_ns": 8547810.99796243, - "cv": 0.01000259860685497, - "ops_per_second": 1.1701941712608437, + "mean_ns": 828181230.5, + "p50_ns": 829474298, + "p75_ns": 830763649, + "p90_ns": 841818961.6, + "p95_ns": 850035221.8, + "p99_ns": 856608229.96, + "min_ns": 824390444, + "max_ns": 858251482, + "std_dev_ns": 2596616.5472364803, + "cv": 0.003135324071120059, + "ops_per_second": 1.2074651817407978, "sample_size": 6, - "files_processed": 3743, - "files_total": 4025, - "files_iterated": 3701 + "files_processed": 4260, + "files_total": 4521, + "files_iterated": 4219, + "runtime": "node" }, { "name": "tsv_wasm", "group": "format/typescript", - "mean_ns": 1145280037.8, - "p50_ns": 1144938011, - "p75_ns": 1145815746, - "p90_ns": 1146670300.2, - "p95_ns": 1146955151.6, - "p99_ns": 1147183032.72, - "min_ns": 1144152898, - "max_ns": 1147240003, - "std_dev_ns": 1281560.5264546424, - "cv": 0.0011189931581418527, - "ops_per_second": 0.8731488954622204, + "mean_ns": 1049490559.6, + "p50_ns": 1048186918, + "p75_ns": 1051124496, + "p90_ns": 1053196050, + "p95_ns": 1053886568, + "p99_ns": 1054438982.4, + "min_ns": 1046485510, + "max_ns": 1054577086, + "std_dev_ns": 3357415.1421673787, + "cv": 0.0031990903695665587, + "ops_per_second": 0.9528432541414544, "sample_size": 5, - "files_processed": 3743, - "files_total": 4025, - "files_iterated": 3701 + "files_processed": 4260, + "files_total": 4521, + "files_iterated": 4219, + "runtime": "node" }, { "name": "oxfmt", "group": "format/typescript", - "mean_ns": 802078434.8571428, - "p50_ns": 804423326, - "p75_ns": 806569662, - "p90_ns": 809150059.2, - "p95_ns": 809881109.1, - "p99_ns": 810465949.02, - "min_ns": 792012009, - "max_ns": 810612159, - "std_dev_ns": 7054022.950975906, - "cv": 0.008794679727590843, - "ops_per_second": 1.246760860960074, - "sample_size": 7, - "files_processed": 3836, - "files_total": 4025, - "files_iterated": 3701 + "mean_ns": 1043309450.6, + "p50_ns": 1038106859, + "p75_ns": 1048998909, + "p90_ns": 1061121142.2, + "p95_ns": 1065161886.6, + "p99_ns": 1068394482.12, + "min_ns": 1028403158, + "max_ns": 1069202631, + "std_dev_ns": 16460090.3032646, + "cv": 0.015776805523805535, + "ops_per_second": 0.9584883942390313, + "sample_size": 5, + "files_processed": 4332, + "files_total": 4521, + "files_iterated": 4219, + "runtime": "node" }, { "name": "biome-wasm", "group": "format/typescript", - "mean_ns": 3651240436.25, - "p50_ns": 3651115766, - "p75_ns": 3652416674, - "p90_ns": 3654275795, - "p95_ns": 3654895502, - "p99_ns": 3655391267.6, - "min_ns": 3650446557, - "max_ns": 3655515209, - "std_dev_ns": 835808.0747653235, - "cv": 0.00022891071934548872, - "ops_per_second": 0.2738795260021409, - "sample_size": 4, - "files_processed": 4025, - "files_total": 4025, - "files_iterated": 3701 + "mean_ns": 4227132372.2, + "p50_ns": 4226520582, + "p75_ns": 4229707731, + "p90_ns": 4237808559.6, + "p95_ns": 4240508835.8, + "p99_ns": 4242669056.76, + "min_ns": 4214235300, + "max_ns": 4243209112, + "std_dev_ns": 10703453.563400237, + "cv": 0.0025320838386306914, + "ops_per_second": 0.23656699434741207, + "sample_size": 5, + "files_processed": 4521, + "files_total": 4521, + "files_iterated": 4219, + "runtime": "node" }, { "name": "svelte/compiler", "group": "parse/css", - "mean_ns": 19403785.678294573, - "p50_ns": 19376518.5, - "p75_ns": 19515459.5, - "p90_ns": 19626101.3, - "p95_ns": 19749809.1, - "p99_ns": 19835973.34, - "min_ns": 19083462, - "max_ns": 19889772, - "std_dev_ns": 170231.79292084067, - "cv": 0.008773122716525623, - "ops_per_second": 51.53633505232013, - "sample_size": 258, - "files_processed": 163, - "files_total": 193, - "files_iterated": 159 + "mean_ns": 5674981.744769874, + "p50_ns": 5675173, + "p75_ns": 5779161, + "p90_ns": 6076480.6, + "p95_ns": 6176071.8, + "p99_ns": 6446288.039999994, + "min_ns": 5445454, + "max_ns": 6906669, + "std_dev_ns": 66349.12347821353, + "cv": 0.011691513111801922, + "ops_per_second": 176.21202057990953, + "sample_size": 717, + "files_processed": 152, + "files_total": 182, + "files_iterated": 148, + "runtime": "node" }, { "name": "tsv-json", "group": "parse/css", - "mean_ns": 176879819.27586207, - "p50_ns": 176417640, - "p75_ns": 178453737, - "p90_ns": 179335842.4, - "p95_ns": 179414368, - "p99_ns": 179869721.35999998, - "min_ns": 173847338, - "max_ns": 180029857, - "std_dev_ns": 1802916.9896241936, - "cv": 0.010192892535763852, - "ops_per_second": 5.653556206094932, - "sample_size": 29, - "files_processed": 165, - "files_total": 193, - "files_iterated": 159 + "mean_ns": 12977907.827195467, + "p50_ns": 12904785.5, + "p75_ns": 13270227.75, + "p90_ns": 13843168.6, + "p95_ns": 14260476.749999998, + "p99_ns": 15100004.379999999, + "min_ns": 12545202, + "max_ns": 16392338, + "std_dev_ns": 332659.4852305573, + "cv": 0.025632751415714528, + "ops_per_second": 77.05402236749438, + "sample_size": 353, + "files_processed": 154, + "files_total": 182, + "files_iterated": 148, + "runtime": "node" }, { "name": "tsv_wasm-json", "group": "parse/css", - "mean_ns": 223033824.05555555, - "p50_ns": 222987561, - "p75_ns": 224042748.5, - "p90_ns": 226002163.2, - "p95_ns": 226359314, - "p99_ns": 226689078.04, - "min_ns": 222564338, - "max_ns": 226779975, - "std_dev_ns": 476931.02029914665, - "cv": 0.002138379783060832, - "ops_per_second": 4.483624868266213, - "sample_size": 18, - "files_processed": 165, - "files_total": 193, - "files_iterated": 159 + "mean_ns": 15161721.315960912, + "p50_ns": 15133874.5, + "p75_ns": 15355264.75, + "p90_ns": 15682443.5, + "p95_ns": 16132697.15, + "p99_ns": 16849124.020000003, + "min_ns": 14800725, + "max_ns": 22947633, + "std_dev_ns": 234543.9985316129, + "cv": 0.015469483552946315, + "ops_per_second": 65.9555718747639, + "sample_size": 307, + "files_processed": 154, + "files_total": 182, + "files_iterated": 148, + "runtime": "node" }, { "name": "tsv-internal", "group": "parse/css", - "mean_ns": 23123759.831578948, - "p50_ns": 23081315.5, - "p75_ns": 23581269.25, - "p90_ns": 25285569.600000005, - "p95_ns": 26399632.149999995, - "p99_ns": 34455670.899999976, - "min_ns": 22528124, - "max_ns": 43861736, - "std_dev_ns": 454153.9601688399, - "cv": 0.019640143448844544, - "ops_per_second": 43.24556245539061, - "sample_size": 190, - "files_processed": 165, - "files_total": 193, - "files_iterated": 159 + "mean_ns": 4823174.063740857, + "p50_ns": 4814582, + "p75_ns": 4863945, + "p90_ns": 4942298, + "p95_ns": 5028450.2, + "p99_ns": 5181341.199999999, + "min_ns": 4741773, + "max_ns": 5438369, + "std_dev_ns": 49410.0654781549, + "cv": 0.010244304855096278, + "ops_per_second": 207.33234728509868, + "sample_size": 957, + "files_processed": 154, + "files_total": 182, + "files_iterated": 148, + "runtime": "node" }, { "name": "tsv_wasm-internal", "group": "parse/css", - "mean_ns": 32072885.51879699, - "p50_ns": 32066954.5, - "p75_ns": 32148053.5, - "p90_ns": 32335215.5, - "p95_ns": 32349665.75, - "p99_ns": 32378088.75, - "min_ns": 31983936, - "max_ns": 32565198, - "std_dev_ns": 53586.24561517934, - "cv": 0.0016707647206789045, - "ops_per_second": 31.178984485631293, - "sample_size": 133, - "files_processed": 165, - "files_total": 193, - "files_iterated": 159 + "mean_ns": 6639633.008784773, + "p50_ns": 6631641, + "p75_ns": 6687427.75, + "p90_ns": 6811301.2, + "p95_ns": 6917467.15, + "p99_ns": 7045058.15, + "min_ns": 6551900, + "max_ns": 7555351, + "std_dev_ns": 56256.47336614011, + "cv": 0.008472828737929977, + "ops_per_second": 150.61073385786818, + "sample_size": 683, + "files_processed": 154, + "files_total": 182, + "files_iterated": 148, + "runtime": "node" }, { "name": "prettier", "group": "format/css", - "mean_ns": 731055145.8571428, - "p50_ns": 726866934, - "p75_ns": 737411474, - "p90_ns": 739494874, - "p95_ns": 740913023.5, - "p99_ns": 742047543.1, - "min_ns": 723869573, - "max_ns": 742331173, - "std_dev_ns": 7724050.9095097985, - "cv": 0.010565620053810789, - "ops_per_second": 1.3678858642428766, - "sample_size": 7, - "files_processed": 192, - "files_total": 193, - "files_iterated": 165 + "mean_ns": 263628109.83333334, + "p50_ns": 263304673, + "p75_ns": 267583880, + "p90_ns": 270831078.2, + "p95_ns": 275674468.6999999, + "p99_ns": 297184221.74, + "min_ns": 256524612, + "max_ns": 302561660, + "std_dev_ns": 4691145.066799993, + "cv": 0.017794555632803164, + "ops_per_second": 3.793222204689036, + "sample_size": 18, + "files_processed": 181, + "files_total": 182, + "files_iterated": 154, + "runtime": "node" }, { "name": "tsv", "group": "format/css", - "mean_ns": 42276700.15044248, - "p50_ns": 42363994, - "p75_ns": 42798711, - "p90_ns": 43541791.3, - "p95_ns": 44634919.449999996, - "p99_ns": 50024498.75, - "min_ns": 40686670, - "max_ns": 51286794, - "std_dev_ns": 850647.2521532943, - "cv": 0.020120947215043962, - "ops_per_second": 23.65369095604624, - "sample_size": 113, - "files_processed": 165, - "files_total": 193, - "files_iterated": 165 + "mean_ns": 9894566.340425532, + "p50_ns": 9878792, + "p75_ns": 10043937, + "p90_ns": 10292521, + "p95_ns": 10454168, + "p99_ns": 11052136, + "min_ns": 9781647, + "max_ns": 11677218, + "std_dev_ns": 95076.69653038164, + "cv": 0.009608980652535876, + "ops_per_second": 101.06557130395603, + "sample_size": 423, + "files_processed": 154, + "files_total": 182, + "files_iterated": 154, + "runtime": "node" }, { "name": "tsv_wasm", "group": "format/css", - "mean_ns": 56842907.02898551, - "p50_ns": 56836126.5, - "p75_ns": 57051209.25, - "p90_ns": 57277215.5, - "p95_ns": 57411214.85, - "p99_ns": 57614455.839999996, - "min_ns": 56701796, - "max_ns": 57937459, - "std_dev_ns": 94515.15490540798, - "cv": 0.0016627431608522859, - "ops_per_second": 17.59234445011894, - "sample_size": 69, - "files_processed": 165, - "files_total": 193, - "files_iterated": 165 + "mean_ns": 12926065.221590908, + "p50_ns": 12919280, + "p75_ns": 12969386, + "p90_ns": 13072597.4, + "p95_ns": 13263006.2, + "p99_ns": 13874546.119999984, + "min_ns": 12851673, + "max_ns": 21923616, + "std_dev_ns": 49833.05694937264, + "cv": 0.0038552379316587814, + "ops_per_second": 77.3630631485335, + "sample_size": 352, + "files_processed": 154, + "files_total": 182, + "files_iterated": 154, + "runtime": "node" }, { "name": "oxfmt", "group": "format/css", - "mean_ns": 759715951, - "p50_ns": 758504294, - "p75_ns": 764356670.5, - "p90_ns": 792120220.8000001, - "p95_ns": 810371960.4, - "p99_ns": 824973352.0799999, - "min_ns": 755827467, - "max_ns": 828623700, - "std_dev_ns": 4300372.980217599, - "cv": 0.005660501105126328, - "ops_per_second": 1.3162814321375227, - "sample_size": 6, - "files_processed": 192, - "files_total": 193, - "files_iterated": 165 + "mean_ns": 288994107.4444444, + "p50_ns": 289283819.5, + "p75_ns": 294131086.75, + "p90_ns": 296024037.1, + "p95_ns": 298473210.25, + "p99_ns": 302334464.45, + "min_ns": 278485858, + "max_ns": 303299778, + "std_dev_ns": 7004351.959271854, + "cv": 0.024237006149401694, + "ops_per_second": 3.4602781656793393, + "sample_size": 18, + "files_processed": 181, + "files_total": 182, + "files_iterated": 154, + "runtime": "node" }, { "name": "biome-wasm", "group": "format/css", - "mean_ns": 207351523.875, - "p50_ns": 207159397, - "p75_ns": 208264123, - "p90_ns": 208754043.4, - "p95_ns": 209395575, - "p99_ns": 209795343.92, - "min_ns": 205889964, - "max_ns": 209888054, - "std_dev_ns": 897025.2129294197, - "cv": 0.004326108610950857, - "ops_per_second": 4.822727999832984, - "sample_size": 24, - "files_processed": 193, - "files_total": 193, - "files_iterated": 165 + "mean_ns": 54798579.31111111, + "p50_ns": 54753750, + "p75_ns": 55061631.5, + "p90_ns": 55378274.2, + "p95_ns": 55661000.15, + "p99_ns": 56701458.46, + "min_ns": 54211043, + "max_ns": 57160184, + "std_dev_ns": 382798.5097647677, + "cv": 0.0069855553661616636, + "ops_per_second": 18.248648278318363, + "sample_size": 90, + "files_processed": 182, + "files_total": 182, + "files_iterated": 154, + "runtime": "node" } ], "suppressed_noise": { diff --git a/src/routes/docs/benchmarks/benchmarks_cross_runtime.json b/src/routes/docs/benchmarks/benchmarks_cross_runtime.json new file mode 100644 index 0000000..9be7d2b --- /dev/null +++ b/src/routes/docs/benchmarks/benchmarks_cross_runtime.json @@ -0,0 +1,628 @@ +{ + "version": 5, + "kind": "combined", + "generated": "2026-06-26T16:14:57.526Z", + "runtimes": [ + "deno", + "node", + "bun" + ], + "sources": [ + { + "runtime": "deno", + "timestamp": "2026-06-26T15:56:20.597Z", + "git_commit": "e4c23f8e", + "tsv": "0.1.0" + }, + { + "runtime": "node", + "timestamp": "2026-06-26T16:05:52.967Z", + "git_commit": "e4c23f8e", + "tsv": "0.1.0" + }, + { + "runtime": "bun", + "timestamp": "2026-06-26T16:14:57.136Z", + "git_commit": "e4c23f8e", + "tsv": "0.1.0" + } + ], + "rows": [ + { + "group": "parse/svelte", + "name": "svelte/compiler", + "ops_per_second": { + "deno": 2.238630616724675, + "node": 2.171459192454959, + "bun": 1.3719971999128666 + }, + "mean_ns": { + "deno": 446701654.3636364, + "node": 460519821.6363636, + "bun": 728864461.2857143 + }, + "files_iterated": { + "deno": 1209, + "node": 1210, + "bun": 1210 + } + }, + { + "group": "parse/svelte", + "name": "tsv-json", + "ops_per_second": { + "deno": 1.7348541684381054, + "node": 1.8194660999068581, + "bun": 2.117882505475197 + }, + "mean_ns": { + "deno": 576417325.5555556, + "node": 549611779, + "bun": 472169724.90909094 + }, + "files_iterated": { + "deno": 1209, + "node": 1210, + "bun": 1210 + } + }, + { + "group": "parse/svelte", + "name": "tsv_wasm-json", + "ops_per_second": { + "deno": 1.654180031415882, + "node": 1.8438317886968851, + "bun": 2.0787300384189034 + }, + "mean_ns": { + "deno": 604529120.7777778, + "node": 542348822.7777778, + "bun": 481062947.8181818 + }, + "files_iterated": { + "deno": 1209, + "node": 1210, + "bun": 1210 + } + }, + { + "group": "parse/svelte", + "name": "tsv-internal", + "ops_per_second": { + "deno": 30.00127879779205, + "node": 35.93875569027329, + "bun": 38.41372651816012 + }, + "mean_ns": { + "deno": 33331912.507462688, + "node": 27825114.72067039, + "bun": 26032361.102150537 + }, + "files_iterated": { + "deno": 1209, + "node": 1210, + "bun": 1210 + } + }, + { + "group": "parse/svelte", + "name": "tsv_wasm-internal", + "ops_per_second": { + "deno": 22.32329562930429, + "node": 25.936879910058455, + "bun": 27.381700251347603 + }, + "mean_ns": { + "deno": 44796253.053571425, + "node": 38555138.608333334, + "bun": 36520741.62015504 + }, + "files_iterated": { + "deno": 1209, + "node": 1210, + "bun": 1210 + } + }, + { + "group": "format/svelte", + "name": "prettier", + "ops_per_second": { + "deno": 0.23667794345472865, + "node": 0.2264356250709842, + "bun": 0.21810325927088134 + }, + "mean_ns": { + "deno": 4225150791, + "node": 4416266211.142858, + "bun": 4584984210.428572 + }, + "files_iterated": { + "deno": 1208, + "node": 1209, + "bun": 1211 + } + }, + { + "group": "format/svelte", + "name": "tsv", + "ops_per_second": { + "deno": 2.8819502728352986, + "node": 4.127792696416839, + "bun": 3.8587202815978814 + }, + "mean_ns": { + "deno": 346987250.06666666, + "node": 242260228.05555555, + "bun": 259153275.44444445 + }, + "files_iterated": { + "deno": 1208, + "node": 1209, + "bun": 1211 + } + }, + { + "group": "format/svelte", + "name": "tsv_wasm", + "ops_per_second": { + "deno": 2.576710545344571, + "node": 2.8337283625922014, + "bun": 2.832828903462568 + }, + "mean_ns": { + "deno": 388091709.3333333, + "node": 352891975.53333336, + "bun": 353004023.21428573 + }, + "files_iterated": { + "deno": 1208, + "node": 1209, + "bun": 1211 + } + }, + { + "group": "format/svelte", + "name": "oxfmt", + "ops_per_second": { + "deno": 0.23531669038674202, + "node": 0.23006201546923422, + "bun": 0.18181135209599103 + }, + "mean_ns": { + "deno": 4249592319, + "node": 4346654087.857142, + "bun": 5500206606.857142 + }, + "files_iterated": { + "deno": 1208, + "node": 1209, + "bun": 1211 + } + }, + { + "group": "format/svelte", + "name": "biome-wasm", + "ops_per_second": { + "deno": 1.256549970281186, + "node": 1.4362701327134877 + }, + "mean_ns": { + "deno": 795829870.4, + "node": 696247855.625 + }, + "files_iterated": { + "deno": 1208, + "node": 1209 + } + }, + { + "group": "parse/typescript", + "name": "acorn-typescript", + "ops_per_second": { + "deno": 0.33972384153178553, + "node": 0.32505966965627475, + "bun": 0.15898909853547305 + }, + "mean_ns": { + "deno": 2943567326.6, + "node": 3076358260.8, + "bun": 6289739417.428572 + }, + "files_iterated": { + "deno": 4120, + "node": 4120, + "bun": 4120 + } + }, + { + "group": "parse/typescript", + "name": "tsv-json", + "ops_per_second": { + "deno": 0.30966010569974217, + "node": 0.3703073270840239, + "bun": 0.5098148870230883 + }, + "mean_ns": { + "deno": 3229347215.2, + "node": 2700459663.8, + "bun": 1961496271.4 + }, + "files_iterated": { + "deno": 4120, + "node": 4120, + "bun": 4120 + } + }, + { + "group": "parse/typescript", + "name": "tsv_wasm-json", + "ops_per_second": { + "deno": 0.33790933050214117, + "node": 0.3423814923427335, + "bun": 0.46423771599387137 + }, + "mean_ns": { + "deno": 2959373742.4, + "node": 2920718620.5, + "bun": 2154068843.5 + }, + "files_iterated": { + "deno": 4120, + "node": 4120, + "bun": 4120 + } + }, + { + "group": "parse/typescript", + "name": "tsv-internal", + "ops_per_second": { + "deno": 4.393287195839822, + "node": 4.815525788316548, + "bun": 5.272376675322944 + }, + "mean_ns": { + "deno": 227619992.82608697, + "node": 207661643.6, + "bun": 189667783.92 + }, + "files_iterated": { + "deno": 4120, + "node": 4120, + "bun": 4120 + } + }, + { + "group": "parse/typescript", + "name": "tsv_wasm-internal", + "ops_per_second": { + "deno": 3.0975007968920942, + "node": 3.7737717669487116, + "bun": 3.920307133301353 + }, + "mean_ns": { + "deno": 322840917.75, + "node": 264986878.31578946, + "bun": 255082055.0526316 + }, + "files_iterated": { + "deno": 4120, + "node": 4120, + "bun": 4120 + } + }, + { + "group": "parse/typescript", + "name": "oxc-parser", + "ops_per_second": { + "deno": 0.8458763500275998, + "node": 0.7780449976607323, + "bun": 1.0442646052841589 + }, + "mean_ns": { + "deno": 1182205886.2, + "node": 1285272706.6, + "bun": 957611696.25 + }, + "files_iterated": { + "deno": 4120, + "node": 4120, + "bun": 4120 + } + }, + { + "group": "parse/typescript", + "name": "oxc-parser-wasm", + "ops_per_second": { + "deno": 0.7765769385649736, + "node": 0.747772118968232 + }, + "mean_ns": { + "deno": 1287702416, + "node": 1337305811 + }, + "files_iterated": { + "deno": 4120, + "node": 4120 + } + }, + { + "group": "format/typescript", + "name": "prettier", + "ops_per_second": { + "deno": 0.07970672931562878, + "node": 0.07390887214419399, + "bun": 0.06404911345750294 + }, + "mean_ns": { + "deno": 12545992146.285715, + "node": 13530175349.571428, + "bun": 15613018604.285715 + }, + "files_iterated": { + "deno": 4219, + "node": 4219, + "bun": 4219 + } + }, + { + "group": "format/typescript", + "name": "tsv", + "ops_per_second": { + "deno": 1.0725580083372601, + "node": 1.2074651817407978, + "bun": 1.2414351255420437 + }, + "mean_ns": { + "deno": 932350504.3333334, + "node": 828181230.5, + "bun": 805519337.6 + }, + "files_iterated": { + "deno": 4219, + "node": 4219, + "bun": 4219 + } + }, + { + "group": "format/typescript", + "name": "tsv_wasm", + "ops_per_second": { + "deno": 0.8236856671645635, + "node": 0.9528432541414544, + "bun": 0.9578534407075834 + }, + "mean_ns": { + "deno": 1214055361, + "node": 1049490559.6, + "bun": 1044001052.25 + }, + "files_iterated": { + "deno": 4219, + "node": 4219, + "bun": 4219 + } + }, + { + "group": "format/typescript", + "name": "oxfmt", + "ops_per_second": { + "deno": 0.9232216237778202, + "node": 0.9584883942390313, + "bun": 0.7333963399702814 + }, + "mean_ns": { + "deno": 1083163537.6, + "node": 1043309450.6, + "bun": 1363519212.6 + }, + "files_iterated": { + "deno": 4219, + "node": 4219, + "bun": 4219 + } + }, + { + "group": "format/typescript", + "name": "biome-wasm", + "ops_per_second": { + "deno": 0.20314375821255962, + "node": 0.23656699434741207 + }, + "mean_ns": { + "deno": 4922622328.142858, + "node": 4227132372.2 + }, + "files_iterated": { + "deno": 4219, + "node": 4219 + } + }, + { + "group": "parse/css", + "name": "svelte/compiler", + "ops_per_second": { + "deno": 189.38754559028513, + "node": 176.21202057990953, + "bun": 136.16648168429685 + }, + "mean_ns": { + "deno": 5280178.255033557, + "node": 5674981.744769874, + "bun": 7343951.225225225 + }, + "files_iterated": { + "deno": 148, + "node": 148, + "bun": 148 + } + }, + { + "group": "parse/css", + "name": "tsv-json", + "ops_per_second": { + "deno": 66.4970799078557, + "node": 77.05402236749438, + "bun": 87.8934606924887 + }, + "mean_ns": { + "deno": 15038254.332155477, + "node": 12977907.827195467, + "bun": 11377410.69837587 + }, + "files_iterated": { + "deno": 148, + "node": 148, + "bun": 148 + } + }, + { + "group": "parse/css", + "name": "tsv_wasm-json", + "ops_per_second": { + "deno": 60.90767584127031, + "node": 65.9555718747639, + "bun": 71.16952761134718 + }, + "mean_ns": { + "deno": 16418291.885017421, + "node": 15161721.315960912, + "bun": 14050957.390934844 + }, + "files_iterated": { + "deno": 148, + "node": 148, + "bun": 148 + } + }, + { + "group": "parse/css", + "name": "tsv-internal", + "ops_per_second": { + "deno": 179.61417038106768, + "node": 207.33234728509868, + "bun": 220.58003846953548 + }, + "mean_ns": { + "deno": 5567489.457420925, + "node": 4823174.063740857, + "bun": 4533501.793445879 + }, + "files_iterated": { + "deno": 148, + "node": 148, + "bun": 148 + } + }, + { + "group": "parse/css", + "name": "tsv_wasm-internal", + "ops_per_second": { + "deno": 130.70208131736257, + "node": 150.61073385786818, + "bun": 150.96756743906028 + }, + "mean_ns": { + "deno": 7650987.573578595, + "node": 6639633.008784773, + "bun": 6623939.280227596 + }, + "files_iterated": { + "deno": 148, + "node": 148, + "bun": 148 + } + }, + { + "group": "format/css", + "name": "prettier", + "ops_per_second": { + "deno": 4.004403609771404, + "node": 3.793222204689036, + "bun": 3.918061399656031 + }, + "mean_ns": { + "deno": 249725077.0526316, + "node": 263628109.83333334, + "bun": 255228261.63157895 + }, + "files_iterated": { + "deno": 154, + "node": 154, + "bun": 154 + } + }, + { + "group": "format/css", + "name": "tsv", + "ops_per_second": { + "deno": 79.21000891029992, + "node": 101.06557130395603, + "bun": 105.63197034802205 + }, + "mean_ns": { + "deno": 12624667.18230563, + "node": 9894566.340425532, + "bun": 9466830.891304348 + }, + "files_iterated": { + "deno": 154, + "node": 154, + "bun": 154 + } + }, + { + "group": "format/css", + "name": "tsv_wasm", + "ops_per_second": { + "deno": 66.83676930074832, + "node": 77.3630631485335, + "bun": 77.99320050438536 + }, + "mean_ns": { + "deno": 14961824.314102564, + "node": 12926065.221590908, + "bun": 12821630.520775624 + }, + "files_iterated": { + "deno": 154, + "node": 154, + "bun": 154 + } + }, + { + "group": "format/css", + "name": "oxfmt", + "ops_per_second": { + "deno": 3.6024211048191663, + "node": 3.4602781656793393, + "bun": 2.845532359370373 + }, + "mean_ns": { + "deno": 277591089.6875, + "node": 288994107.4444444, + "bun": 351428089.26666665 + }, + "files_iterated": { + "deno": 154, + "node": 154, + "bun": 154 + } + }, + { + "group": "format/css", + "name": "biome-wasm", + "ops_per_second": { + "deno": 14.800849700236778, + "node": 18.248648278318363 + }, + "mean_ns": { + "deno": 67563688.5890411, + "node": 54798579.31111111 + }, + "files_iterated": { + "deno": 154, + "node": 154 + } + } + ] +} diff --git a/src/routes/docs/benchmarks/benchmarks_cross_runtime.ts b/src/routes/docs/benchmarks/benchmarks_cross_runtime.ts new file mode 100644 index 0000000..00d2a45 --- /dev/null +++ b/src/routes/docs/benchmarks/benchmarks_cross_runtime.ts @@ -0,0 +1,5 @@ +import type {CrossRuntimeReport} from './benchmark_data.ts'; + +import json from './benchmarks_cross_runtime.json' with {type: 'json'}; + +export const benchmarks_cross_runtime_json: CrossRuntimeReport = json as CrossRuntimeReport; diff --git a/src/routes/docs/introduction/+page.svelte b/src/routes/docs/introduction/+page.svelte index d1414e1..eacd802 100644 --- a/src/routes/docs/introduction/+page.svelte +++ b/src/routes/docs/introduction/+page.svelte @@ -69,11 +69,12 @@ const ast: Root = parse_svelte('

    @@ -32,9 +19,9 @@ - Svelte
    {count_label('svelte')} files - TypeScript
    {count_label('typescript')} files - CSS
    {count_label('css')} files + Svelte + TypeScript + CSS @@ -58,10 +45,6 @@ padding: var(--space_xs) var(--space_sm); font-size: var(--font_size_sm); } - thead th small { - font-weight: 400; - opacity: 0.7; - } tbody td { padding: var(--space_xs) var(--space_sm); } From 9f5a331834c694171e231aed70a46f334e09c172 Mon Sep 17 00:00:00 2001 From: Ryan Atkinson Date: Fri, 3 Jul 2026 18:32:50 -0400 Subject: [PATCH 005/218] fairer size groups --- package-lock.json | 8 +- package.json | 2 +- src/routes/docs/benchmarks/+page.svelte | 27 +++-- .../docs/benchmarks/BenchmarksBar.svelte | 60 ++++++++-- .../docs/benchmarks/BenchmarksGroup.svelte | 7 +- .../docs/benchmarks/BenchmarksSizes.svelte | 60 ++-------- src/routes/docs/benchmarks/benchmark_data.ts | 107 ++++++++++++++++++ src/routes/docs/playground/Playground.svelte | 19 +++- src/test/benchmark_data.test.ts | 64 +++++++++++ 9 files changed, 278 insertions(+), 76 deletions(-) diff --git a/package-lock.json b/package-lock.json index 07542a8..a468070 100644 --- a/package-lock.json +++ b/package-lock.json @@ -31,7 +31,7 @@ "magic-string": "^0.30.21", "svelte": "^5.56.0", "svelte-check": "^4.3.6", - "svelte-docinfo": "^0.5.3", + "svelte-docinfo": "^0.5.4", "svelte2tsx": "^0.7.47", "tslib": "^2.8.1", "typescript": "^5.9.3", @@ -4162,9 +4162,9 @@ } }, "node_modules/svelte-docinfo": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/svelte-docinfo/-/svelte-docinfo-0.5.3.tgz", - "integrity": "sha512-qZMyZoorups/oNzJtyba8nRdKDbJEBhC2AXKLccozpaZzahYzLaU4V5lmFOUO6uMyzC5yuzPS8jCXd99Wss0sw==", + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/svelte-docinfo/-/svelte-docinfo-0.5.4.tgz", + "integrity": "sha512-9XONWxu//kRmThbJBpDuNu3jSP6lSPgMy4T9G2GYHWWrHDiowJFn8ov5acvhBvAogBinBATylXk1TsvyQlI0iQ==", "dev": true, "license": "MIT", "dependencies": { diff --git a/package.json b/package.json index d6196fa..2c6065f 100644 --- a/package.json +++ b/package.json @@ -45,7 +45,7 @@ "magic-string": "^0.30.21", "svelte": "^5.56.0", "svelte-check": "^4.3.6", - "svelte-docinfo": "^0.5.3", + "svelte-docinfo": "^0.5.4", "svelte2tsx": "^0.7.47", "tslib": "^2.8.1", "typescript": "^5.9.3", diff --git a/src/routes/docs/benchmarks/+page.svelte b/src/routes/docs/benchmarks/+page.svelte index 6c627ac..2f36f5e 100644 --- a/src/routes/docs/benchmarks/+page.svelte +++ b/src/routes/docs/benchmarks/+page.svelte @@ -61,7 +61,8 @@

    Rather than supporting many languages, tsv focuses on Svelte/HTML, TypeScript/JS, and CSS. This lets it be smaller when it's all you need, a quality that's more relevant when used in - the browser via wasm: + the browser via wasm. The builds below are grouped by capability — full toolchain, formatter, + and parser — so each sits beside its closest competitor:

    @@ -175,7 +180,7 @@

    The same benchmark harness runs under three JS runtimes - Node, Deno, and Bun. The headline - numbers above are the Node run. The native row differs by runtime: Node and Bun load tsv's + numbers above are the Node run. The native entry differs by runtime: Node and Bun load tsv's N-API addon, while Deno loads its C-FFI library. They share code but have a different binding boundary. A per-runtime delta on the same implementation is a runtime or binding-boundary effect, not an engine difference. @@ -184,9 +189,9 @@

    Reading the tables:

    • - tsv's native rows are faster under Node/Bun (N-API) than Deno (FFI), which pays a per-call - marshalling cost - so the Node headline reflects tsv's real native speed better than the - Deno-FFI numbers do. + tsv's native entries are faster under Node/Bun (N-API) than Deno (FFI), which pays a + per-call marshalling cost - so the Node headline reflects tsv's real native speed better + than the Deno-FFI numbers do.
    • tsv's own paths - native (N-API/FFI) and wasm - run on all three runtimes. Bun currently diff --git a/src/routes/docs/benchmarks/BenchmarksBar.svelte b/src/routes/docs/benchmarks/BenchmarksBar.svelte index 128c7b5..ee75578 100644 --- a/src/routes/docs/benchmarks/BenchmarksBar.svelte +++ b/src/routes/docs/benchmarks/BenchmarksBar.svelte @@ -14,6 +14,8 @@ ratio_text, ratio_color, annotation, + badge, + disabled = false, }: { label: string; bar_fraction: number; @@ -24,23 +26,46 @@ // optional extra context shown between value and ratio (corpus coverage in // benchmark groups, gzipped size in binary-size groups); omitted when absent annotation?: string | undefined; + // optional leading tag (the wasm/native kind in binary-size groups); omitted when absent + badge?: string | undefined; + // a grayed-out, inert placeholder (a tool that doesn't run in this group) — + // no bar, no value, no ratio, just the label held in its shared slot + disabled?: boolean; } = $props(); -
      +
      + {#if badge != null} + {badge} + {/if} {format_label(label)}
      -
      + {#if !disabled} +
      + {/if}
      - {value.value} {value.unit} + + {#if disabled} + — + {:else} + {value.value} {value.unit} + {/if} + {#if annotation != null} {annotation} {/if} - {ratio_text} + {#if !disabled}{ratio_text}{/if}
      diff --git a/src/routes/docs/benchmarks/benchmark_data.ts b/src/routes/docs/benchmarks/benchmark_data.ts index cd3b75b..d07d70f 100644 --- a/src/routes/docs/benchmarks/benchmark_data.ts +++ b/src/routes/docs/benchmarks/benchmark_data.ts @@ -11,6 +11,19 @@ export interface BenchmarkBaseline { // Counts of silenced third-party stderr noise, keyed by message pattern. // Present from baseline `version` 4 on; not rendered, kept for parity. suppressed_noise?: Record; + // Which corpus/surface produced the report: `perf` (real-world corpus, + // format + parse) or `conformance` (full fixtures-included corpus, parse + // only). Present from `version` 6 on. + corpus_kind?: 'perf' | 'conformance'; + // Per-entry corpus composition (path + loaded file count) — discloses which + // sources were present on the machine that produced the report. Present + // from `version` 6 on. + corpus_sources?: Array; +} + +export interface CorpusSource { + path: string; + files: number; } export interface BaselineEntry { @@ -243,6 +256,83 @@ export const derive_benchmark_groups = (baseline: BenchmarkBaseline): Array; +} + +/** + * One coverage row per ENGINE, not per binding: the conformance headline is + * "which files does this parser accept," which is identical across a tool's + * native/wasm/internal variants — so the `-wasm` and `-internal` duplicates + * are dropped and `tsv-json` stands in for tsv (relabeled plainly, since the + * JSON-materialization qualifier is a speed concern, not a coverage one). + */ +const CONFORMANCE_ENGINE_NAMES: Record = { + 'svelte/compiler': 'svelte/compiler', + 'acorn-typescript': 'acorn-typescript', + 'tsv-json': 'tsv', + 'oxc-parser': 'oxc-parser', +}; + +/** + * Derives per-language parse-coverage groups from a conformance report + * (`corpus_kind: 'conformance'` — parse groups only). Rows sort by coverage + * descending; entries without coverage data are dropped. + */ +export const derive_conformance_groups = (baseline: BenchmarkBaseline): Array => { + const by_language: Map> = new Map(); + for (const entry of baseline.entries) { + const [operation, language] = entry.group.split('/'); + if (operation !== 'parse' || !language) continue; + const display_name = CONFORMANCE_ENGINE_NAMES[entry.name]; + if (!display_name) continue; + if (entry.files_processed == null || entry.files_total == null) continue; + let rows = by_language.get(language); + if (!rows) { + rows = []; + by_language.set(language, rows); + } + rows.push({ + name: display_name, + category: categorize_name(entry.name), + files_processed: entry.files_processed, + files_total: entry.files_total, + coverage_fraction: entry.files_total > 0 ? entry.files_processed / entry.files_total : 0, + }); + } + + const result: Array = []; + for (const [language, rows] of by_language) { + rows.sort((a, b) => b.coverage_fraction - a.coverage_fraction || a.name.localeCompare(b.name)); + result.push({ + language, + files_total: Math.max(0, ...rows.map((r) => r.files_total)), + rows, + }); + } + const LANG_ORDER: Record = {svelte: 0, typescript: 1, css: 2}; + result.sort((a, b) => (LANG_ORDER[a.language] ?? 9) - (LANG_ORDER[b.language] ?? 9)); + return result; +}; + +/** Formats a coverage fraction as a percentage with one decimal (`97.4%`). */ +export const format_coverage_percent = (fraction: number): string => + `${(fraction * 100).toFixed(1)}%`; + export const derive_speedup_summary = (groups: Array): Array => { const find_speedup = ( operation: string, diff --git a/src/routes/docs/benchmarks/benchmarks_conformance.json b/src/routes/docs/benchmarks/benchmarks_conformance.json new file mode 100644 index 0000000..0d27972 --- /dev/null +++ b/src/routes/docs/benchmarks/benchmarks_conformance.json @@ -0,0 +1,544 @@ +{ + "version": 6, + "runtime": "node", + "corpus_kind": "conformance", + "timestamp": "2026-07-04T22:58:25.136Z", + "git_commit": "34a14e63", + "corpus": { + "svelte": 50, + "typescript": 50, + "css": 50 + }, + "corpus_sources": [ + { + "path": "../zzz/src", + "files": 325 + }, + { + "path": "../fuz_app/src", + "files": 664 + }, + { + "path": "../fuz_blog/src", + "files": 32 + }, + { + "path": "../fuz_code/src", + "files": 68 + }, + { + "path": "../fuz_css/src", + "files": 124 + }, + { + "path": "../fuz_docs/src", + "files": 64 + }, + { + "path": "../fuz_gitops/src", + "files": 203 + }, + { + "path": "../fuz_mastodon/src", + "files": 24 + }, + { + "path": "../fuz_template/src", + "files": 15 + }, + { + "path": "../fuz_ui/src", + "files": 215 + }, + { + "path": "../fuz_util/src", + "files": 144 + }, + { + "path": "../gro/src", + "files": 187 + }, + { + "path": "../svelte-docinfo/src", + "files": 297 + }, + { + "path": "../tsv.fuz.dev/src", + "files": 26 + }, + { + "path": "../kit/packages/kit/src", + "files": 381 + }, + { + "path": "../svelte/packages/svelte/src", + "files": 380 + }, + { + "path": "../svelte.dev/apps/svelte.dev/src", + "files": 138 + }, + { + "path": "../svelte.dev/packages/repl/src", + "files": 48 + }, + { + "path": "../svelte.dev/packages/site-kit/src", + "files": 65 + }, + { + "path": "../prettier-plugin-svelte/test", + "files": 325 + }, + { + "path": "../prettier/tests/format/typescript", + "files": 789 + }, + { + "path": "../prettier/tests/format/js", + "files": 1103 + }, + { + "path": "../prettier/tests/format/css", + "files": 228 + }, + { + "path": "../prettier/tests/format/html", + "files": 124 + }, + { + "path": "../svelte/packages/svelte/tests", + "files": 4543 + }, + { + "path": "benches/js/.cache/wpt_css", + "files": 22310 + }, + { + "path": "benches/js/.cache/test262_files.json", + "files": 42113 + } + ], + "versions": { + "tsv": "0.1.0", + "svelte": "5.56.1", + "acorn": "8.16.0", + "acorn_ts": "1.0.10", + "prettier": "3.9.0", + "prettier_svelte": "4.1.1", + "oxc_parser": "0.134.0", + "oxfmt": "0.53.0", + "biome": "2.4.16" + }, + "binary_sizes": [ + { + "label": "tsv (ffi)", + "bytes": 3324480, + "kind": "native", + "gzip_bytes": 1423272 + }, + { + "label": "tsv format (ffi)", + "bytes": 3070736, + "kind": "native", + "gzip_bytes": 1317789 + }, + { + "label": "tsv parse (ffi)", + "bytes": 1545168, + "kind": "native", + "gzip_bytes": 683595 + }, + { + "label": "tsv (napi)", + "bytes": 3447328, + "kind": "native", + "gzip_bytes": 1464803 + }, + { + "label": "tsv_format_wasm", + "bytes": 2312689, + "kind": "wasm", + "gzip_bytes": 784944 + }, + { + "label": "tsv_parse_wasm", + "bytes": 1126329, + "kind": "wasm", + "gzip_bytes": 401394 + }, + { + "label": "tsv_wasm", + "bytes": 2540357, + "kind": "wasm", + "gzip_bytes": 866096 + }, + { + "label": "biome (wasm)", + "bytes": 34430368, + "kind": "wasm", + "gzip_bytes": 8187702 + }, + { + "label": "oxc-parser (napi)", + "bytes": 2658008, + "kind": "native", + "gzip_bytes": 1032774 + }, + { + "label": "oxfmt (napi)", + "bytes": 8016464, + "kind": "native", + "gzip_bytes": 3224684 + }, + { + "label": "oxc-parser (wasm)", + "bytes": 1866798, + "kind": "wasm", + "gzip_bytes": 518682 + } + ], + "entries": [ + { + "name": "svelte/compiler", + "group": "parse/svelte", + "mean_ns": 42592126.652173914, + "p50_ns": 42372503, + "p75_ns": 45104994.75, + "p90_ns": 45953787, + "p95_ns": 46785490.85, + "p99_ns": 52088600.62, + "min_ns": 38997284, + "max_ns": 53632500, + "std_dev_ns": 2420666.899346065, + "cv": 0.05683367067144353, + "ops_per_second": 23.478517712121796, + "sample_size": 23, + "files_processed": 50, + "files_total": 50, + "files_iterated": 50, + "runtime": "node" + }, + { + "name": "tsv-json", + "group": "parse/svelte", + "mean_ns": 17520284.375, + "p50_ns": 17484422, + "p75_ns": 17756645, + "p90_ns": 18229084.4, + "p95_ns": 18622561.6, + "p99_ns": 18941451.279999997, + "min_ns": 16824456, + "max_ns": 19231608, + "std_dev_ns": 459761.35622087336, + "cv": 0.026241660602091304, + "ops_per_second": 57.07669913320114, + "sample_size": 56, + "files_processed": 50, + "files_total": 50, + "files_iterated": 50, + "runtime": "node" + }, + { + "name": "tsv_wasm-json", + "group": "parse/svelte", + "mean_ns": 19937617.36734694, + "p50_ns": 19894594, + "p75_ns": 20359697.25, + "p90_ns": 20799981.7, + "p95_ns": 21010359.85, + "p99_ns": 21736769.689999998, + "min_ns": 19127492, + "max_ns": 22395829, + "std_dev_ns": 538124.008094583, + "cv": 0.026990386974518922, + "ops_per_second": 50.156444552786006, + "sample_size": 49, + "files_processed": 50, + "files_total": 50, + "files_iterated": 50, + "runtime": "node" + }, + { + "name": "tsv-internal", + "group": "parse/svelte", + "mean_ns": 1561040.194221509, + "p50_ns": 1558470, + "p75_ns": 1599678, + "p90_ns": 1641439.2, + "p95_ns": 1705062.7999999998, + "p99_ns": 1859773.76, + "min_ns": 1453612, + "max_ns": 2576662, + "std_dev_ns": 60498.44548723698, + "cv": 0.03875521316567224, + "ops_per_second": 640.5984956067708, + "sample_size": 623, + "files_processed": 50, + "files_total": 50, + "files_iterated": 50, + "runtime": "node" + }, + { + "name": "tsv_wasm-internal", + "group": "parse/svelte", + "mean_ns": 2351937.689903846, + "p50_ns": 2351807.5, + "p75_ns": 2400101.25, + "p90_ns": 2463373.7, + "p95_ns": 2530434.9499999997, + "p99_ns": 2663788.4799999995, + "min_ns": 2207946, + "max_ns": 2793461, + "std_dev_ns": 81268.77684799174, + "cv": 0.03455396679803802, + "ops_per_second": 425.1813320959548, + "sample_size": 416, + "files_processed": 50, + "files_total": 50, + "files_iterated": 50, + "runtime": "node" + }, + { + "name": "acorn-typescript", + "group": "parse/typescript", + "mean_ns": 49106025.84210526, + "p50_ns": 49163618, + "p75_ns": 49871864, + "p90_ns": 51325036, + "p95_ns": 53582887, + "p99_ns": 54569459.800000004, + "min_ns": 47755199, + "max_ns": 54816103, + "std_dev_ns": 979671.3320026867, + "cv": 0.01995012455605156, + "ops_per_second": 20.364099575383765, + "sample_size": 19, + "files_processed": 50, + "files_total": 50, + "files_iterated": 50, + "runtime": "node" + }, + { + "name": "tsv-json", + "group": "parse/typescript", + "mean_ns": 31513656.464285713, + "p50_ns": 31588069, + "p75_ns": 31932624.25, + "p90_ns": 34192304.7, + "p95_ns": 34608299.95, + "p99_ns": 35685192.4, + "min_ns": 30599438, + "max_ns": 36043261, + "std_dev_ns": 521142.4047038912, + "cv": 0.01653703388226306, + "ops_per_second": 31.732274581760944, + "sample_size": 28, + "files_processed": 50, + "files_total": 50, + "files_iterated": 50, + "runtime": "node" + }, + { + "name": "tsv_wasm-json", + "group": "parse/typescript", + "mean_ns": 34645150.2962963, + "p50_ns": 34680689, + "p75_ns": 35207563, + "p90_ns": 36540927.8, + "p95_ns": 38035464.4, + "p99_ns": 39149145.36, + "min_ns": 33500061, + "max_ns": 39240163, + "std_dev_ns": 762383.5100824264, + "cv": 0.022005490048745094, + "ops_per_second": 28.86406874981587, + "sample_size": 27, + "files_processed": 50, + "files_total": 50, + "files_iterated": 50, + "runtime": "node" + }, + { + "name": "tsv-internal", + "group": "parse/typescript", + "mean_ns": 2162101.937360179, + "p50_ns": 2168251, + "p75_ns": 2197687, + "p90_ns": 2237192, + "p95_ns": 2292356, + "p99_ns": 2471238.999999999, + "min_ns": 2049307, + "max_ns": 2664057, + "std_dev_ns": 56058.794264350276, + "cv": 0.025927914542639617, + "ops_per_second": 462.5128828203869, + "sample_size": 447, + "files_processed": 50, + "files_total": 50, + "files_iterated": 50, + "runtime": "node" + }, + { + "name": "tsv_wasm-internal", + "group": "parse/typescript", + "mean_ns": 3276734.684931507, + "p50_ns": 3273948, + "p75_ns": 3346114, + "p90_ns": 3449610.6, + "p95_ns": 3578550.349999999, + "p99_ns": 3893452.9999999986, + "min_ns": 3098076, + "max_ns": 4042888, + "std_dev_ns": 103174.0229134631, + "cv": 0.031486840661199195, + "ops_per_second": 305.1818643110261, + "sample_size": 292, + "files_processed": 50, + "files_total": 50, + "files_iterated": 50, + "runtime": "node" + }, + { + "name": "oxc-parser", + "group": "parse/typescript", + "mean_ns": 17757639.431818184, + "p50_ns": 17790378.5, + "p75_ns": 18193898, + "p90_ns": 36024234.7, + "p95_ns": 37406521.9, + "p99_ns": 42044068.58999999, + "min_ns": 16896211, + "max_ns": 45152388, + "std_dev_ns": 470654.8101898134, + "cv": 0.026504356730348566, + "ops_per_second": 56.313791246836416, + "sample_size": 44, + "files_processed": 50, + "files_total": 50, + "files_iterated": 50, + "runtime": "node" + }, + { + "name": "oxc-parser-wasm", + "group": "parse/typescript", + "mean_ns": 22603262.589743588, + "p50_ns": 22243320, + "p75_ns": 23859140.5, + "p90_ns": 25405074.8, + "p95_ns": 27667718.099999998, + "p99_ns": 34038511.29999999, + "min_ns": 21268100, + "max_ns": 36715228, + "std_dev_ns": 1210693.4068062142, + "cv": 0.05356277227675867, + "ops_per_second": 44.24140081678996, + "sample_size": 39, + "files_processed": 50, + "files_total": 50, + "files_iterated": 50, + "runtime": "node" + }, + { + "name": "svelte/compiler", + "group": "parse/css", + "mean_ns": 3965116.419213974, + "p50_ns": 3948034, + "p75_ns": 4097113.25, + "p90_ns": 4408711.2, + "p95_ns": 4583902.6, + "p99_ns": 5021958.08, + "min_ns": 3734547, + "max_ns": 6578933, + "std_dev_ns": 165867.08268332237, + "cv": 0.04183157949148012, + "ops_per_second": 252.199404575928, + "sample_size": 229, + "files_processed": 48, + "files_total": 50, + "files_iterated": 48, + "runtime": "node" + }, + { + "name": "tsv-json", + "group": "parse/css", + "mean_ns": 6552144.952380952, + "p50_ns": 6536829.5, + "p75_ns": 6652212.25, + "p90_ns": 6797909.7, + "p95_ns": 6915894.9, + "p99_ns": 8203895.45, + "min_ns": 6259591, + "max_ns": 8306503, + "std_dev_ns": 152812.986907506, + "cv": 0.023322589475371122, + "ops_per_second": 152.62177611571533, + "sample_size": 147, + "files_processed": 48, + "files_total": 50, + "files_iterated": 48, + "runtime": "node" + }, + { + "name": "tsv_wasm-json", + "group": "parse/css", + "mean_ns": 8055132.974789916, + "p50_ns": 8046998.5, + "p75_ns": 8244085.25, + "p90_ns": 8485059.8, + "p95_ns": 9021225, + "p99_ns": 9823383.929999998, + "min_ns": 7526642, + "max_ns": 10726119, + "std_dev_ns": 288354.58832505083, + "cv": 0.03579761988132435, + "ops_per_second": 124.14444344118115, + "sample_size": 119, + "files_processed": 48, + "files_total": 50, + "files_iterated": 48, + "runtime": "node" + }, + { + "name": "tsv-internal", + "group": "parse/css", + "mean_ns": 2505575.1297709923, + "p50_ns": 2513632, + "p75_ns": 2551819.5, + "p90_ns": 2572908.4, + "p95_ns": 2603319.3, + "p99_ns": 2775517.0599999996, + "min_ns": 2376735, + "max_ns": 3187926, + "std_dev_ns": 61166.80711833826, + "cv": 0.024412282190847283, + "ops_per_second": 399.10996406298113, + "sample_size": 393, + "files_processed": 48, + "files_total": 50, + "files_iterated": 48, + "runtime": "node" + }, + { + "name": "tsv_wasm-internal", + "group": "parse/css", + "mean_ns": 3581292.0037037036, + "p50_ns": 3572496, + "p75_ns": 3635640.25, + "p90_ns": 3718303.7, + "p95_ns": 3817991.65, + "p99_ns": 4150013.95, + "min_ns": 3421496, + "max_ns": 5141341, + "std_dev_ns": 91275.83305976799, + "cv": 0.025486844682134902, + "ops_per_second": 279.2288366784443, + "sample_size": 270, + "files_processed": 48, + "files_total": 50, + "files_iterated": 48, + "runtime": "node" + } + ], + "suppressed_noise": {} +} diff --git a/src/routes/docs/benchmarks/benchmarks_conformance.ts b/src/routes/docs/benchmarks/benchmarks_conformance.ts new file mode 100644 index 0000000..6aee0cd --- /dev/null +++ b/src/routes/docs/benchmarks/benchmarks_conformance.ts @@ -0,0 +1,5 @@ +import type {BenchmarkBaseline} from './benchmark_data.ts'; + +import json from './benchmarks_conformance.json' with {type: 'json'}; + +export const benchmarks_conformance_json: BenchmarkBaseline = json as BenchmarkBaseline; diff --git a/src/test/benchmark_data.test.ts b/src/test/benchmark_data.test.ts index daeed16..318fbc2 100644 --- a/src/test/benchmark_data.test.ts +++ b/src/test/benchmark_data.test.ts @@ -1,11 +1,13 @@ import {assert, describe, test} from 'vitest'; import {benchmarks_json} from '$routes/docs/benchmarks/benchmarks.ts'; +import {benchmarks_conformance_json} from '$routes/docs/benchmarks/benchmarks_conformance.ts'; import {benchmarks_cross_runtime_json} from '$routes/docs/benchmarks/benchmarks_cross_runtime.ts'; import { categorize_size_capability, compute_baseline_ratio, derive_benchmark_groups, + derive_conformance_groups, derive_cross_runtime_groups, derive_size_groups, derive_speedup_summary, @@ -201,6 +203,49 @@ describe('benchmarks.json shape', () => { }); }); +// Shape gate for the committed conformance report `benchmarks_conformance.json` +// (tsv's `report.conformance.node.json` — the parse-coverage surface over the +// full fixtures-included corpus), consumed by the Parse conformance section. +describe('benchmarks_conformance.json shape', () => { + test('report is the conformance surface at the current version', () => { + assert.isAtLeast(benchmarks_conformance_json.version, 6); + assert.strictEqual(benchmarks_conformance_json.corpus_kind, 'conformance'); + assert.strictEqual((benchmarks_conformance_json as {runtime?: string}).runtime, 'node'); + }); + + test('conformance report is parse-only', () => { + for (const entry of benchmarks_conformance_json.entries) { + assert.match(entry.group, /^parse\//, `${entry.group}/${entry.name}`); + } + }); + + test('corpus sources disclose the composition', () => { + assert.isNotEmpty(benchmarks_conformance_json.corpus_sources ?? []); + }); + + test('derives one coverage group per language, each with a tsv row and full coverage data', () => { + const groups = derive_conformance_groups(benchmarks_conformance_json); + assert.strictEqual(groups.length, 3); // svelte / typescript / css + assert.deepEqual( + groups.map((g) => g.language), + ['svelte', 'typescript', 'css'], + ); + for (const group of groups) { + assert.ok( + group.rows.some((r) => r.name === 'tsv'), + `${group.language} has a tsv row`, + ); + for (const row of group.rows) { + assert.isAbove(row.files_total, 0, `${group.language}/${row.name} total`); + assert.isAtLeast(row.coverage_fraction, 0); + assert.isAtMost(row.coverage_fraction, 1); + // engine-level rows only — binding/materialization variants are folded + assert.notMatch(row.name, /-internal|wasm-|-wasm/, `${group.language}/${row.name}`); + } + } + }); +}); + describe('format_speedup_signed', () => { test('anchor-and-faster entries read as a plain multiple', () => { assert.strictEqual(format_speedup_signed(1), '1.00x'); From e8be447a9c3f026f54f54128d1be62ab5498cd6f Mon Sep 17 00:00:00 2001 From: Ryan Atkinson Date: Sun, 5 Jul 2026 10:40:48 -0400 Subject: [PATCH 017/218] wip --- src/routes/docs/benchmarks/+page.svelte | 3 ++- src/routes/docs/benchmarks/benchmark_data.ts | 20 ++++++++++++++++++++ src/routes/docs/playground/Playground.svelte | 5 +++++ 3 files changed, 27 insertions(+), 1 deletion(-) diff --git a/src/routes/docs/benchmarks/+page.svelte b/src/routes/docs/benchmarks/+page.svelte index f1b3ccc..54da1c5 100644 --- a/src/routes/docs/benchmarks/+page.svelte +++ b/src/routes/docs/benchmarks/+page.svelte @@ -12,6 +12,7 @@ derive_benchmark_groups, derive_conformance_groups, derive_speedup_summary, + format_corpus_source_files, } from './benchmark_data.ts'; import BenchmarksSummary from './BenchmarksSummary.svelte'; import BenchmarksGroup from './BenchmarksGroup.svelte'; @@ -188,7 +189,7 @@ Corpus sources ({benchmarks_conformance_json.corpus_sources.length})
        {#each benchmarks_conformance_json.corpus_sources as source (source.path)} -
      • {source.path} - {source.files.toLocaleString('en-US')} files
      • +
      • {source.path} - {format_corpus_source_files(source)}
      • {/each}
      diff --git a/src/routes/docs/benchmarks/benchmark_data.ts b/src/routes/docs/benchmarks/benchmark_data.ts index d07d70f..8f17b27 100644 --- a/src/routes/docs/benchmarks/benchmark_data.ts +++ b/src/routes/docs/benchmarks/benchmark_data.ts @@ -24,6 +24,10 @@ export interface BenchmarkBaseline { export interface CorpusSource { path: string; files: number; + // Per-language split of `files` (svelte/typescript/css counts summing to + // `files`). Present on reports whose loader emitted it; older reports carry + // only the `files` total, so treat it as optional. + by_language?: Partial>; } export interface BaselineEntry { @@ -607,6 +611,22 @@ export const format_coverage = ( return `${processed}/${total}`; }; +/** + * Formats a corpus source's file count as a per-language breakdown + * (`124 typescript, 15 svelte, 31 css`), largest language first and dropping + * zero-count languages. Falls back to the plain `N files` total when the report + * predates the per-language split (or lists no recognized language). + */ +export const format_corpus_source_files = (source: CorpusSource): string => { + const total = `${source.files.toLocaleString('en-US')} files`; + if (!source.by_language) return total; + const parts = Object.entries(source.by_language) + .filter((entry): entry is [string, number] => (entry[1] ?? 0) > 0) + .sort((a, b) => b[1] - a[1]) + .map(([language, count]) => `${count.toLocaleString('en-US')} ${language}`); + return parts.length > 0 ? parts.join(', ') : total; +}; + /** * Formats a gzipped binary size as a bar annotation (e.g. `716.6 KB gz`), or * `undefined` when the baseline lacks it (older runs, or no `gzip` available diff --git a/src/routes/docs/playground/Playground.svelte b/src/routes/docs/playground/Playground.svelte index 749c733..ff3e970 100644 --- a/src/routes/docs/playground/Playground.svelte +++ b/src/routes/docs/playground/Playground.svelte @@ -142,6 +142,7 @@ position: relative; } .ast_output :global(.ast_copy) { + --font_size: var(--font_size_lg); position: absolute; top: var(--space_xs); /* clear the pane's scrollbar */ @@ -149,6 +150,10 @@ z-index: 1; background: var(--shade_00); } + /* TODO hacky */ + .ast_output :global(.ast_copy > div) { + width: auto !important; + } .error { color: var(--color_e_40); white-space: pre-wrap; From ca8829385932070c9262352a13187d171f314d8e Mon Sep 17 00:00:00 2001 From: Ryan Atkinson Date: Sun, 5 Jul 2026 11:08:30 -0400 Subject: [PATCH 018/218] wip --- src/routes/docs/benchmarks/benchmarks.json | 844 +++++++++--------- .../benchmarks/benchmarks_conformance.json | 737 ++++++++------- .../benchmarks/benchmarks_cross_runtime.json | 440 ++++----- 3 files changed, 1078 insertions(+), 943 deletions(-) diff --git a/src/routes/docs/benchmarks/benchmarks.json b/src/routes/docs/benchmarks/benchmarks.json index 327ca08..76e3290 100644 --- a/src/routes/docs/benchmarks/benchmarks.json +++ b/src/routes/docs/benchmarks/benchmarks.json @@ -1,10 +1,10 @@ { "version": 5, "runtime": "node", - "timestamp": "2026-07-03T21:04:21.052Z", - "git_commit": "2136c09e", + "timestamp": "2026-07-04T17:07:43.168Z", + "git_commit": "ad1c91b6", "corpus": { - "svelte": 1263, + "svelte": 1264, "typescript": 4523, "css": 182 }, @@ -22,45 +22,45 @@ "binary_sizes": [ { "label": "tsv (ffi)", - "bytes": 3375312, + "bytes": 3469872, "kind": "native", - "gzip_bytes": 1446358 + "gzip_bytes": 1465913 }, { "label": "tsv format (ffi)", - "bytes": 3033808, + "bytes": 3218032, "kind": "native", - "gzip_bytes": 1295889 + "gzip_bytes": 1362251 }, { "label": "tsv parse (ffi)", - "bytes": 1645856, + "bytes": 1540064, "kind": "native", - "gzip_bytes": 730714 + "gzip_bytes": 681068 }, { "label": "tsv (napi)", - "bytes": 3503920, + "bytes": 3593008, "kind": "native", - "gzip_bytes": 1490448 + "gzip_bytes": 1507737 }, { "label": "tsv_format_wasm", - "bytes": 2315079, + "bytes": 2388313, "kind": "wasm", - "gzip_bytes": 778502 + "gzip_bytes": 802695 }, { "label": "tsv_parse_wasm", - "bytes": 1225460, + "bytes": 1121318, "kind": "wasm", - "gzip_bytes": 436648 + "gzip_bytes": 399755 }, { "label": "tsv_wasm", - "bytes": 2632957, + "bytes": 2614246, "kind": "wasm", - "gzip_bytes": 894314 + "gzip_bytes": 883671 }, { "label": "biome (wasm)", @@ -91,218 +91,218 @@ { "name": "svelte/compiler", "group": "parse/svelte", - "mean_ns": 448679708.8333333, - "p50_ns": 448153295, - "p75_ns": 451278111, - "p90_ns": 452145270.6, - "p95_ns": 455316712.35, - "p99_ns": 458411735.27, - "min_ns": 442696237, - "max_ns": 459185491, - "std_dev_ns": 4671090.721367097, - "cv": 0.010410746528994968, - "ops_per_second": 2.2287613643153636, + "mean_ns": 453024589.9166667, + "p50_ns": 454046264, + "p75_ns": 455774769.75, + "p90_ns": 457913268.3, + "p95_ns": 459773935.3, + "p99_ns": 461586468.66, + "min_ns": 441527976, + "max_ns": 462039602, + "std_dev_ns": 5691705.876851324, + "cv": 0.01256379014193977, + "ops_per_second": 2.2073856966217855, "sample_size": 12, - "files_processed": 1216, - "files_total": 1263, - "files_iterated": 1215, + "files_processed": 1217, + "files_total": 1264, + "files_iterated": 1216, "runtime": "node" }, { "name": "tsv-json", "group": "parse/svelte", - "mean_ns": 339756877.46666664, - "p50_ns": 339603958, - "p75_ns": 340916886, - "p90_ns": 341348227.6, - "p95_ns": 341437796.3, - "p99_ns": 341437998.46, - "min_ns": 337407455, - "max_ns": 341438049, - "std_dev_ns": 1298355.6248491986, - "cv": 0.003821425586820033, - "ops_per_second": 2.9432811116475763, - "sample_size": 15, - "files_processed": 1225, - "files_total": 1263, - "files_iterated": 1215, + "mean_ns": 220965435.52380952, + "p50_ns": 220590997, + "p75_ns": 223249600, + "p90_ns": 227113833.2, + "p95_ns": 235643324.5, + "p99_ns": 240547375.92000002, + "min_ns": 216194563, + "max_ns": 241688079, + "std_dev_ns": 2549987.299988171, + "cv": 0.011540208965005317, + "ops_per_second": 4.525594682396595, + "sample_size": 21, + "files_processed": 1226, + "files_total": 1264, + "files_iterated": 1216, "runtime": "node" }, { "name": "tsv_wasm-json", "group": "parse/svelte", - "mean_ns": 383854889.15384614, - "p50_ns": 383697400.5, - "p75_ns": 384613576.75, - "p90_ns": 385657087.9, - "p95_ns": 386475969.95, - "p99_ns": 387230488.39, - "min_ns": 382604353, - "max_ns": 387419118, - "std_dev_ns": 942640.0196518857, - "cv": 0.0024557197167132676, - "ops_per_second": 2.605151134597657, - "sample_size": 13, - "files_processed": 1225, - "files_total": 1263, - "files_iterated": 1215, + "mean_ns": 246915268.14285713, + "p50_ns": 246819188, + "p75_ns": 248305457, + "p90_ns": 248854284, + "p95_ns": 249335093, + "p99_ns": 249511226.6, + "min_ns": 242488430, + "max_ns": 249555260, + "std_dev_ns": 1731382.3239353953, + "cv": 0.007012050477711544, + "ops_per_second": 4.049972314476044, + "sample_size": 21, + "files_processed": 1226, + "files_total": 1264, + "files_iterated": 1216, "runtime": "node" }, { "name": "tsv-internal", "group": "parse/svelte", - "mean_ns": 22741839.841836736, - "p50_ns": 22713045.5, - "p75_ns": 22923383.5, - "p90_ns": 23325634.8, - "p95_ns": 23630612.1, - "p99_ns": 23971527.74, - "min_ns": 22071325, - "max_ns": 24174613, - "std_dev_ns": 207882.44389812456, - "cv": 0.009140968599897369, - "ops_per_second": 43.971816130740784, - "sample_size": 196, - "files_processed": 1225, - "files_total": 1263, - "files_iterated": 1215, + "mean_ns": 22998296.396313366, + "p50_ns": 22924819.5, + "p75_ns": 23297533.25, + "p90_ns": 23733034.3, + "p95_ns": 23945571.849999998, + "p99_ns": 24559876.52, + "min_ns": 21679532, + "max_ns": 26744002, + "std_dev_ns": 538473.53120547, + "cv": 0.02341362690202512, + "ops_per_second": 43.4814815309668, + "sample_size": 217, + "files_processed": 1226, + "files_total": 1264, + "files_iterated": 1216, "runtime": "node" }, { "name": "tsv_wasm-internal", "group": "parse/svelte", - "mean_ns": 50428132.225, - "p50_ns": 49681466, - "p75_ns": 50562218, - "p90_ns": 53144950.4, - "p95_ns": 54144681.89999999, - "p99_ns": 55804490.919999994, - "min_ns": 46919760, - "max_ns": 71071210, - "std_dev_ns": 1942665.2759959653, - "cv": 0.03852344297282696, - "ops_per_second": 19.830201038146818, - "sample_size": 80, - "files_processed": 1225, - "files_total": 1263, - "files_iterated": 1215, + "mean_ns": 41790261.449152544, + "p50_ns": 46679148, + "p75_ns": 47789406.5, + "p90_ns": 48994405.6, + "p95_ns": 50412989.099999994, + "p99_ns": 58181273.99999997, + "min_ns": 31464780, + "max_ns": 73953879, + "std_dev_ns": 7885932.449488532, + "cv": 0.1887026349209033, + "ops_per_second": 23.929019951615516, + "sample_size": 118, + "files_processed": 1226, + "files_total": 1264, + "files_iterated": 1216, "runtime": "node" }, { "name": "prettier", "group": "format/svelte", - "mean_ns": 4540999248.285714, - "p50_ns": 4551154282, - "p75_ns": 4552901692, - "p90_ns": 4562191810, - "p95_ns": 4569065864.5, - "p99_ns": 4574565108.1, - "min_ns": 4515462655, - "max_ns": 4575939919, - "std_dev_ns": 23191710.815302763, - "cv": 0.005107182262595162, - "ops_per_second": 0.22021584794965843, - "sample_size": 7, - "files_processed": 1224, - "files_total": 1263, - "files_iterated": 1214, + "mean_ns": 4595102285.333333, + "p50_ns": 4592878829, + "p75_ns": 4607140474.5, + "p90_ns": 4654189636.8, + "p95_ns": 4684174688.4, + "p99_ns": 4708162729.68, + "min_ns": 4481205370, + "max_ns": 4714159740, + "std_dev_ns": 75195260.28690374, + "cv": 0.016364219035322085, + "ops_per_second": 0.21762301204737144, + "sample_size": 6, + "files_processed": 1225, + "files_total": 1264, + "files_iterated": 1215, "runtime": "node" }, { "name": "tsv", "group": "format/svelte", - "mean_ns": 85093868.19642857, - "p50_ns": 84868372, - "p75_ns": 85967166, - "p90_ns": 88468833.8, - "p95_ns": 89484810.2, - "p99_ns": 90362411.32000001, - "min_ns": 83388250, - "max_ns": 90505959, - "std_dev_ns": 1491457.2024215343, - "cv": 0.017527199480210393, - "ops_per_second": 11.751728076241932, - "sample_size": 56, - "files_processed": 1225, - "files_total": 1263, - "files_iterated": 1214, + "mean_ns": 77541154.1875, + "p50_ns": 77391841, + "p75_ns": 77922166, + "p90_ns": 78304050.6, + "p95_ns": 78749573.6, + "p99_ns": 79923906.76, + "min_ns": 76728312, + "max_ns": 81524893, + "std_dev_ns": 547300.6189677698, + "cv": 0.007058195415099937, + "ops_per_second": 12.896377549164786, + "sample_size": 64, + "files_processed": 1226, + "files_total": 1264, + "files_iterated": 1215, "runtime": "node" }, { "name": "tsv_wasm", "group": "format/svelte", - "mean_ns": 139127262.77142859, - "p50_ns": 138961636.5, - "p75_ns": 139873502.25, - "p90_ns": 141511618, - "p95_ns": 143845730.5, - "p99_ns": 147192765.95, - "min_ns": 137170608, - "max_ns": 148797846, - "std_dev_ns": 1656503.4855079728, - "cv": 0.011906390253860116, - "ops_per_second": 7.187663870329243, + "mean_ns": 138495028.25714287, + "p50_ns": 136721227.5, + "p75_ns": 142157343, + "p90_ns": 144764049, + "p95_ns": 146884290.25, + "p99_ns": 152309360.39999998, + "min_ns": 133446749, + "max_ns": 154475747, + "std_dev_ns": 4365589.040379325, + "cv": 0.03152163002034818, + "ops_per_second": 7.220475800353686, "sample_size": 35, - "files_processed": 1225, - "files_total": 1263, - "files_iterated": 1214, + "files_processed": 1226, + "files_total": 1264, + "files_iterated": 1215, "runtime": "node" }, { "name": "oxfmt", "group": "format/svelte", - "mean_ns": 4375422554.285714, - "p50_ns": 4367742730, - "p75_ns": 4390244856.5, - "p90_ns": 4420031346.2, - "p95_ns": 4436656481.6, - "p99_ns": 4449956589.92, - "min_ns": 4316632110, - "max_ns": 4453281617, - "std_dev_ns": 42921858.201548055, - "cv": 0.009809762981521914, - "ops_per_second": 0.22854935439789759, - "sample_size": 7, - "files_processed": 1221, - "files_total": 1263, - "files_iterated": 1214, + "mean_ns": 4294085590.8333335, + "p50_ns": 4292043545, + "p75_ns": 4303748468, + "p90_ns": 4319942194.2, + "p95_ns": 4328372426.1, + "p99_ns": 4335116611.62, + "min_ns": 4286959192, + "max_ns": 4336802658, + "std_dev_ns": 8279435.87860104, + "cv": 0.0019281022009145113, + "ops_per_second": 0.23287845080096192, + "sample_size": 6, + "files_processed": 1222, + "files_total": 1264, + "files_iterated": 1215, "runtime": "node" }, { "name": "biome-wasm", "group": "format/svelte", - "mean_ns": 686900111.375, - "p50_ns": 686434060.5, - "p75_ns": 688465419, - "p90_ns": 691257113.1, - "p95_ns": 693129976.05, - "p99_ns": 694628266.41, - "min_ns": 682111856, - "max_ns": 695002839, - "std_dev_ns": 4196004.597219256, - "cv": 0.006108609574716647, - "ops_per_second": 1.4558157488113568, + "mean_ns": 699350310.125, + "p50_ns": 699314545.5, + "p75_ns": 701737052.5, + "p90_ns": 703567982.8, + "p95_ns": 703587714.4, + "p99_ns": 703603499.68, + "min_ns": 692756358, + "max_ns": 703607446, + "std_dev_ns": 3638973.119180482, + "cv": 0.005203362415797115, + "ops_per_second": 1.4298985580220342, "sample_size": 8, - "files_processed": 1261, - "files_total": 1263, - "files_iterated": 1214, + "files_processed": 1262, + "files_total": 1264, + "files_iterated": 1215, "runtime": "node" }, { "name": "acorn-typescript", "group": "parse/typescript", - "mean_ns": 3073866475.5, - "p50_ns": 3074323220, - "p75_ns": 3074454880, - "p90_ns": 3081001004.8, - "p95_ns": 3083183046.4, - "p99_ns": 3084928679.68, - "min_ns": 3073241562, - "max_ns": 3085365088, - "std_dev_ns": 611541.8088304892, - "cv": 0.00019894872262823804, - "ops_per_second": 0.32532317456545945, - "sample_size": 4, + "mean_ns": 3118521139, + "p50_ns": 3118367834, + "p75_ns": 3118921922, + "p90_ns": 3121248988.4, + "p95_ns": 3122024677.2, + "p99_ns": 3122645228.24, + "min_ns": 3118273661, + "max_ns": 3122800366, + "std_dev_ns": 350267.60954875627, + "cv": 0.00011231849775470009, + "ops_per_second": 0.32066481368173916, + "sample_size": 3, "files_processed": 4191, "files_total": 4523, "files_iterated": 4170, @@ -311,18 +311,18 @@ { "name": "tsv-json", "group": "parse/typescript", - "mean_ns": 2078050556.4, - "p50_ns": 2079755976, - "p75_ns": 2079861385, - "p90_ns": 2080547122.6, - "p95_ns": 2080775701.8, - "p99_ns": 2080958565.16, - "min_ns": 2074218939, - "max_ns": 2081004281, - "std_dev_ns": 3023005.8038308164, - "cv": 0.0014547315966498189, - "ops_per_second": 0.4812202460234619, - "sample_size": 5, + "mean_ns": 2122191637.25, + "p50_ns": 2122060512, + "p75_ns": 2124187756, + "p90_ns": 2127898753.6, + "p95_ns": 2129135752.8, + "p99_ns": 2130125352.16, + "min_ns": 2120779194, + "max_ns": 2130372752, + "std_dev_ns": 1437762.3306762432, + "cv": 0.0006774893960751532, + "ops_per_second": 0.47121097946452667, + "sample_size": 4, "files_processed": 4323, "files_total": 4523, "files_iterated": 4170, @@ -331,17 +331,17 @@ { "name": "tsv_wasm-json", "group": "parse/typescript", - "mean_ns": 2229412735.4, - "p50_ns": 2226101219, - "p75_ns": 2233783435, - "p90_ns": 2238138226, - "p95_ns": 2239589823, - "p99_ns": 2240751100.6, - "min_ns": 2222491617, - "max_ns": 2241041420, - "std_dev_ns": 7849406.664462053, - "cv": 0.0035208405064815046, - "ops_per_second": 0.4485486173651827, + "mean_ns": 2281022702.8, + "p50_ns": 2281696769, + "p75_ns": 2289604472, + "p90_ns": 2296515271.4, + "p95_ns": 2298818871.2, + "p99_ns": 2300661751.04, + "min_ns": 2253613238, + "max_ns": 2301122471, + "std_dev_ns": 17558246.113928113, + "cv": 0.0076975323798290215, + "ops_per_second": 0.43839984528539777, "sample_size": 5, "files_processed": 4323, "files_total": 4523, @@ -351,18 +351,18 @@ { "name": "tsv-internal", "group": "parse/typescript", - "mean_ns": 159495637.87096775, - "p50_ns": 159629301, - "p75_ns": 159896475.75, - "p90_ns": 160569694.9, - "p95_ns": 160741424.8, - "p99_ns": 162729266.17000002, - "min_ns": 158152786, - "max_ns": 163583934, - "std_dev_ns": 669455.3342449737, - "cv": 0.004197326918661965, - "ops_per_second": 6.269763946829705, - "sample_size": 31, + "mean_ns": 175049760.72413793, + "p50_ns": 172252213, + "p75_ns": 179593072, + "p90_ns": 189395322.2, + "p95_ns": 200253685.6, + "p99_ns": 201078118.08, + "min_ns": 162837802, + "max_ns": 201144433, + "std_dev_ns": 11132267.86636394, + "cv": 0.06359487622440887, + "ops_per_second": 5.712661336200891, + "sample_size": 29, "files_processed": 4323, "files_total": 4523, "files_iterated": 4170, @@ -371,17 +371,17 @@ { "name": "tsv_wasm-internal", "group": "parse/typescript", - "mean_ns": 224221421.8181818, - "p50_ns": 224211495, - "p75_ns": 224575523, - "p90_ns": 225053230.4, - "p95_ns": 225218932.4, - "p99_ns": 226291981.96, - "min_ns": 223265522, - "max_ns": 226590815, - "std_dev_ns": 518216.05755649257, - "cv": 0.0023111799637802097, - "ops_per_second": 4.459877169144377, + "mean_ns": 209973689.5909091, + "p50_ns": 211159171, + "p75_ns": 212134666, + "p90_ns": 217408975.4, + "p95_ns": 223538677.75, + "p99_ns": 225153526.57, + "min_ns": 203537287, + "max_ns": 225318124, + "std_dev_ns": 3816301.7893612613, + "cv": 0.01817514278477721, + "ops_per_second": 4.762501444577633, "sample_size": 22, "files_processed": 4323, "files_total": 4523, @@ -391,17 +391,17 @@ { "name": "oxc-parser", "group": "parse/typescript", - "mean_ns": 1274185600.2, - "p50_ns": 1274635433, - "p75_ns": 1275621493, - "p90_ns": 1275911913.4, - "p95_ns": 1276008720.2, - "p99_ns": 1276086165.64, - "min_ns": 1271492383, - "max_ns": 1276105527, - "std_dev_ns": 1900078.127274034, - "cv": 0.0014912098574774288, - "ops_per_second": 0.7848150221153315, + "mean_ns": 1353134449.8, + "p50_ns": 1355085285, + "p75_ns": 1377763882, + "p90_ns": 1383105909.4, + "p95_ns": 1384886585.2, + "p99_ns": 1386311125.84, + "min_ns": 1312074197, + "max_ns": 1386667261, + "std_dev_ns": 30756375.950410083, + "cv": 0.02272972649166979, + "ops_per_second": 0.7390248619771709, "sample_size": 5, "files_processed": 4331, "files_total": 4523, @@ -411,18 +411,18 @@ { "name": "oxc-parser-wasm", "group": "parse/typescript", - "mean_ns": 1331938497.8, - "p50_ns": 1332265580, - "p75_ns": 1334243201, - "p90_ns": 1334336303.6, - "p95_ns": 1334367337.8, - "p99_ns": 1334392165.16, - "min_ns": 1328994716, - "max_ns": 1334398372, - "std_dev_ns": 2487410.853438611, - "cv": 0.001867511793935784, - "ops_per_second": 0.7507854166327709, - "sample_size": 5, + "mean_ns": 1380851596.75, + "p50_ns": 1379007066, + "p75_ns": 1380988334, + "p90_ns": 1383911433.8, + "p95_ns": 1384885800.4, + "p99_ns": 1385665293.68, + "min_ns": 1377550820, + "max_ns": 1385860167, + "std_dev_ns": 3624081.210723565, + "cv": 0.002624526212123935, + "ops_per_second": 0.7241907836827796, + "sample_size": 4, "files_processed": 4523, "files_total": 4523, "files_iterated": 4170, @@ -431,17 +431,17 @@ { "name": "prettier", "group": "format/typescript", - "mean_ns": 14903136730.142857, - "p50_ns": 14914963032, - "p75_ns": 14929654180, - "p90_ns": 14932819536.6, - "p95_ns": 14934094570.8, - "p99_ns": 14935114598.16, - "min_ns": 14860792100, - "max_ns": 14935369605, - "std_dev_ns": 31311786.66282276, - "cv": 0.002101019887946946, - "ops_per_second": 0.06709996815485261, + "mean_ns": 14865588398.571428, + "p50_ns": 14836805076, + "p75_ns": 14999225599.5, + "p90_ns": 15110158986.4, + "p95_ns": 15125331638.2, + "p99_ns": 15137469759.64, + "min_ns": 14626693526, + "max_ns": 15140504290, + "std_dev_ns": 192928718.63292965, + "cv": 0.01297820936919456, + "ops_per_second": 0.06726945299360632, "sample_size": 7, "files_processed": 4357, "files_total": 4523, @@ -451,17 +451,17 @@ { "name": "tsv", "group": "format/typescript", - "mean_ns": 604598564.8888888, - "p50_ns": 604402729, - "p75_ns": 604936643, - "p90_ns": 606916881.8, - "p95_ns": 607044903.4, - "p99_ns": 607147320.68, - "min_ns": 602312351, - "max_ns": 607172925, - "std_dev_ns": 1624169.4845821543, - "cv": 0.0026863601386163376, - "ops_per_second": 1.6539900325164958, + "mean_ns": 581185880.5555556, + "p50_ns": 581855803, + "p75_ns": 582483076, + "p90_ns": 584090648.6, + "p95_ns": 584251675.8, + "p99_ns": 584380497.56, + "min_ns": 576145694, + "max_ns": 584412703, + "std_dev_ns": 2603216.923018139, + "cv": 0.004479146879015236, + "ops_per_second": 1.7206199143105472, "sample_size": 9, "files_processed": 4323, "files_total": 4523, @@ -471,18 +471,18 @@ { "name": "tsv_wasm", "group": "format/typescript", - "mean_ns": 832472708.8571428, - "p50_ns": 832426015, - "p75_ns": 832661322.5, - "p90_ns": 833489641, - "p95_ns": 834043999, - "p99_ns": 834487485.4, - "min_ns": 831517123, - "max_ns": 834598357, - "std_dev_ns": 1057867.259824916, - "cv": 0.0012707530812357864, - "ops_per_second": 1.2012405804543989, - "sample_size": 7, + "mean_ns": 799478102.5, + "p50_ns": 799773268, + "p75_ns": 802678932.5, + "p90_ns": 810868798.8, + "p95_ns": 815312721.9, + "p99_ns": 818867860.38, + "min_ns": 795498967, + "max_ns": 819756645, + "std_dev_ns": 3248981.961188504, + "cv": 0.004063878611595249, + "ops_per_second": 1.2508159971773587, + "sample_size": 6, "files_processed": 4323, "files_total": 4523, "files_iterated": 4278, @@ -491,18 +491,18 @@ { "name": "oxfmt", "group": "format/typescript", - "mean_ns": 1018268616.4, - "p50_ns": 1018266044, - "p75_ns": 1021783414, - "p90_ns": 1025778326.2, - "p95_ns": 1027109963.6, - "p99_ns": 1028175273.52, - "min_ns": 1010728819, - "max_ns": 1028441601, - "std_dev_ns": 7253586.403586251, - "cv": 0.007123450813234993, - "ops_per_second": 0.9820591383199189, - "sample_size": 5, + "mean_ns": 1036740939.25, + "p50_ns": 1034490484, + "p75_ns": 1048641544, + "p90_ns": 1053423188.2, + "p95_ns": 1055017069.6, + "p99_ns": 1056292174.72, + "min_ns": 1031855015, + "max_ns": 1056610951, + "std_dev_ns": 8026187.144953506, + "cv": 0.007741748050153993, + "ops_per_second": 0.9645611185407811, + "sample_size": 4, "files_processed": 4334, "files_total": 4523, "files_iterated": 4278, @@ -511,17 +511,17 @@ { "name": "biome-wasm", "group": "format/typescript", - "mean_ns": 4206434816.8, - "p50_ns": 4205309650, - "p75_ns": 4205800116, - "p90_ns": 4215920650.8, - "p95_ns": 4219294162.4, - "p99_ns": 4221992971.68, - "min_ns": 4198335745, - "max_ns": 4222667674, - "std_dev_ns": 9635822.363084104, - "cv": 0.002290733788290211, - "ops_per_second": 0.23773101059503382, + "mean_ns": 4343426926, + "p50_ns": 4335003435, + "p75_ns": 4361727113, + "p90_ns": 4363591750.4, + "p95_ns": 4364213296.2, + "p99_ns": 4364710532.84, + "min_ns": 4326623753, + "max_ns": 4364834842, + "std_dev_ns": 18413375.64587056, + "cv": 0.004239365818645882, + "ops_per_second": 0.23023295131637722, "sample_size": 5, "files_processed": 4523, "files_total": 4523, @@ -531,18 +531,18 @@ { "name": "svelte/compiler", "group": "parse/css", - "mean_ns": 5534167.372124492, - "p50_ns": 5534511, - "p75_ns": 5601589, - "p90_ns": 6057350.4, - "p95_ns": 6150469.199999999, - "p99_ns": 6331490.52, - "min_ns": 5360670, - "max_ns": 7112497, - "std_dev_ns": 50160.98098094864, - "cv": 0.009063871330239967, - "ops_per_second": 180.69565532784264, - "sample_size": 739, + "mean_ns": 5870367.247820673, + "p50_ns": 5825597, + "p75_ns": 6057834.25, + "p90_ns": 6469521.3, + "p95_ns": 6690801.699999999, + "p99_ns": 7521029.210000005, + "min_ns": 5400252, + "max_ns": 10472606, + "std_dev_ns": 286448.91603264335, + "cv": 0.048795740358320044, + "ops_per_second": 170.34709376508636, + "sample_size": 803, "files_processed": 152, "files_total": 182, "files_iterated": 147, @@ -551,18 +551,18 @@ { "name": "tsv-json", "group": "parse/css", - "mean_ns": 9171936.661322646, - "p50_ns": 9158297, - "p75_ns": 9237479.75, - "p90_ns": 9324059.3, - "p95_ns": 9530100.2, - "p99_ns": 10376539.99, - "min_ns": 9062661, - "max_ns": 10896022, - "std_dev_ns": 64049.18834447374, - "cv": 0.0069831694994759675, - "ops_per_second": 109.02822783512269, - "sample_size": 499, + "mean_ns": 9425835.477459017, + "p50_ns": 9369952.5, + "p75_ns": 9684847, + "p90_ns": 10059710, + "p95_ns": 10452166, + "p99_ns": 10942451, + "min_ns": 9075258, + "max_ns": 11551277, + "std_dev_ns": 269257.3757002338, + "cv": 0.028565889606723672, + "ops_per_second": 106.09139130333902, + "sample_size": 488, "files_processed": 153, "files_total": 182, "files_iterated": 147, @@ -571,18 +571,18 @@ { "name": "tsv_wasm-json", "group": "parse/css", - "mean_ns": 11045188.038647342, - "p50_ns": 11037590, - "p75_ns": 11103768, - "p90_ns": 11237545.9, - "p95_ns": 11622702.049999997, - "p99_ns": 12360696.03, - "min_ns": 10937669, - "max_ns": 13541870, - "std_dev_ns": 71841.89158514125, - "cv": 0.006504361114882334, - "ops_per_second": 90.53716392160814, - "sample_size": 414, + "mean_ns": 11364531.188995216, + "p50_ns": 11314146.5, + "p75_ns": 11599107.25, + "p90_ns": 11888054.9, + "p95_ns": 12371595.3, + "p99_ns": 13100540.639999999, + "min_ns": 10962640, + "max_ns": 13814717, + "std_dev_ns": 300654.2595114274, + "cv": 0.02645549160906561, + "ops_per_second": 87.99307101804118, + "sample_size": 418, "files_processed": 153, "files_total": 182, "files_iterated": 147, @@ -591,18 +591,18 @@ { "name": "tsv-internal", "group": "parse/css", - "mean_ns": 3410261.394924663, - "p50_ns": 3407118, - "p75_ns": 3434811, - "p90_ns": 3467453, - "p95_ns": 3495275, - "p99_ns": 3645063.0000000005, - "min_ns": 3383693, - "max_ns": 3944501, - "std_dev_ns": 16122.873334384554, - "cv": 0.004727752939519385, - "ops_per_second": 293.23265409749956, - "sample_size": 1261, + "mean_ns": 3500777.4858454475, + "p50_ns": 3486641, + "p75_ns": 3563767, + "p90_ns": 3699880.8000000003, + "p95_ns": 3874631.95, + "p99_ns": 4275628.060000001, + "min_ns": 3398776, + "max_ns": 7466320, + "std_dev_ns": 77746.99861454495, + "cv": 0.02220849480690968, + "ops_per_second": 285.65083157763087, + "sample_size": 1307, "files_processed": 153, "files_total": 182, "files_iterated": 147, @@ -611,18 +611,18 @@ { "name": "tsv_wasm-internal", "group": "parse/css", - "mean_ns": 4971100.250797024, - "p50_ns": 4965925, - "p75_ns": 4991575, - "p90_ns": 5023109, - "p95_ns": 5051287.8, - "p99_ns": 5122918.600000001, - "min_ns": 4930558, - "max_ns": 5219349, - "std_dev_ns": 24283.641995262085, - "cv": 0.004884963241561796, - "ops_per_second": 201.16271037577013, - "sample_size": 941, + "mean_ns": 5273823.9488372095, + "p50_ns": 5260251, + "p75_ns": 5419930.5, + "p90_ns": 5717902.2, + "p95_ns": 6154693.2, + "p99_ns": 9825791.819999993, + "min_ns": 4967418, + "max_ns": 10957782, + "std_dev_ns": 197944.1662332258, + "cv": 0.03753332840715497, + "ops_per_second": 189.6157341809795, + "sample_size": 860, "files_processed": 153, "files_total": 182, "files_iterated": 147, @@ -631,18 +631,18 @@ { "name": "prettier", "group": "format/css", - "mean_ns": 320919202.73333335, - "p50_ns": 320902248, - "p75_ns": 322924090, - "p90_ns": 323683631.5, - "p95_ns": 326586274, - "p99_ns": 333233098, - "min_ns": 318156839, - "max_ns": 334894804, - "std_dev_ns": 1979353.451437957, - "cv": 0.006167762585035129, - "ops_per_second": 3.1160491222799975, - "sample_size": 15, + "mean_ns": 451542404.9166667, + "p50_ns": 451401012, + "p75_ns": 537009888.25, + "p90_ns": 593155503.1, + "p95_ns": 605417464.05, + "p99_ns": 611814478.41, + "min_ns": 333088874, + "max_ns": 613413732, + "std_dev_ns": 112599354.128353, + "cv": 0.2493660681750001, + "ops_per_second": 2.214631425778389, + "sample_size": 12, "files_processed": 181, "files_total": 182, "files_iterated": 153, @@ -651,18 +651,18 @@ { "name": "tsv", "group": "format/css", - "mean_ns": 6645486.207658321, - "p50_ns": 6639481, - "p75_ns": 6676670.5, - "p90_ns": 6736424, - "p95_ns": 6797941.5, - "p99_ns": 6983620.5, - "min_ns": 6585758, - "max_ns": 8033584, - "std_dev_ns": 31611.78048880123, - "cv": 0.004756880008624729, - "ops_per_second": 150.4780792182806, - "sample_size": 679, + "mean_ns": 9418552.322033899, + "p50_ns": 9134591, + "p75_ns": 10773992, + "p90_ns": 12294829, + "p95_ns": 13228071, + "p99_ns": 15355900.2, + "min_ns": 6464767, + "max_ns": 16725207, + "std_dev_ns": 2127507.416067421, + "cv": 0.2258847584347224, + "ops_per_second": 106.17342939854838, + "sample_size": 531, "files_processed": 153, "files_total": 182, "files_iterated": 153, @@ -671,18 +671,18 @@ { "name": "tsv_wasm", "group": "format/css", - "mean_ns": 9195869.153398057, - "p50_ns": 9183181, - "p75_ns": 9241086.5, - "p90_ns": 9307186.2, - "p95_ns": 9372383.1, - "p99_ns": 9515467.540000001, - "min_ns": 9110854, - "max_ns": 9936375, - "std_dev_ns": 54575.1335220998, - "cv": 0.0059347444609880295, - "ops_per_second": 108.74447899581955, - "sample_size": 515, + "mean_ns": 9213985.190196078, + "p50_ns": 9189335, + "p75_ns": 9323648, + "p90_ns": 9502915, + "p95_ns": 9728650, + "p99_ns": 10245225.8, + "min_ns": 8965223, + "max_ns": 10470907, + "std_dev_ns": 142383.6319869831, + "cv": 0.015452991191963604, + "ops_per_second": 108.53067151269423, + "sample_size": 510, "files_processed": 153, "files_total": 182, "files_iterated": 153, @@ -691,18 +691,18 @@ { "name": "oxfmt", "group": "format/css", - "mean_ns": 292456522.8333333, - "p50_ns": 292313677.5, - "p75_ns": 296447278, - "p90_ns": 299998187.6, - "p95_ns": 300901237.15, - "p99_ns": 302286044.23, - "min_ns": 283731824, - "max_ns": 302632246, - "std_dev_ns": 5633480.978016558, - "cv": 0.019262627222122162, - "ops_per_second": 3.4193116648996247, - "sample_size": 18, + "mean_ns": 312652692.125, + "p50_ns": 313776817, + "p75_ns": 321239933.75, + "p90_ns": 323114033.5, + "p95_ns": 326371161.25, + "p99_ns": 333399403.45, + "min_ns": 284581591, + "max_ns": 335156464, + "std_dev_ns": 12163190.144380694, + "cv": 0.03890319978283697, + "ops_per_second": 3.198437196249042, + "sample_size": 16, "files_processed": 181, "files_total": 182, "files_iterated": 153, @@ -711,18 +711,18 @@ { "name": "biome-wasm", "group": "format/css", - "mean_ns": 54948565.73863637, - "p50_ns": 54817967, - "p75_ns": 55308124.5, - "p90_ns": 56045414, - "p95_ns": 56254933, - "p99_ns": 56897367.9, - "min_ns": 54193803, - "max_ns": 57302988, - "std_dev_ns": 557561.4128707072, - "cv": 0.010146969358995755, - "ops_per_second": 18.19883715903549, - "sample_size": 88, + "mean_ns": 59552482.0875, + "p50_ns": 59497971, + "p75_ns": 60232216.25, + "p90_ns": 61290096.4, + "p95_ns": 61797406.1, + "p99_ns": 69678226.84000002, + "min_ns": 57784300, + "max_ns": 75834214, + "std_dev_ns": 888796.4896561778, + "cv": 0.014924591864202672, + "ops_per_second": 16.79191135191826, + "sample_size": 80, "files_processed": 182, "files_total": 182, "files_iterated": 153, diff --git a/src/routes/docs/benchmarks/benchmarks_conformance.json b/src/routes/docs/benchmarks/benchmarks_conformance.json index 0d27972..26efb39 100644 --- a/src/routes/docs/benchmarks/benchmarks_conformance.json +++ b/src/routes/docs/benchmarks/benchmarks_conformance.json @@ -2,121 +2,256 @@ "version": 6, "runtime": "node", "corpus_kind": "conformance", - "timestamp": "2026-07-04T22:58:25.136Z", - "git_commit": "34a14e63", + "timestamp": "2026-07-05T15:06:16.483Z", + "git_commit": "ade06e02", "corpus": { - "svelte": 50, - "typescript": 50, - "css": 50 + "svelte": 5355, + "typescript": 46708, + "css": 22672 }, "corpus_sources": [ { "path": "../zzz/src", - "files": 325 + "files": 325, + "by_language": { + "svelte": 173, + "typescript": 151, + "css": 1 + } }, { "path": "../fuz_app/src", - "files": 664 + "files": 664, + "by_language": { + "svelte": 33, + "typescript": 630, + "css": 1 + } }, { "path": "../fuz_blog/src", - "files": 32 + "files": 32, + "by_language": { + "svelte": 18, + "typescript": 13, + "css": 1 + } }, { "path": "../fuz_code/src", - "files": 68 + "files": 64, + "by_language": { + "svelte": 21, + "typescript": 38, + "css": 5 + } }, { "path": "../fuz_css/src", - "files": 124 + "files": 124, + "by_language": { + "svelte": 37, + "typescript": 85, + "css": 2 + } }, { "path": "../fuz_docs/src", - "files": 64 + "files": 64, + "by_language": { + "svelte": 45, + "typescript": 18, + "css": 1 + } }, { "path": "../fuz_gitops/src", - "files": 203 + "files": 203, + "by_language": { + "svelte": 28, + "typescript": 174, + "css": 1 + } }, { "path": "../fuz_mastodon/src", - "files": 24 + "files": 24, + "by_language": { + "svelte": 15, + "typescript": 8, + "css": 1 + } }, { "path": "../fuz_template/src", - "files": 15 + "files": 15, + "by_language": { + "svelte": 10, + "typescript": 4, + "css": 1 + } }, { "path": "../fuz_ui/src", - "files": 215 + "files": 215, + "by_language": { + "svelte": 121, + "typescript": 94, + "css": 0 + } }, { "path": "../fuz_util/src", - "files": 144 + "files": 144, + "by_language": { + "svelte": 8, + "typescript": 135, + "css": 1 + } }, { "path": "../gro/src", - "files": 187 + "files": 187, + "by_language": { + "svelte": 11, + "typescript": 175, + "css": 1 + } }, { "path": "../svelte-docinfo/src", - "files": 297 + "files": 297, + "by_language": { + "svelte": 82, + "typescript": 214, + "css": 1 + } }, { "path": "../tsv.fuz.dev/src", - "files": 26 + "files": 28, + "by_language": { + "svelte": 16, + "typescript": 11, + "css": 1 + } }, { "path": "../kit/packages/kit/src", - "files": 381 + "files": 318, + "by_language": { + "svelte": 84, + "typescript": 233, + "css": 1 + } }, { "path": "../svelte/packages/svelte/src", - "files": 380 + "files": 375, + "by_language": { + "svelte": 0, + "typescript": 375, + "css": 0 + } }, { "path": "../svelte.dev/apps/svelte.dev/src", - "files": 138 + "files": 135, + "by_language": { + "svelte": 60, + "typescript": 75, + "css": 0 + } }, { "path": "../svelte.dev/packages/repl/src", - "files": 48 + "files": 48, + "by_language": { + "svelte": 17, + "typescript": 29, + "css": 2 + } }, { "path": "../svelte.dev/packages/site-kit/src", - "files": 65 + "files": 65, + "by_language": { + "svelte": 26, + "typescript": 28, + "css": 11 + } }, { "path": "../prettier-plugin-svelte/test", - "files": 325 + "files": 309, + "by_language": { + "svelte": 309, + "typescript": 0, + "css": 0 + } }, { "path": "../prettier/tests/format/typescript", - "files": 789 + "files": 789, + "by_language": { + "svelte": 0, + "typescript": 789, + "css": 0 + } }, { "path": "../prettier/tests/format/js", - "files": 1103 + "files": 1103, + "by_language": { + "svelte": 0, + "typescript": 1103, + "css": 0 + } }, { "path": "../prettier/tests/format/css", - "files": 228 + "files": 228, + "by_language": { + "svelte": 0, + "typescript": 78, + "css": 150 + } }, { "path": "../prettier/tests/format/html", - "files": 124 + "files": 124, + "by_language": { + "svelte": 124, + "typescript": 0, + "css": 0 + } }, { "path": "../svelte/packages/svelte/tests", - "files": 4543 + "files": 4432, + "by_language": { + "svelte": 4117, + "typescript": 135, + "css": 180 + } }, { "path": "benches/js/.cache/wpt_css", - "files": 22310 + "files": 22310, + "by_language": { + "svelte": 0, + "typescript": 0, + "css": 22310 + } }, { "path": "benches/js/.cache/test262_files.json", - "files": 42113 + "files": 42113, + "by_language": { + "svelte": 0, + "typescript": 42113, + "css": 0 + } } ], "versions": { @@ -133,45 +268,45 @@ "binary_sizes": [ { "label": "tsv (ffi)", - "bytes": 3324480, + "bytes": 3307360, "kind": "native", - "gzip_bytes": 1423272 + "gzip_bytes": 1428738 }, { "label": "tsv format (ffi)", - "bytes": 3070736, + "bytes": 3054656, "kind": "native", - "gzip_bytes": 1317789 + "gzip_bytes": 1324423 }, { "label": "tsv parse (ffi)", - "bytes": 1545168, + "bytes": 1542576, "kind": "native", - "gzip_bytes": 683595 + "gzip_bytes": 682941 }, { "label": "tsv (napi)", - "bytes": 3447328, + "bytes": 3431120, "kind": "native", - "gzip_bytes": 1464803 + "gzip_bytes": 1470536 }, { "label": "tsv_format_wasm", - "bytes": 2312689, + "bytes": 2186094, "kind": "wasm", - "gzip_bytes": 784944 + "gzip_bytes": 754306 }, { "label": "tsv_parse_wasm", - "bytes": 1126329, + "bytes": 1015654, "kind": "wasm", - "gzip_bytes": 401394 + "gzip_bytes": 375849 }, { "label": "tsv_wasm", - "bytes": 2540357, + "bytes": 2410073, "kind": "wasm", - "gzip_bytes": 866096 + "gzip_bytes": 833573 }, { "label": "biome (wasm)", @@ -202,341 +337,341 @@ { "name": "svelte/compiler", "group": "parse/svelte", - "mean_ns": 42592126.652173914, - "p50_ns": 42372503, - "p75_ns": 45104994.75, - "p90_ns": 45953787, - "p95_ns": 46785490.85, - "p99_ns": 52088600.62, - "min_ns": 38997284, - "max_ns": 53632500, - "std_dev_ns": 2420666.899346065, - "cv": 0.05683367067144353, - "ops_per_second": 23.478517712121796, - "sample_size": 23, - "files_processed": 50, - "files_total": 50, - "files_iterated": 50, + "mean_ns": 711837306, + "p50_ns": 714220953, + "p75_ns": 715413109, + "p90_ns": 726956792.8, + "p95_ns": 730804687.4, + "p99_ns": 733883003.08, + "min_ns": 696738177, + "max_ns": 734652582, + "std_dev_ns": 15443531.08049325, + "cv": 0.021695310080437468, + "ops_per_second": 1.4048153862843484, + "sample_size": 5, + "files_processed": 5217, + "files_total": 5355, + "files_iterated": 5209, "runtime": "node" }, { "name": "tsv-json", "group": "parse/svelte", - "mean_ns": 17520284.375, - "p50_ns": 17484422, - "p75_ns": 17756645, - "p90_ns": 18229084.4, - "p95_ns": 18622561.6, - "p99_ns": 18941451.279999997, - "min_ns": 16824456, - "max_ns": 19231608, - "std_dev_ns": 459761.35622087336, - "cv": 0.026241660602091304, - "ops_per_second": 57.07669913320114, - "sample_size": 56, - "files_processed": 50, - "files_total": 50, - "files_iterated": 50, + "mean_ns": 355459711.2, + "p50_ns": 354466667, + "p75_ns": 356068214, + "p90_ns": 358833872.6, + "p95_ns": 359755758.8, + "p99_ns": 360493267.76, + "min_ns": 352185836, + "max_ns": 360677645, + "std_dev_ns": 3230077.3328286894, + "cv": 0.009087042022074004, + "ops_per_second": 2.813258348250186, + "sample_size": 5, + "files_processed": 5241, + "files_total": 5355, + "files_iterated": 5209, "runtime": "node" }, { "name": "tsv_wasm-json", "group": "parse/svelte", - "mean_ns": 19937617.36734694, - "p50_ns": 19894594, - "p75_ns": 20359697.25, - "p90_ns": 20799981.7, - "p95_ns": 21010359.85, - "p99_ns": 21736769.689999998, - "min_ns": 19127492, - "max_ns": 22395829, - "std_dev_ns": 538124.008094583, - "cv": 0.026990386974518922, - "ops_per_second": 50.156444552786006, - "sample_size": 49, - "files_processed": 50, - "files_total": 50, - "files_iterated": 50, + "mean_ns": 386411127.3333333, + "p50_ns": 386422999, + "p75_ns": 386439730, + "p90_ns": 389706363.4, + "p95_ns": 390795241.2, + "p99_ns": 391666343.44, + "min_ns": 386370653, + "max_ns": 391884119, + "std_dev_ns": 36036.23640633596, + "cv": 0.00009325879576767388, + "ops_per_second": 2.58791719301955, + "sample_size": 3, + "files_processed": 5241, + "files_total": 5355, + "files_iterated": 5209, "runtime": "node" }, { "name": "tsv-internal", "group": "parse/svelte", - "mean_ns": 1561040.194221509, - "p50_ns": 1558470, - "p75_ns": 1599678, - "p90_ns": 1641439.2, - "p95_ns": 1705062.7999999998, - "p99_ns": 1859773.76, - "min_ns": 1453612, - "max_ns": 2576662, - "std_dev_ns": 60498.44548723698, - "cv": 0.03875521316567224, - "ops_per_second": 640.5984956067708, - "sample_size": 623, - "files_processed": 50, - "files_total": 50, - "files_iterated": 50, + "mean_ns": 37838861, + "p50_ns": 38017131, + "p75_ns": 38134240, + "p90_ns": 39168125.8, + "p95_ns": 39512754.4, + "p99_ns": 39788457.28, + "min_ns": 37396175, + "max_ns": 39857383, + "std_dev_ns": 324529.684572408, + "cv": 0.00857662403137367, + "ops_per_second": 26.427856800446502, + "sample_size": 4, + "files_processed": 5241, + "files_total": 5355, + "files_iterated": 5209, "runtime": "node" }, { "name": "tsv_wasm-internal", "group": "parse/svelte", - "mean_ns": 2351937.689903846, - "p50_ns": 2351807.5, - "p75_ns": 2400101.25, - "p90_ns": 2463373.7, - "p95_ns": 2530434.9499999997, - "p99_ns": 2663788.4799999995, - "min_ns": 2207946, - "max_ns": 2793461, - "std_dev_ns": 81268.77684799174, - "cv": 0.03455396679803802, - "ops_per_second": 425.1813320959548, - "sample_size": 416, - "files_processed": 50, - "files_total": 50, - "files_iterated": 50, + "mean_ns": 52819275.333333336, + "p50_ns": 53183599, + "p75_ns": 78185568, + "p90_ns": 79334740.2, + "p95_ns": 79717797.6, + "p99_ns": 80024243.52, + "min_ns": 52405770, + "max_ns": 80100855, + "std_dev_ns": 391239.8440373032, + "cv": 0.007407141456755247, + "ops_per_second": 18.932482388089813, + "sample_size": 3, + "files_processed": 5241, + "files_total": 5355, + "files_iterated": 5209, "runtime": "node" }, { "name": "acorn-typescript", "group": "parse/typescript", - "mean_ns": 49106025.84210526, - "p50_ns": 49163618, - "p75_ns": 49871864, - "p90_ns": 51325036, - "p95_ns": 53582887, - "p99_ns": 54569459.800000004, - "min_ns": 47755199, - "max_ns": 54816103, - "std_dev_ns": 979671.3320026867, - "cv": 0.01995012455605156, - "ops_per_second": 20.364099575383765, - "sample_size": 19, - "files_processed": 50, - "files_total": 50, - "files_iterated": 50, + "mean_ns": 10546714871.285715, + "p50_ns": 10531234774, + "p75_ns": 10623521053, + "p90_ns": 10655027623.8, + "p95_ns": 10669469424.9, + "p99_ns": 10681022865.78, + "min_ns": 10439500875, + "max_ns": 10683911226, + "std_dev_ns": 97599727.07873665, + "cv": 0.009254040549105941, + "ops_per_second": 0.0948162543696503, + "sample_size": 7, + "files_processed": 46030, + "files_total": 46708, + "files_iterated": 45959, "runtime": "node" }, { "name": "tsv-json", "group": "parse/typescript", - "mean_ns": 31513656.464285713, - "p50_ns": 31588069, - "p75_ns": 31932624.25, - "p90_ns": 34192304.7, - "p95_ns": 34608299.95, - "p99_ns": 35685192.4, - "min_ns": 30599438, - "max_ns": 36043261, - "std_dev_ns": 521142.4047038912, - "cv": 0.01653703388226306, - "ops_per_second": 31.732274581760944, - "sample_size": 28, - "files_processed": 50, - "files_total": 50, - "files_iterated": 50, + "mean_ns": 5764540928.142858, + "p50_ns": 5760753423, + "p75_ns": 5773887260, + "p90_ns": 5807996417.6, + "p95_ns": 5827958654.3, + "p99_ns": 5843928443.66, + "min_ns": 5710986387, + "max_ns": 5847920891, + "std_dev_ns": 43250996.46975181, + "cv": 0.007502938570285394, + "ops_per_second": 0.1734743516379485, + "sample_size": 7, + "files_processed": 46464, + "files_total": 46708, + "files_iterated": 45959, "runtime": "node" }, { "name": "tsv_wasm-json", "group": "parse/typescript", - "mean_ns": 34645150.2962963, - "p50_ns": 34680689, - "p75_ns": 35207563, - "p90_ns": 36540927.8, - "p95_ns": 38035464.4, - "p99_ns": 39149145.36, - "min_ns": 33500061, - "max_ns": 39240163, - "std_dev_ns": 762383.5100824264, - "cv": 0.022005490048745094, - "ops_per_second": 28.86406874981587, - "sample_size": 27, - "files_processed": 50, - "files_total": 50, - "files_iterated": 50, + "mean_ns": 6126542016.428572, + "p50_ns": 6130197740, + "p75_ns": 6141894028.5, + "p90_ns": 6151765711.6, + "p95_ns": 6154230910.3, + "p99_ns": 6156203069.26, + "min_ns": 6094006411, + "max_ns": 6156696109, + "std_dev_ns": 22744048.227786593, + "cv": 0.003712379375967308, + "ops_per_second": 0.16322421315620775, + "sample_size": 7, + "files_processed": 46464, + "files_total": 46708, + "files_iterated": 45959, "runtime": "node" }, { "name": "tsv-internal", "group": "parse/typescript", - "mean_ns": 2162101.937360179, - "p50_ns": 2168251, - "p75_ns": 2197687, - "p90_ns": 2237192, - "p95_ns": 2292356, - "p99_ns": 2471238.999999999, - "min_ns": 2049307, - "max_ns": 2664057, - "std_dev_ns": 56058.794264350276, - "cv": 0.025927914542639617, - "ops_per_second": 462.5128828203869, - "sample_size": 447, - "files_processed": 50, - "files_total": 50, - "files_iterated": 50, + "mean_ns": 450847760.4, + "p50_ns": 450898135, + "p75_ns": 451459309, + "p90_ns": 451880158.6, + "p95_ns": 452020441.8, + "p99_ns": 452132668.36, + "min_ns": 449571935, + "max_ns": 452160725, + "std_dev_ns": 1026745.3459499099, + "cv": 0.0022773659672590224, + "ops_per_second": 2.2180436232239074, + "sample_size": 5, + "files_processed": 46464, + "files_total": 46708, + "files_iterated": 45959, "runtime": "node" }, { "name": "tsv_wasm-internal", "group": "parse/typescript", - "mean_ns": 3276734.684931507, - "p50_ns": 3273948, - "p75_ns": 3346114, - "p90_ns": 3449610.6, - "p95_ns": 3578550.349999999, - "p99_ns": 3893452.9999999986, - "min_ns": 3098076, - "max_ns": 4042888, - "std_dev_ns": 103174.0229134631, - "cv": 0.031486840661199195, - "ops_per_second": 305.1818643110261, - "sample_size": 292, - "files_processed": 50, - "files_total": 50, - "files_iterated": 50, + "mean_ns": 636976103, + "p50_ns": 637059871, + "p75_ns": 637081070, + "p90_ns": 638550510.2, + "p95_ns": 639040323.6, + "p99_ns": 639432174.32, + "min_ns": 636787368, + "max_ns": 639530137, + "std_dev_ns": 163792.62672354942, + "cv": 0.0002571409287603203, + "ops_per_second": 1.569917608039371, + "sample_size": 3, + "files_processed": 46464, + "files_total": 46708, + "files_iterated": 45959, "runtime": "node" }, { "name": "oxc-parser", "group": "parse/typescript", - "mean_ns": 17757639.431818184, - "p50_ns": 17790378.5, - "p75_ns": 18193898, - "p90_ns": 36024234.7, - "p95_ns": 37406521.9, - "p99_ns": 42044068.58999999, - "min_ns": 16896211, - "max_ns": 45152388, - "std_dev_ns": 470654.8101898134, - "cv": 0.026504356730348566, - "ops_per_second": 56.313791246836416, - "sample_size": 44, - "files_processed": 50, - "files_total": 50, - "files_iterated": 50, + "mean_ns": 3712865724.5, + "p50_ns": 3714305438, + "p75_ns": 3735694100, + "p90_ns": 3853014017, + "p95_ns": 3892120656, + "p99_ns": 3923405967.2, + "min_ns": 3697862054, + "max_ns": 3931227295, + "std_dev_ns": 16674802.163212162, + "cv": 0.004491086777844007, + "ops_per_second": 0.269333736849497, + "sample_size": 4, + "files_processed": 46465, + "files_total": 46708, + "files_iterated": 45959, "runtime": "node" }, { "name": "oxc-parser-wasm", "group": "parse/typescript", - "mean_ns": 22603262.589743588, - "p50_ns": 22243320, - "p75_ns": 23859140.5, - "p90_ns": 25405074.8, - "p95_ns": 27667718.099999998, - "p99_ns": 34038511.29999999, - "min_ns": 21268100, - "max_ns": 36715228, - "std_dev_ns": 1210693.4068062142, - "cv": 0.05356277227675867, - "ops_per_second": 44.24140081678996, - "sample_size": 39, - "files_processed": 50, - "files_total": 50, - "files_iterated": 50, + "mean_ns": 4347237533.2, + "p50_ns": 4346363747, + "p75_ns": 4362145916, + "p90_ns": 4417627440.2, + "p95_ns": 4436121281.6, + "p99_ns": 4450916354.72, + "min_ns": 4284843015, + "max_ns": 4454615123, + "std_dev_ns": 69154051.2776857, + "cv": 0.015907585161738663, + "ops_per_second": 0.23003113870888495, + "sample_size": 5, + "files_processed": 46708, + "files_total": 46708, + "files_iterated": 45959, "runtime": "node" }, { "name": "svelte/compiler", "group": "parse/css", - "mean_ns": 3965116.419213974, - "p50_ns": 3948034, - "p75_ns": 4097113.25, - "p90_ns": 4408711.2, - "p95_ns": 4583902.6, - "p99_ns": 5021958.08, - "min_ns": 3734547, - "max_ns": 6578933, - "std_dev_ns": 165867.08268332237, - "cv": 0.04183157949148012, - "ops_per_second": 252.199404575928, - "sample_size": 229, - "files_processed": 48, - "files_total": 50, - "files_iterated": 48, + "mean_ns": 240630028.8, + "p50_ns": 241029027, + "p75_ns": 242335570, + "p90_ns": 243382705, + "p95_ns": 243731750, + "p99_ns": 244010986, + "min_ns": 237629418, + "max_ns": 244080795, + "std_dev_ns": 2761611.3235657727, + "cv": 0.011476586431617352, + "ops_per_second": 4.155757305050034, + "sample_size": 5, + "files_processed": 22433, + "files_total": 22672, + "files_iterated": 22409, "runtime": "node" }, { "name": "tsv-json", "group": "parse/css", - "mean_ns": 6552144.952380952, - "p50_ns": 6536829.5, - "p75_ns": 6652212.25, - "p90_ns": 6797909.7, - "p95_ns": 6915894.9, - "p99_ns": 8203895.45, - "min_ns": 6259591, - "max_ns": 8306503, - "std_dev_ns": 152812.986907506, - "cv": 0.023322589475371122, - "ops_per_second": 152.62177611571533, - "sample_size": 147, - "files_processed": 48, - "files_total": 50, - "files_iterated": 48, + "mean_ns": 454197684, + "p50_ns": 453949601, + "p75_ns": 455880395, + "p90_ns": 457332746, + "p95_ns": 457816863, + "p99_ns": 458204156.6, + "min_ns": 450319049, + "max_ns": 458300980, + "std_dev_ns": 3062970.3310990464, + "cv": 0.006743694296554463, + "ops_per_second": 2.201684498241519, + "sample_size": 5, + "files_processed": 22478, + "files_total": 22672, + "files_iterated": 22409, "runtime": "node" }, { "name": "tsv_wasm-json", "group": "parse/css", - "mean_ns": 8055132.974789916, - "p50_ns": 8046998.5, - "p75_ns": 8244085.25, - "p90_ns": 8485059.8, - "p95_ns": 9021225, - "p99_ns": 9823383.929999998, - "min_ns": 7526642, - "max_ns": 10726119, - "std_dev_ns": 288354.58832505083, - "cv": 0.03579761988132435, - "ops_per_second": 124.14444344118115, - "sample_size": 119, - "files_processed": 48, - "files_total": 50, - "files_iterated": 48, + "mean_ns": 535892000.6, + "p50_ns": 535585178, + "p75_ns": 537001487, + "p90_ns": 537083391.2, + "p95_ns": 537110692.6, + "p99_ns": 537132533.72, + "min_ns": 534584622, + "max_ns": 537137994, + "std_dev_ns": 1133173.9163799174, + "cv": 0.0021145565059959535, + "ops_per_second": 1.8660476343747834, + "sample_size": 5, + "files_processed": 22478, + "files_total": 22672, + "files_iterated": 22409, "runtime": "node" }, { "name": "tsv-internal", "group": "parse/css", - "mean_ns": 2505575.1297709923, - "p50_ns": 2513632, - "p75_ns": 2551819.5, - "p90_ns": 2572908.4, - "p95_ns": 2603319.3, - "p99_ns": 2775517.0599999996, - "min_ns": 2376735, - "max_ns": 3187926, - "std_dev_ns": 61166.80711833826, - "cv": 0.024412282190847283, - "ops_per_second": 399.10996406298113, - "sample_size": 393, - "files_processed": 48, - "files_total": 50, - "files_iterated": 48, + "mean_ns": 108869208, + "p50_ns": 108826588, + "p75_ns": 109251275, + "p90_ns": 109666637, + "p95_ns": 109805091, + "p99_ns": 109915854.2, + "min_ns": 108051914, + "max_ns": 109943545, + "std_dev_ns": 762522.368359447, + "cv": 0.007004022371132222, + "ops_per_second": 9.185333652835979, + "sample_size": 5, + "files_processed": 22478, + "files_total": 22672, + "files_iterated": 22409, "runtime": "node" }, { "name": "tsv_wasm-internal", "group": "parse/css", - "mean_ns": 3581292.0037037036, - "p50_ns": 3572496, - "p75_ns": 3635640.25, - "p90_ns": 3718303.7, - "p95_ns": 3817991.65, - "p99_ns": 4150013.95, - "min_ns": 3421496, - "max_ns": 5141341, - "std_dev_ns": 91275.83305976799, - "cv": 0.025486844682134902, - "ops_per_second": 279.2288366784443, - "sample_size": 270, - "files_processed": 48, - "files_total": 50, - "files_iterated": 48, + "mean_ns": 169215491.4, + "p50_ns": 168845557, + "p75_ns": 169885669, + "p90_ns": 170432503.6, + "p95_ns": 170614781.8, + "p99_ns": 170760604.36, + "min_ns": 167811576, + "max_ns": 170797060, + "std_dev_ns": 1149642.567479258, + "cv": 0.006793955789554017, + "ops_per_second": 5.909624418701419, + "sample_size": 5, + "files_processed": 22478, + "files_total": 22672, + "files_iterated": 22409, "runtime": "node" } ], diff --git a/src/routes/docs/benchmarks/benchmarks_cross_runtime.json b/src/routes/docs/benchmarks/benchmarks_cross_runtime.json index 5b1e7f5..de62947 100644 --- a/src/routes/docs/benchmarks/benchmarks_cross_runtime.json +++ b/src/routes/docs/benchmarks/benchmarks_cross_runtime.json @@ -1,7 +1,7 @@ { "version": 5, "kind": "combined", - "generated": "2026-07-03T21:13:05.215Z", + "generated": "2026-07-04T17:17:03.572Z", "runtimes": [ "deno", "node", @@ -10,20 +10,20 @@ "sources": [ { "runtime": "deno", - "timestamp": "2026-07-03T20:54:20.010Z", - "git_commit": "2136c09e", + "timestamp": "2026-07-04T16:57:37.990Z", + "git_commit": "ad1c91b6", "tsv": "0.1.0" }, { "runtime": "node", - "timestamp": "2026-07-03T21:04:21.052Z", - "git_commit": "2136c09e", + "timestamp": "2026-07-04T17:07:43.168Z", + "git_commit": "ad1c91b6", "tsv": "0.1.0" }, { "runtime": "bun", - "timestamp": "2026-07-03T21:13:04.771Z", - "git_commit": "2136c09e", + "timestamp": "2026-07-04T17:17:03.227Z", + "git_commit": "ad1c91b6", "tsv": "0.1.0" } ], @@ -32,201 +32,201 @@ "group": "parse/svelte", "name": "svelte/compiler", "ops_per_second": { - "deno": 2.2655155719990065, - "node": 2.2287613643153636, - "bun": 1.374707246100767 + "deno": 2.347271545649636, + "node": 2.2073856966217855, + "bun": 1.171840168515791 }, "mean_ns": { - "deno": 441400629.6666667, - "node": 448679708.8333333, - "bun": 727427605.2857143 + "deno": 426026550.6363636, + "node": 453024589.9166667, + "bun": 853358697.6 }, "files_iterated": { - "deno": 1214, - "node": 1215, - "bun": 1215 + "deno": 1215, + "node": 1216, + "bun": 1216 } }, { "group": "parse/svelte", "name": "tsv-json", "ops_per_second": { - "deno": 2.9132640280963105, - "node": 2.9432811116475763, - "bun": 3.474870532057512 + "deno": 4.8038751589342255, + "node": 4.525594682396595, + "bun": 4.563558073156287 }, "mean_ns": { - "deno": 343257593.6666667, - "node": 339756877.46666664, - "bun": 287780506 + "deno": 208165276.3478261, + "node": 220965435.52380952, + "bun": 219127265.16666666 }, "files_iterated": { - "deno": 1214, - "node": 1215, - "bun": 1215 + "deno": 1215, + "node": 1216, + "bun": 1216 } }, { "group": "parse/svelte", "name": "tsv_wasm-json", "ops_per_second": { - "deno": 2.4134217889818093, - "node": 2.605151134597657, - "bun": 3.086284306092055 + "deno": 4.088832504572286, + "node": 4.049972314476044, + "bun": 4.900803899447002 }, "mean_ns": { - "deno": 414349453.7777778, - "node": 383854889.15384614, - "bun": 324014219.3076923 + "deno": 244568589.9047619, + "node": 246915268.14285713, + "bun": 204048156.2857143 }, "files_iterated": { - "deno": 1214, - "node": 1215, - "bun": 1215 + "deno": 1215, + "node": 1216, + "bun": 1216 } }, { "group": "parse/svelte", "name": "tsv-internal", "ops_per_second": { - "deno": 35.9191416476366, - "node": 43.971816130740784, - "bun": 46.361811588668914 + "deno": 37.97137258480949, + "node": 43.4814815309668, + "bun": 29.275859998855154 }, "mean_ns": { - "deno": 27840308.93081761, - "node": 22741839.841836736, - "bun": 21569476.380090497 + "deno": 26335629.5, + "node": 22998296.396313366, + "bun": 34157835.159722224 }, "files_iterated": { - "deno": 1214, - "node": 1215, - "bun": 1215 + "deno": 1215, + "node": 1216, + "bun": 1216 } }, { "group": "parse/svelte", "name": "tsv_wasm-internal", "ops_per_second": { - "deno": 26.03544346384601, - "node": 19.830201038146818, - "bun": 9.30639827049212 + "deno": 28.0667336249714, + "node": 23.929019951615516, + "bun": 12.342135202912267 }, "mean_ns": { - "deno": 38409178.67938931, - "node": 50428132.225, - "bun": 107452955.58333333 + "deno": 35629368.68115942, + "node": 41790261.449152544, + "bun": 81023257.6097561 }, "files_iterated": { - "deno": 1214, - "node": 1215, - "bun": 1215 + "deno": 1215, + "node": 1216, + "bun": 1216 } }, { "group": "format/svelte", "name": "prettier", "ops_per_second": { - "deno": 0.2232339223196913, - "node": 0.22021584794965843, - "bun": 0.2436162337836398 + "deno": 0.23081010317523074, + "node": 0.21762301204737144, + "bun": 0.20749604552817394 }, "mean_ns": { - "deno": 4479605920.142858, - "node": 4540999248.285714, - "bun": 4104816762.285714 + "deno": 4332565976.285714, + "node": 4595102285.333333, + "bun": 4819368954.5 }, "files_iterated": { - "deno": 1213, - "node": 1214, - "bun": 1216 + "deno": 1214, + "node": 1215, + "bun": 1217 } }, { "group": "format/svelte", "name": "tsv", "ops_per_second": { - "deno": 9.851941893942634, - "node": 11.751728076241932, - "bun": 11.378781812596568 + "deno": 11.489997266485988, + "node": 12.896377549164786, + "bun": 11.866863420135138 }, "mean_ns": { - "deno": 101502831.70212767, - "node": 85093868.19642857, - "bun": 87882869.75438596 + "deno": 87032222.62, + "node": 77541154.1875, + "bun": 84268265.72413793 }, "files_iterated": { - "deno": 1213, - "node": 1214, - "bun": 1216 + "deno": 1214, + "node": 1215, + "bun": 1217 } }, { "group": "format/svelte", "name": "tsv_wasm", "ops_per_second": { - "deno": 7.428911375211762, - "node": 7.187663870329243, - "bun": 8.401494676675258 + "deno": 8.024426938173194, + "node": 7.220475800353686, + "bun": 6.524826304571686 }, "mean_ns": { - "deno": 134609224.6216216, - "node": 139127262.77142859, - "bun": 119026439.75675675 + "deno": 124619490.925, + "node": 138495028.25714287, + "bun": 153260784.78125 }, "files_iterated": { - "deno": 1213, - "node": 1214, - "bun": 1216 + "deno": 1214, + "node": 1215, + "bun": 1217 } }, { "group": "format/svelte", "name": "oxfmt", "ops_per_second": { - "deno": 0.23644393807232356, - "node": 0.22854935439789759, - "bun": 0.18319215632205318 + "deno": 0.23517958089863975, + "node": 0.23287845080096192, + "bun": 0.17886350316998154 }, "mean_ns": { - "deno": 4229332365.857143, - "node": 4375422554.285714, - "bun": 5458748999.285714 + "deno": 4252069827.571429, + "node": 4294085590.8333335, + "bun": 5590855497.5 }, "files_iterated": { - "deno": 1213, - "node": 1214, - "bun": 1216 + "deno": 1214, + "node": 1215, + "bun": 1217 } }, { "group": "format/svelte", "name": "biome-wasm", "ops_per_second": { - "deno": 1.2812117910213243, - "node": 1.4558157488113568 + "deno": 1.2632997868971714, + "node": 1.4298985580220342 }, "mean_ns": { - "deno": 780511081, - "node": 686900111.375 + "deno": 791577747.7142857, + "node": 699350310.125 }, "files_iterated": { - "deno": 1213, - "node": 1214 + "deno": 1214, + "node": 1215 } }, { "group": "parse/typescript", "name": "acorn-typescript", "ops_per_second": { - "deno": 0.3448484563403436, - "node": 0.32532317456545945, - "bun": 0.16276943290411833 + "deno": 0.3460161266948982, + "node": 0.32066481368173916, + "bun": 0.15444299404057144 }, "mean_ns": { - "deno": 2899824492.8, - "node": 3073866475.5, - "bun": 6143659667.285714 + "deno": 2890038708.75, + "node": 3118521139, + "bun": 6474880950.166667 }, "files_iterated": { "deno": 4170, @@ -238,14 +238,14 @@ "group": "parse/typescript", "name": "tsv-json", "ops_per_second": { - "deno": 0.5109412736328188, - "node": 0.4812202460234619, - "bun": 0.7358910971790861 + "deno": 0.505380554644006, + "node": 0.47121097946452667, + "bun": 0.7219629701427577 }, "mean_ns": { - "deno": 1957172089.25, - "node": 2078050556.4, - "bun": 1358896722.4 + "deno": 1978706918.6, + "node": 2122191637.25, + "bun": 1385112590.75 }, "files_iterated": { "deno": 4170, @@ -257,14 +257,14 @@ "group": "parse/typescript", "name": "tsv_wasm-json", "ops_per_second": { - "deno": 0.44959811378880415, - "node": 0.4485486173651827, - "bun": 0.6735078706368185 + "deno": 0.453980087399881, + "node": 0.43839984528539777, + "bun": 0.6611939084409393 }, "mean_ns": { - "deno": 2224208619.5, - "node": 2229412735.4, - "bun": 1484763643.6 + "deno": 2202739784.75, + "node": 2281022702.8, + "bun": 1512415627.6 }, "files_iterated": { "deno": 4170, @@ -276,14 +276,14 @@ "group": "parse/typescript", "name": "tsv-internal", "ops_per_second": { - "deno": 5.566956831156124, - "node": 6.269763946829705, - "bun": 6.897577446230635 + "deno": 5.793969893387226, + "node": 5.712661336200891, + "bun": 7.075024236203023 }, "mean_ns": { - "deno": 179631355.2142857, - "node": 159495637.87096775, - "bun": 144978437.4 + "deno": 172593233.72413793, + "node": 175049760.72413793, + "bun": 141342272 }, "files_iterated": { "deno": 4170, @@ -295,14 +295,14 @@ "group": "parse/typescript", "name": "tsv_wasm-internal", "ops_per_second": { - "deno": 3.852183793159643, - "node": 4.459877169144377, - "bun": 4.505169311234465 + "deno": 4.246094553689498, + "node": 4.762501444577633, + "bun": 4.838220957049038 }, "mean_ns": { - "deno": 259593013.65, - "node": 224221421.8181818, - "bun": 221967240.5 + "deno": 235510535, + "node": 209973689.5909091, + "bun": 206687542.5652174 }, "files_iterated": { "deno": 4170, @@ -314,14 +314,14 @@ "group": "parse/typescript", "name": "oxc-parser", "ops_per_second": { - "deno": 0.8428454867591976, - "node": 0.7848150221153315, - "bun": 1.054251047643705 + "deno": 0.835768365220317, + "node": 0.7390248619771709, + "bun": 1.015456845836143 }, "mean_ns": { - "deno": 1186457085.8, - "node": 1274185600.2, - "bun": 948540674.6666666 + "deno": 1196503770.2, + "node": 1353134449.8, + "bun": 984778431.6 }, "files_iterated": { "deno": 4170, @@ -333,12 +333,12 @@ "group": "parse/typescript", "name": "oxc-parser-wasm", "ops_per_second": { - "deno": 0.7754633266588533, - "node": 0.7507854166327709 + "deno": 0.7493453264469214, + "node": 0.7241907836827796 }, "mean_ns": { - "deno": 1289551634, - "node": 1331938497.8 + "deno": 1334498214.25, + "node": 1380851596.75 }, "files_iterated": { "deno": 4170, @@ -349,14 +349,14 @@ "group": "format/typescript", "name": "prettier", "ops_per_second": { - "deno": 0.07649992948869264, - "node": 0.06709996815485261, - "bun": 0.06414328180062466 + "deno": 0.07257444058273492, + "node": 0.06726945299360632, + "bun": 0.05949589854834684 }, "mean_ns": { - "deno": 13071907473.428572, - "node": 14903136730.142857, - "bun": 15590097231.2 + "deno": 13778955676, + "node": 14865588398.571428, + "bun": 16807881289.285715 }, "files_iterated": { "deno": 4278, @@ -368,14 +368,14 @@ "group": "format/typescript", "name": "tsv", "ops_per_second": { - "deno": 1.5237024469986489, - "node": 1.6539900325164958, - "bun": 1.6301952763564374 + "deno": 1.6225228085021561, + "node": 1.7206199143105472, + "bun": 1.7131005537975372 }, "mean_ns": { - "deno": 656296117.375, - "node": 604598564.8888888, - "bun": 613423443.5 + "deno": 616324155.6666666, + "node": 581185880.5555556, + "bun": 583736896.1111112 }, "files_iterated": { "deno": 4278, @@ -387,14 +387,14 @@ "group": "format/typescript", "name": "tsv_wasm", "ops_per_second": { - "deno": 1.0613709064323158, - "node": 1.2012405804543989, - "bun": 1.195773878261993 + "deno": 1.1138720591007718, + "node": 1.2508159971773587, + "bun": 1.2200565933011256 }, "mean_ns": { - "deno": 942177700.5, - "node": 832472708.8571428, - "bun": 836278512.3333334 + "deno": 897769175.4, + "node": 799478102.5, + "bun": 819634110 }, "files_iterated": { "deno": 4278, @@ -406,14 +406,14 @@ "group": "format/typescript", "name": "oxfmt", "ops_per_second": { - "deno": 0.9590165337310202, - "node": 0.9820591383199189, - "bun": 0.7248619281223401 + "deno": 0.9322639962497004, + "node": 0.9645611185407811, + "bun": 0.709778825189999 }, "mean_ns": { - "deno": 1042734890.2, - "node": 1018268616.4, - "bun": 1379573076.2 + "deno": 1072657534.8, + "node": 1036740939.25, + "bun": 1408889592.8 }, "files_iterated": { "deno": 4278, @@ -425,12 +425,12 @@ "group": "format/typescript", "name": "biome-wasm", "ops_per_second": { - "deno": 0.20819478378187434, - "node": 0.23773101059503382 + "deno": 0.1996797827689896, + "node": 0.23023295131637722 }, "mean_ns": { - "deno": 4803194306, - "node": 4206434816.8 + "deno": 5008018268.714286, + "node": 4343426926 }, "files_iterated": { "deno": 4278, @@ -441,14 +441,14 @@ "group": "parse/css", "name": "svelte/compiler", "ops_per_second": { - "deno": 196.09339787612726, - "node": 180.69565532784264, - "bun": 139.2377531889514 + "deno": 197.12363658904547, + "node": 170.34709376508636, + "bun": 134.824385441298 }, "mean_ns": { - "deno": 5099610.750952986, - "node": 5534167.372124492, - "bun": 7181960.1875 + "deno": 5072958.359046283, + "node": 5870367.247820673, + "bun": 7417055.874031007 }, "files_iterated": { "deno": 147, @@ -460,14 +460,14 @@ "group": "parse/css", "name": "tsv-json", "ops_per_second": { - "deno": 104.9187248165179, - "node": 109.02822783512269, - "bun": 130.71619431537164 + "deno": 104.39988929575249, + "node": 106.09139130333902, + "bun": 125.43816258744992 }, "mean_ns": { - "deno": 9531187.133171912, - "node": 9171936.661322646, - "bun": 7650161.521588947 + "deno": 9578554.218262807, + "node": 9425835.477459017, + "bun": 7972055.548109965 }, "files_iterated": { "deno": 147, @@ -479,14 +479,14 @@ "group": "parse/css", "name": "tsv_wasm-json", "ops_per_second": { - "deno": 85.67340098504212, - "node": 90.53716392160814, - "bun": 107.3852271258385 + "deno": 83.93164827102449, + "node": 87.99307101804118, + "bun": 103.51069419004973 }, "mean_ns": { - "deno": 11672234.188235294, - "node": 11045188.038647342, - "bun": 9312267.867424242 + "deno": 11914456.830049261, + "node": 11364531.188995216, + "bun": 9660837.537848605 }, "files_iterated": { "deno": 147, @@ -498,14 +498,14 @@ "group": "parse/css", "name": "tsv-internal", "ops_per_second": { - "deno": 254.04050316960635, - "node": 293.23265409749956, - "bun": 303.8517892883515 + "deno": 254.65845248614326, + "node": 285.65083157763087, + "bun": 298.72949767055616 }, "mean_ns": { - "deno": 3936380.1737251515, - "node": 3410261.394924663, - "bun": 3291078.200796813 + "deno": 3926828.2290940764, + "node": 3500777.4858454475, + "bun": 3347510.0644490644 }, "files_iterated": { "deno": 147, @@ -517,14 +517,14 @@ "group": "parse/css", "name": "tsv_wasm-internal", "ops_per_second": { - "deno": 180.15024042075325, - "node": 201.16271037577013, - "bun": 210.11449069147554 + "deno": 178.90052363025188, + "node": 189.6157341809795, + "bun": 203.85733475372683 }, "mean_ns": { - "deno": 5550922.372706422, - "node": 4971100.250797024, - "bun": 4759310.015739769 + "deno": 5589698.563805104, + "node": 5273823.9488372095, + "bun": 4905391.317943336 }, "files_iterated": { "deno": 147, @@ -536,14 +536,14 @@ "group": "format/css", "name": "prettier", "ops_per_second": { - "deno": 3.252481012247861, - "node": 3.1160491222799975, - "bun": 3.081552221965597 + "deno": 3.164976023546895, + "node": 2.214631425778389, + "bun": 3.0123278538411897 }, "mean_ns": { - "deno": 307457598.1333333, - "node": 320919202.73333335, - "bun": 324511781.06666666 + "deno": 315958159.73333335, + "node": 451542404.9166667, + "bun": 331969177.5 }, "files_iterated": { "deno": 153, @@ -555,14 +555,14 @@ "group": "format/css", "name": "tsv", "ops_per_second": { - "deno": 129.1982569566136, - "node": 150.4780792182806, - "bun": 150.3954905429447 + "deno": 143.49410362738362, + "node": 106.17342939854838, + "bun": 160.63543853916678 }, "mean_ns": { - "deno": 7740042.50177936, - "node": 6645486.207658321, - "bun": 6649135.531855956 + "deno": 6968927.466153846, + "node": 9418552.322033899, + "bun": 6225276.371727749 }, "files_iterated": { "deno": 153, @@ -574,14 +574,14 @@ "group": "format/css", "name": "tsv_wasm", "ops_per_second": { - "deno": 96.24415983732571, - "node": 108.74447899581955, - "bun": 112.25649893036211 + "deno": 96.83646245625317, + "node": 108.53067151269423, + "bun": 114.398840536358 }, "mean_ns": { - "deno": 10390240.838407494, - "node": 9195869.153398057, - "bun": 8908170.213114753 + "deno": 10326688.673202615, + "node": 9213985.190196078, + "bun": 8741347.336314848 }, "files_iterated": { "deno": 153, @@ -593,14 +593,14 @@ "group": "format/css", "name": "oxfmt", "ops_per_second": { - "deno": 3.6785927004424517, - "node": 3.4193116648996247, - "bun": 3.010706509761357 + "deno": 3.711810209370068, + "node": 3.198437196249042, + "bun": 2.7389695550942514 }, "mean_ns": { - "deno": 271843088.2222222, - "node": 292456522.8333333, - "bun": 332147951.5714286 + "deno": 269410326.3888889, + "node": 312652692.125, + "bun": 365100808.85714287 }, "files_iterated": { "deno": 153, @@ -612,12 +612,12 @@ "group": "format/css", "name": "biome-wasm", "ops_per_second": { - "deno": 15.825360061955019, - "node": 18.19883715903549 + "deno": 15.536680210086416, + "node": 16.79191135191826 }, "mean_ns": { - "deno": 63189715.5, - "node": 54948565.73863637 + "deno": 64363814.307692304, + "node": 59552482.0875 }, "files_iterated": { "deno": 153, From 062a2811e5e6b35cd7303a472e544343c0dd2602 Mon Sep 17 00:00:00 2001 From: Ryan Atkinson Date: Sun, 5 Jul 2026 11:13:23 -0400 Subject: [PATCH 019/218] wip --- src/routes/docs/benchmarks/+page.svelte | 4 +++- src/routes/docs/benchmarks/BenchmarksConformance.svelte | 6 +++--- src/routes/docs/benchmarks/benchmark_data.ts | 2 +- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/routes/docs/benchmarks/+page.svelte b/src/routes/docs/benchmarks/+page.svelte index 54da1c5..8f1f06f 100644 --- a/src/routes/docs/benchmarks/+page.svelte +++ b/src/routes/docs/benchmarks/+page.svelte @@ -164,7 +164,9 @@ Separate from the speed numbers above, this measures parse coverage: how much of a much larger, deliberately hard corpus each parser accepts - the real-world code above plus Prettier's format-test suites, Svelte's compiler test suite, CSS extracted from - web-platform-tests, and test262's expected-valid strict-mode tests. + web-platform-tests, and test262's expected-valid strict-mode tests.

    {row.files_processed.toLocaleString('en-US')}/{row.files_total.toLocaleString( + >{row.files_processed.toLocaleString('en-US')} / {row.files_total.toLocaleString( 'en-US', )} @@ -78,13 +78,13 @@ transition: width 0.3s ease; } .coverage-count { - font-size: var(--font_size_xs); + font-size: var(--font_size_sm); text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; } .coverage-percent { - font-size: var(--font_size_sm); + font-size: var(--font_size_md); font-weight: 700; text-align: right; font-variant-numeric: tabular-nums; diff --git a/src/routes/docs/benchmarks/benchmark_data.ts b/src/routes/docs/benchmarks/benchmark_data.ts index 8f17b27..5bfab7a 100644 --- a/src/routes/docs/benchmarks/benchmark_data.ts +++ b/src/routes/docs/benchmarks/benchmark_data.ts @@ -608,7 +608,7 @@ export const format_coverage = ( total: number | null | undefined, ): string | undefined => { if (processed == null || total == null) return undefined; - return `${processed}/${total}`; + return `${processed} / ${total}`; }; /** From 7686c6173fe370976d20a939a0d40425d9450536 Mon Sep 17 00:00:00 2001 From: Ryan Atkinson Date: Sun, 5 Jul 2026 12:40:38 -0400 Subject: [PATCH 020/218] update-benchmarks --- src/routes/docs/benchmarks/+page.svelte | 19 +- src/routes/docs/benchmarks/benchmark_data.ts | 39 +- .../benchmarks/benchmarks_conformance.json | 444 +++++++++--------- src/test/benchmark_data.test.ts | 3 +- 4 files changed, 258 insertions(+), 247 deletions(-) diff --git a/src/routes/docs/benchmarks/+page.svelte b/src/routes/docs/benchmarks/+page.svelte index 8f1f06f..f8e20ea 100644 --- a/src/routes/docs/benchmarks/+page.svelte +++ b/src/routes/docs/benchmarks/+page.svelte @@ -177,8 +177,12 @@ native or wasm, so each tool appears once.
  • - 100% isn't the target: some suite inputs are intentionally invalid or use syntax that's - out of scope by design, so read the numbers relative to each other. + For Svelte, the corpus excludes the files svelte/compiler itself rejects, so its number is + 100% by construction and the rest read as drop-in fidelity against it - higher is strictly + better. For TypeScript and CSS the canonical parser isn't a clean validity oracle + (acorn-typescript trails modern syntax, Svelte's CSS parser is lenient), so those suites + keep intentionally-invalid and out-of-scope inputs - read them relative to each other, not + as an absolute target.
  • Accepting a file says nothing about producing the right AST - tsv's output is @@ -219,14 +223,13 @@ Biome's native engine only ships as the biome CLI binary, not an embeddable library - @biomejs/js-api wires up wasm builds only. Every other native entry here (tsv, oxc-parser, oxfmt) is measured as an in-process library call, so a CLI binary - invoked as a subprocess isn't a comparable artifact and is excluded; only Biome's wasm - build is shown + invoked as a subprocess isn't a comparable artifact and is excluded; therefore only + Biome's wasm build is included
  • +
  • tsv and tsv_wasm include a parser and formatter for Svelte, TypeScript/JS, and CSS
  • - tsv and tsv_wasm include a parser and formatter for Svelte/HTML, TypeScript/JS, and CSS -
  • -
  • - oxc-parser only parses TypeScript and JS, not CSS or HTML; oxfmt is its separate formatter + oxc-parser only parses TypeScript and JS, not CSS or Svelte; oxfmt is its separate + formatter
  • the oxc-parser + oxfmt entry under Full toolchain sums oxc's separate parser diff --git a/src/routes/docs/benchmarks/benchmark_data.ts b/src/routes/docs/benchmarks/benchmark_data.ts index 5bfab7a..4b09f0c 100644 --- a/src/routes/docs/benchmarks/benchmark_data.ts +++ b/src/routes/docs/benchmarks/benchmark_data.ts @@ -33,18 +33,23 @@ export interface CorpusSource { export interface BaselineEntry { name: string; group: string; - mean_ns: number; - p50_ns: number; - p75_ns: number; - p90_ns: number; - p95_ns: number; - p99_ns: number; - min_ns: number; - max_ns: number; - std_dev_ns: number; - cv: number; - ops_per_second: number; - sample_size: number; + // Timing stats are `null` on a coverage-only report (the conformance surface + // the site refreshes from — parse coverage measured, timed phase skipped). A + // perf report always carries real numbers, and only the perf path + // (`derive_benchmark_groups`) reads these, so the nulls are unreachable there + // but must be expressed for the shared cast to stay sound. + mean_ns: number | null; + p50_ns: number | null; + p75_ns: number | null; + p90_ns: number | null; + p95_ns: number | null; + p99_ns: number | null; + min_ns: number | null; + max_ns: number | null; + std_dev_ns: number | null; + cv: number | null; + ops_per_second: number | null; + sample_size: number | null; // Per-implementation preflight coverage: files this impl processed / the // language's total discovered files. Present from baseline `version` 3 on; // absent (or `null`) in older baselines. @@ -176,12 +181,14 @@ export const derive_benchmark_groups = (baseline: BenchmarkBaseline): Array e.mean_ns)); + // `?? 0` coerces the coverage-only null (unreachable on a perf report, the + // only kind this runs on) so the display entry's `mean_ns` stays a number. + const slowest = Math.max(...entries.map((e) => e.mean_ns ?? 0)); const display_entries: Array = entries.map((e) => ({ name: e.name, - mean_ns: e.mean_ns, - bar_fraction: slowest > 0 ? e.mean_ns / slowest : 0, + mean_ns: e.mean_ns ?? 0, + bar_fraction: slowest > 0 ? (e.mean_ns ?? 0) / slowest : 0, category: categorize_name(e.name), files_processed: e.files_processed ?? null, files_total: e.files_total ?? null, @@ -333,7 +340,7 @@ export const derive_conformance_groups = (baseline: BenchmarkBaseline): Array `${(fraction * 100).toFixed(1)}%`; diff --git a/src/routes/docs/benchmarks/benchmarks_conformance.json b/src/routes/docs/benchmarks/benchmarks_conformance.json index 26efb39..8d97da4 100644 --- a/src/routes/docs/benchmarks/benchmarks_conformance.json +++ b/src/routes/docs/benchmarks/benchmarks_conformance.json @@ -2,10 +2,10 @@ "version": 6, "runtime": "node", "corpus_kind": "conformance", - "timestamp": "2026-07-05T15:06:16.483Z", - "git_commit": "ade06e02", + "timestamp": "2026-07-05T16:36:58.498Z", + "git_commit": "bbd52a6b", "corpus": { - "svelte": 5355, + "svelte": 5217, "typescript": 46708, "css": 22672 }, @@ -183,9 +183,9 @@ }, { "path": "../prettier-plugin-svelte/test", - "files": 309, + "files": 302, "by_language": { - "svelte": 309, + "svelte": 302, "typescript": 0, "css": 0 } @@ -219,18 +219,18 @@ }, { "path": "../prettier/tests/format/html", - "files": 124, + "files": 84, "by_language": { - "svelte": 124, + "svelte": 84, "typescript": 0, "css": 0 } }, { "path": "../svelte/packages/svelte/tests", - "files": 4432, + "files": 4341, "by_language": { - "svelte": 4117, + "svelte": 4026, "typescript": 135, "css": 180 } @@ -337,118 +337,118 @@ { "name": "svelte/compiler", "group": "parse/svelte", - "mean_ns": 711837306, - "p50_ns": 714220953, - "p75_ns": 715413109, - "p90_ns": 726956792.8, - "p95_ns": 730804687.4, - "p99_ns": 733883003.08, - "min_ns": 696738177, - "max_ns": 734652582, - "std_dev_ns": 15443531.08049325, - "cv": 0.021695310080437468, - "ops_per_second": 1.4048153862843484, - "sample_size": 5, + "mean_ns": null, + "p50_ns": null, + "p75_ns": null, + "p90_ns": null, + "p95_ns": null, + "p99_ns": null, + "min_ns": null, + "max_ns": null, + "std_dev_ns": null, + "cv": null, + "ops_per_second": null, + "sample_size": null, "files_processed": 5217, - "files_total": 5355, + "files_total": 5217, "files_iterated": 5209, "runtime": "node" }, { "name": "tsv-json", "group": "parse/svelte", - "mean_ns": 355459711.2, - "p50_ns": 354466667, - "p75_ns": 356068214, - "p90_ns": 358833872.6, - "p95_ns": 359755758.8, - "p99_ns": 360493267.76, - "min_ns": 352185836, - "max_ns": 360677645, - "std_dev_ns": 3230077.3328286894, - "cv": 0.009087042022074004, - "ops_per_second": 2.813258348250186, - "sample_size": 5, - "files_processed": 5241, - "files_total": 5355, + "mean_ns": null, + "p50_ns": null, + "p75_ns": null, + "p90_ns": null, + "p95_ns": null, + "p99_ns": null, + "min_ns": null, + "max_ns": null, + "std_dev_ns": null, + "cv": null, + "ops_per_second": null, + "sample_size": null, + "files_processed": 5209, + "files_total": 5217, "files_iterated": 5209, "runtime": "node" }, { "name": "tsv_wasm-json", "group": "parse/svelte", - "mean_ns": 386411127.3333333, - "p50_ns": 386422999, - "p75_ns": 386439730, - "p90_ns": 389706363.4, - "p95_ns": 390795241.2, - "p99_ns": 391666343.44, - "min_ns": 386370653, - "max_ns": 391884119, - "std_dev_ns": 36036.23640633596, - "cv": 0.00009325879576767388, - "ops_per_second": 2.58791719301955, - "sample_size": 3, - "files_processed": 5241, - "files_total": 5355, + "mean_ns": null, + "p50_ns": null, + "p75_ns": null, + "p90_ns": null, + "p95_ns": null, + "p99_ns": null, + "min_ns": null, + "max_ns": null, + "std_dev_ns": null, + "cv": null, + "ops_per_second": null, + "sample_size": null, + "files_processed": 5209, + "files_total": 5217, "files_iterated": 5209, "runtime": "node" }, { "name": "tsv-internal", "group": "parse/svelte", - "mean_ns": 37838861, - "p50_ns": 38017131, - "p75_ns": 38134240, - "p90_ns": 39168125.8, - "p95_ns": 39512754.4, - "p99_ns": 39788457.28, - "min_ns": 37396175, - "max_ns": 39857383, - "std_dev_ns": 324529.684572408, - "cv": 0.00857662403137367, - "ops_per_second": 26.427856800446502, - "sample_size": 4, - "files_processed": 5241, - "files_total": 5355, + "mean_ns": null, + "p50_ns": null, + "p75_ns": null, + "p90_ns": null, + "p95_ns": null, + "p99_ns": null, + "min_ns": null, + "max_ns": null, + "std_dev_ns": null, + "cv": null, + "ops_per_second": null, + "sample_size": null, + "files_processed": 5209, + "files_total": 5217, "files_iterated": 5209, "runtime": "node" }, { "name": "tsv_wasm-internal", "group": "parse/svelte", - "mean_ns": 52819275.333333336, - "p50_ns": 53183599, - "p75_ns": 78185568, - "p90_ns": 79334740.2, - "p95_ns": 79717797.6, - "p99_ns": 80024243.52, - "min_ns": 52405770, - "max_ns": 80100855, - "std_dev_ns": 391239.8440373032, - "cv": 0.007407141456755247, - "ops_per_second": 18.932482388089813, - "sample_size": 3, - "files_processed": 5241, - "files_total": 5355, + "mean_ns": null, + "p50_ns": null, + "p75_ns": null, + "p90_ns": null, + "p95_ns": null, + "p99_ns": null, + "min_ns": null, + "max_ns": null, + "std_dev_ns": null, + "cv": null, + "ops_per_second": null, + "sample_size": null, + "files_processed": 5209, + "files_total": 5217, "files_iterated": 5209, "runtime": "node" }, { "name": "acorn-typescript", "group": "parse/typescript", - "mean_ns": 10546714871.285715, - "p50_ns": 10531234774, - "p75_ns": 10623521053, - "p90_ns": 10655027623.8, - "p95_ns": 10669469424.9, - "p99_ns": 10681022865.78, - "min_ns": 10439500875, - "max_ns": 10683911226, - "std_dev_ns": 97599727.07873665, - "cv": 0.009254040549105941, - "ops_per_second": 0.0948162543696503, - "sample_size": 7, + "mean_ns": null, + "p50_ns": null, + "p75_ns": null, + "p90_ns": null, + "p95_ns": null, + "p99_ns": null, + "min_ns": null, + "max_ns": null, + "std_dev_ns": null, + "cv": null, + "ops_per_second": null, + "sample_size": null, "files_processed": 46030, "files_total": 46708, "files_iterated": 45959, @@ -457,18 +457,18 @@ { "name": "tsv-json", "group": "parse/typescript", - "mean_ns": 5764540928.142858, - "p50_ns": 5760753423, - "p75_ns": 5773887260, - "p90_ns": 5807996417.6, - "p95_ns": 5827958654.3, - "p99_ns": 5843928443.66, - "min_ns": 5710986387, - "max_ns": 5847920891, - "std_dev_ns": 43250996.46975181, - "cv": 0.007502938570285394, - "ops_per_second": 0.1734743516379485, - "sample_size": 7, + "mean_ns": null, + "p50_ns": null, + "p75_ns": null, + "p90_ns": null, + "p95_ns": null, + "p99_ns": null, + "min_ns": null, + "max_ns": null, + "std_dev_ns": null, + "cv": null, + "ops_per_second": null, + "sample_size": null, "files_processed": 46464, "files_total": 46708, "files_iterated": 45959, @@ -477,18 +477,18 @@ { "name": "tsv_wasm-json", "group": "parse/typescript", - "mean_ns": 6126542016.428572, - "p50_ns": 6130197740, - "p75_ns": 6141894028.5, - "p90_ns": 6151765711.6, - "p95_ns": 6154230910.3, - "p99_ns": 6156203069.26, - "min_ns": 6094006411, - "max_ns": 6156696109, - "std_dev_ns": 22744048.227786593, - "cv": 0.003712379375967308, - "ops_per_second": 0.16322421315620775, - "sample_size": 7, + "mean_ns": null, + "p50_ns": null, + "p75_ns": null, + "p90_ns": null, + "p95_ns": null, + "p99_ns": null, + "min_ns": null, + "max_ns": null, + "std_dev_ns": null, + "cv": null, + "ops_per_second": null, + "sample_size": null, "files_processed": 46464, "files_total": 46708, "files_iterated": 45959, @@ -497,18 +497,18 @@ { "name": "tsv-internal", "group": "parse/typescript", - "mean_ns": 450847760.4, - "p50_ns": 450898135, - "p75_ns": 451459309, - "p90_ns": 451880158.6, - "p95_ns": 452020441.8, - "p99_ns": 452132668.36, - "min_ns": 449571935, - "max_ns": 452160725, - "std_dev_ns": 1026745.3459499099, - "cv": 0.0022773659672590224, - "ops_per_second": 2.2180436232239074, - "sample_size": 5, + "mean_ns": null, + "p50_ns": null, + "p75_ns": null, + "p90_ns": null, + "p95_ns": null, + "p99_ns": null, + "min_ns": null, + "max_ns": null, + "std_dev_ns": null, + "cv": null, + "ops_per_second": null, + "sample_size": null, "files_processed": 46464, "files_total": 46708, "files_iterated": 45959, @@ -517,18 +517,18 @@ { "name": "tsv_wasm-internal", "group": "parse/typescript", - "mean_ns": 636976103, - "p50_ns": 637059871, - "p75_ns": 637081070, - "p90_ns": 638550510.2, - "p95_ns": 639040323.6, - "p99_ns": 639432174.32, - "min_ns": 636787368, - "max_ns": 639530137, - "std_dev_ns": 163792.62672354942, - "cv": 0.0002571409287603203, - "ops_per_second": 1.569917608039371, - "sample_size": 3, + "mean_ns": null, + "p50_ns": null, + "p75_ns": null, + "p90_ns": null, + "p95_ns": null, + "p99_ns": null, + "min_ns": null, + "max_ns": null, + "std_dev_ns": null, + "cv": null, + "ops_per_second": null, + "sample_size": null, "files_processed": 46464, "files_total": 46708, "files_iterated": 45959, @@ -537,18 +537,18 @@ { "name": "oxc-parser", "group": "parse/typescript", - "mean_ns": 3712865724.5, - "p50_ns": 3714305438, - "p75_ns": 3735694100, - "p90_ns": 3853014017, - "p95_ns": 3892120656, - "p99_ns": 3923405967.2, - "min_ns": 3697862054, - "max_ns": 3931227295, - "std_dev_ns": 16674802.163212162, - "cv": 0.004491086777844007, - "ops_per_second": 0.269333736849497, - "sample_size": 4, + "mean_ns": null, + "p50_ns": null, + "p75_ns": null, + "p90_ns": null, + "p95_ns": null, + "p99_ns": null, + "min_ns": null, + "max_ns": null, + "std_dev_ns": null, + "cv": null, + "ops_per_second": null, + "sample_size": null, "files_processed": 46465, "files_total": 46708, "files_iterated": 45959, @@ -557,18 +557,18 @@ { "name": "oxc-parser-wasm", "group": "parse/typescript", - "mean_ns": 4347237533.2, - "p50_ns": 4346363747, - "p75_ns": 4362145916, - "p90_ns": 4417627440.2, - "p95_ns": 4436121281.6, - "p99_ns": 4450916354.72, - "min_ns": 4284843015, - "max_ns": 4454615123, - "std_dev_ns": 69154051.2776857, - "cv": 0.015907585161738663, - "ops_per_second": 0.23003113870888495, - "sample_size": 5, + "mean_ns": null, + "p50_ns": null, + "p75_ns": null, + "p90_ns": null, + "p95_ns": null, + "p99_ns": null, + "min_ns": null, + "max_ns": null, + "std_dev_ns": null, + "cv": null, + "ops_per_second": null, + "sample_size": null, "files_processed": 46708, "files_total": 46708, "files_iterated": 45959, @@ -577,18 +577,18 @@ { "name": "svelte/compiler", "group": "parse/css", - "mean_ns": 240630028.8, - "p50_ns": 241029027, - "p75_ns": 242335570, - "p90_ns": 243382705, - "p95_ns": 243731750, - "p99_ns": 244010986, - "min_ns": 237629418, - "max_ns": 244080795, - "std_dev_ns": 2761611.3235657727, - "cv": 0.011476586431617352, - "ops_per_second": 4.155757305050034, - "sample_size": 5, + "mean_ns": null, + "p50_ns": null, + "p75_ns": null, + "p90_ns": null, + "p95_ns": null, + "p99_ns": null, + "min_ns": null, + "max_ns": null, + "std_dev_ns": null, + "cv": null, + "ops_per_second": null, + "sample_size": null, "files_processed": 22433, "files_total": 22672, "files_iterated": 22409, @@ -597,18 +597,18 @@ { "name": "tsv-json", "group": "parse/css", - "mean_ns": 454197684, - "p50_ns": 453949601, - "p75_ns": 455880395, - "p90_ns": 457332746, - "p95_ns": 457816863, - "p99_ns": 458204156.6, - "min_ns": 450319049, - "max_ns": 458300980, - "std_dev_ns": 3062970.3310990464, - "cv": 0.006743694296554463, - "ops_per_second": 2.201684498241519, - "sample_size": 5, + "mean_ns": null, + "p50_ns": null, + "p75_ns": null, + "p90_ns": null, + "p95_ns": null, + "p99_ns": null, + "min_ns": null, + "max_ns": null, + "std_dev_ns": null, + "cv": null, + "ops_per_second": null, + "sample_size": null, "files_processed": 22478, "files_total": 22672, "files_iterated": 22409, @@ -617,18 +617,18 @@ { "name": "tsv_wasm-json", "group": "parse/css", - "mean_ns": 535892000.6, - "p50_ns": 535585178, - "p75_ns": 537001487, - "p90_ns": 537083391.2, - "p95_ns": 537110692.6, - "p99_ns": 537132533.72, - "min_ns": 534584622, - "max_ns": 537137994, - "std_dev_ns": 1133173.9163799174, - "cv": 0.0021145565059959535, - "ops_per_second": 1.8660476343747834, - "sample_size": 5, + "mean_ns": null, + "p50_ns": null, + "p75_ns": null, + "p90_ns": null, + "p95_ns": null, + "p99_ns": null, + "min_ns": null, + "max_ns": null, + "std_dev_ns": null, + "cv": null, + "ops_per_second": null, + "sample_size": null, "files_processed": 22478, "files_total": 22672, "files_iterated": 22409, @@ -637,18 +637,18 @@ { "name": "tsv-internal", "group": "parse/css", - "mean_ns": 108869208, - "p50_ns": 108826588, - "p75_ns": 109251275, - "p90_ns": 109666637, - "p95_ns": 109805091, - "p99_ns": 109915854.2, - "min_ns": 108051914, - "max_ns": 109943545, - "std_dev_ns": 762522.368359447, - "cv": 0.007004022371132222, - "ops_per_second": 9.185333652835979, - "sample_size": 5, + "mean_ns": null, + "p50_ns": null, + "p75_ns": null, + "p90_ns": null, + "p95_ns": null, + "p99_ns": null, + "min_ns": null, + "max_ns": null, + "std_dev_ns": null, + "cv": null, + "ops_per_second": null, + "sample_size": null, "files_processed": 22478, "files_total": 22672, "files_iterated": 22409, @@ -657,18 +657,18 @@ { "name": "tsv_wasm-internal", "group": "parse/css", - "mean_ns": 169215491.4, - "p50_ns": 168845557, - "p75_ns": 169885669, - "p90_ns": 170432503.6, - "p95_ns": 170614781.8, - "p99_ns": 170760604.36, - "min_ns": 167811576, - "max_ns": 170797060, - "std_dev_ns": 1149642.567479258, - "cv": 0.006793955789554017, - "ops_per_second": 5.909624418701419, - "sample_size": 5, + "mean_ns": null, + "p50_ns": null, + "p75_ns": null, + "p90_ns": null, + "p95_ns": null, + "p99_ns": null, + "min_ns": null, + "max_ns": null, + "std_dev_ns": null, + "cv": null, + "ops_per_second": null, + "sample_size": null, "files_processed": 22478, "files_total": 22672, "files_iterated": 22409, diff --git a/src/test/benchmark_data.test.ts b/src/test/benchmark_data.test.ts index 318fbc2..117d1c5 100644 --- a/src/test/benchmark_data.test.ts +++ b/src/test/benchmark_data.test.ts @@ -205,7 +205,8 @@ describe('benchmarks.json shape', () => { // Shape gate for the committed conformance report `benchmarks_conformance.json` // (tsv's `report.conformance.node.json` — the parse-coverage surface over the -// full fixtures-included corpus), consumed by the Parse conformance section. +// fixtures-included corpus, Svelte set minus canonical-rejects), consumed by the +// Parse conformance section. describe('benchmarks_conformance.json shape', () => { test('report is the conformance surface at the current version', () => { assert.isAtLeast(benchmarks_conformance_json.version, 6); From 20f97ad9d48fffe7d693a4a56930c1c4557e81d8 Mon Sep 17 00:00:00 2001 From: Ryan Atkinson Date: Sun, 5 Jul 2026 20:59:48 -0400 Subject: [PATCH 021/218] wip --- src/routes/docs/benchmarks/+page.svelte | 5 ++++- src/routes/docs/benchmarks/benchmark_data.ts | 23 +++++++++++++++++--- 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/src/routes/docs/benchmarks/+page.svelte b/src/routes/docs/benchmarks/+page.svelte index f8e20ea..97a68ca 100644 --- a/src/routes/docs/benchmarks/+page.svelte +++ b/src/routes/docs/benchmarks/+page.svelte @@ -30,6 +30,9 @@ const conformance_groups = derive_conformance_groups(benchmarks_conformance_json); const corpus = $derived(benchmarks_json.corpus); + // Derived from the report so the "What's measured" figure can't drift from the + // copied data (the report carries per-language file counts, not bytes). + const corpus_file_count = $derived(Object.values(corpus).reduce((sum, n) => sum + n, 0)); const format_groups = groups.filter((g) => g.operation === 'format'); const parse_groups = groups.filter((g) => g.operation === 'parse'); @@ -265,7 +268,7 @@ at once, which most of these tools (tsv included) can do.

    - What's measured: around 2,900 files (~17 MB) of .svelte, + What's measured: {corpus_file_count.toLocaleString('en-US')} files of .svelte, .ts/.js, and .css - real-world code only, from two sources: the fuz.dev libraries and apps, and upstream framework source (Svelte, SvelteKit, and the svelte.dev site). Test files count as real code and stay in; fixture files (the formatter diff --git a/src/routes/docs/benchmarks/benchmark_data.ts b/src/routes/docs/benchmarks/benchmark_data.ts index 4b09f0c..f64fce9 100644 --- a/src/routes/docs/benchmarks/benchmark_data.ts +++ b/src/routes/docs/benchmarks/benchmark_data.ts @@ -299,10 +299,25 @@ const CONFORMANCE_ENGINE_NAMES: Record = { 'oxc-parser': 'oxc-parser', }; +/** + * Fixed row order for the conformance groups, applied across every language so a + * reader scans one tool down the page and tsv stays prominent (leading each + * group). Values are the post-mapping display names from `CONFORMANCE_ENGINE_NAMES`; + * a tool absent from a language (e.g. `oxc-parser` under svelte/css) simply doesn't + * appear. Any unmapped name sorts last. + */ +const CONFORMANCE_ROW_ORDER = ['tsv', 'svelte/compiler', 'acorn-typescript', 'oxc-parser']; + +const conformance_row_rank = (name: string): number => { + const index = CONFORMANCE_ROW_ORDER.indexOf(name); + return index === -1 ? CONFORMANCE_ROW_ORDER.length : index; +}; + /** * Derives per-language parse-coverage groups from a conformance report - * (`corpus_kind: 'conformance'` — parse groups only). Rows sort by coverage - * descending; entries without coverage data are dropped. + * (`corpus_kind: 'conformance'` — parse groups only). Rows follow the fixed + * `CONFORMANCE_ROW_ORDER` (tsv first, same order in every group); entries without + * coverage data are dropped. */ export const derive_conformance_groups = (baseline: BenchmarkBaseline): Array => { const by_language: Map> = new Map(); @@ -328,7 +343,9 @@ export const derive_conformance_groups = (baseline: BenchmarkBaseline): Array = []; for (const [language, rows] of by_language) { - rows.sort((a, b) => b.coverage_fraction - a.coverage_fraction || a.name.localeCompare(b.name)); + rows.sort( + (a, b) => conformance_row_rank(a.name) - conformance_row_rank(b.name) || a.name.localeCompare(b.name), + ); result.push({ language, files_total: Math.max(0, ...rows.map((r) => r.files_total)), From 8105c16db9bc7f804af8c19a7c979c682f64eabb Mon Sep 17 00:00:00 2001 From: Ryan Atkinson Date: Sun, 5 Jul 2026 23:15:09 -0400 Subject: [PATCH 022/218] add no-locations variants --- src/routes/docs/benchmarks/+page.svelte | 22 ++++++++++++++++---- src/routes/docs/benchmarks/benchmark_data.ts | 3 +++ src/test/benchmark_data.test.ts | 9 ++++++-- 3 files changed, 28 insertions(+), 6 deletions(-) diff --git a/src/routes/docs/benchmarks/+page.svelte b/src/routes/docs/benchmarks/+page.svelte index 97a68ca..e1d809f 100644 --- a/src/routes/docs/benchmarks/+page.svelte +++ b/src/routes/docs/benchmarks/+page.svelte @@ -125,10 +125,16 @@

    - The parse entries that build a full JS AST are directly comparable: tsv and oxc-parser both - serialize the AST to JSON in Rust and deserialize it in JS, native and wasm alike. The - tsv-internal and tsv_wasm-internal entries are tsv's parse-only numbers - they build the - native AST but skip JS-side materialization, so they show raw in-engine speed rather than a + The parse entries that build a full JS AST are comparable in mechanism: tsv and oxc-parser + both serialize the AST to JSON in Rust and deserialize it in JS, native and wasm alike. But + the deliverables differ — tsv's default wire (tsv-json / tsv_wasm-json) + carries a per-node loc (line/column) object that oxc-parser's default span-only + AST omits, and that loc is roughly half the wire bytes and most of its JSON.parse + cost. The tsv-json-no-locations / tsv_wasm-json-no-locations entries + drop it, emitting the same span-only shape oxc does, so those are the payload-matched, + apples-to-apples comparison with oxc-parser (line/column stays derivable from the + offsets plus source, so nothing is lost). The tsv-internal and tsv_wasm-internal entries build + the native AST but skip JS-side materialization, so they show raw in-engine speed rather than a cross-tool comparison.

    {#each parse_groups as group (group.language)} @@ -151,6 +157,14 @@ oxc-parser only parses TypeScript and JS, so it's shown grayed-out under Svelte and CSS — holding its slot so the three parse groups line up entry-for-entry.
  • +
  • + tsv-json-no-locations / tsv_wasm-json-no-locations are the fair, + payload-matched comparison with oxc-parser: they emit tsv's span-only wire (offsets, no + per-node loc), matching oxc's default AST shape. The plain + tsv-json entries carry the richer loc-bearing drop-in AST that + Svelte's compiler consumes for sourcemaps — a strictly larger deliverable, so a slower + number that isn't an engine-speed difference. +
  • tsv internal (napi) and tsv_wasm internal aren't a fair comparison to the other entries - they skip JS-side AST materialization entirely, so diff --git a/src/routes/docs/benchmarks/benchmark_data.ts b/src/routes/docs/benchmarks/benchmark_data.ts index f64fce9..e132313 100644 --- a/src/routes/docs/benchmarks/benchmark_data.ts +++ b/src/routes/docs/benchmarks/benchmark_data.ts @@ -131,9 +131,11 @@ const CATEGORY_BY_NAME: Record = { 'acorn-typescript': 'canonical', tsv: 'tsv_native', 'tsv-json': 'tsv_native_json', + 'tsv-json-no-locations': 'tsv_native_json', 'tsv-internal': 'tsv_native', tsv_wasm: 'tsv_wasm', 'tsv_wasm-json': 'tsv_wasm_json', + 'tsv_wasm-json-no-locations': 'tsv_wasm_json', 'tsv_wasm-internal': 'tsv_wasm', 'biome-wasm': 'biome', 'oxc-parser': 'oxc', @@ -696,6 +698,7 @@ const HYPHENATED_NAMES = ['acorn-typescript', 'oxc-parser']; const LABEL_OVERRIDES: Record = { tsv: 'tsv (napi)', 'tsv-json': 'tsv json (napi)', + 'tsv-json-no-locations': 'tsv json no-locations (napi)', 'tsv-internal': 'tsv internal (napi)', 'oxc-parser': 'oxc-parser (napi)', oxfmt: 'oxfmt (napi)', diff --git a/src/test/benchmark_data.test.ts b/src/test/benchmark_data.test.ts index 117d1c5..b654aba 100644 --- a/src/test/benchmark_data.test.ts +++ b/src/test/benchmark_data.test.ts @@ -100,10 +100,15 @@ describe('benchmarks.json shape', () => { assert.ok(entry.disabled, `${language} biome entry should be disabled`); assert.strictEqual(entry.bar_fraction, 0, `${language} biome bar`); - // slotted just after the JS-materializing `*-json` entries + // slotted just after the JS-materializing `*-json` entries (the + // `*-json-no-locations` span-only variants materialize the same way, so + // they belong to the same group) const names = group.entries.map((e) => e.name); const first_biome = names.findIndex((n) => n.includes('biome')); - const last_json = names.reduce((idx, n, i) => (n.endsWith('-json') ? i : idx), -1); + const last_json = names.reduce( + (idx, n, i) => (n.endsWith('-json') || n.endsWith('-no-locations') ? i : idx), + -1, + ); assert.strictEqual( first_biome, last_json + 1, From ea99405726522cbce226e87d1bdbe255423c77d8 Mon Sep 17 00:00:00 2001 From: Ryan Atkinson Date: Mon, 6 Jul 2026 15:01:19 -0400 Subject: [PATCH 023/218] merge main --- CLAUDE.md | 16 +++-- package-lock.json | 9 ++- package.json | 3 +- src/routes/docs/benchmarks/+page.svelte | 20 ++++--- .../benchmarks/BenchmarksCrossRuntime.svelte | 18 +++--- .../docs/benchmarks/BenchmarksGroup.svelte | 6 +- .../docs/benchmarks/BenchmarksMeta.svelte | 3 + src/routes/docs/benchmarks/benchmark_data.ts | 58 ++++++++++++++++--- src/test/benchmark_data.test.ts | 16 ++++- 9 files changed, 106 insertions(+), 43 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index f82f0f0..cdf2e3e 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -89,19 +89,23 @@ npm run update-benchmarks ``` Step 1 writes the per-runtime `benches/js/results/report..{json,md}` -siblings plus the composed cross-runtime `report.{json,md}` (committed to tsv). -Step 2 copies two of them: `report.node.json` → `benchmarks.json` and the -composed `report.json` → `benchmarks_cross_runtime.json`. Note the script's -source paths are hardcoded to `../tsv` — if the reports were generated in a -different worktree, copy them into `~/dev/tsv` (or copy manually) first. +siblings, the composed cross-runtime `report.{json,md}`, and the conformance +coverage report `report.conformance.node.json` (committed to tsv). +Step 2 copies three of them — `report.node.json` → `benchmarks.json`, the +composed `report.json` → `benchmarks_cross_runtime.json`, and +`report.conformance.node.json` → `benchmarks_conformance.json` — then runs +`gro format` over the copies. Note the script's source paths are hardcoded to +`../tsv` — if the reports were generated in a different worktree, copy them +into `~/dev/tsv` (or copy manually) first. The JSON formats match the types in `benchmark_data.ts`. Key files in `src/routes/docs/benchmarks/`: - `benchmarks.json` — per-runtime Node report (copied from tsv) - `benchmarks_cross_runtime.json` — composed cross-runtime report (copied from tsv) +- `benchmarks_conformance.json` — conformance parse-coverage report (copied from tsv) - `benchmark_data.ts` — TypeScript types matching the JSON format -- `benchmarks.ts` — re-exports the JSON with types +- `benchmarks.ts`, `benchmarks_cross_runtime.ts`, `benchmarks_conformance.ts` — re-export the JSON with types - `BenchmarksBar.svelte`, `BenchmarksGroup.svelte`, etc. — visualization components - `BenchmarksBaselineGroup.svelte` — shared interactive column behind the format, parse, and binary-size groups: hovering a row re-baselines that group's ratios (each of the three groups per section is independent), restoring the default anchor (the canonical reference — Prettier for format, the JS baseline for parse — and the smallest build for size) on mouseleave. `benchmark_data.ts`'s `compute_baseline_ratio`/`format_baseline_ratio`/`baseline_ratio_color` carry the per-`BaselineDirection` (`speed`/`size`) formulas it and the derivations share diff --git a/package-lock.json b/package-lock.json index 467de13..6dc96ec 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,7 +12,7 @@ "@fuzdev/blake3_wasm": "^0.1.1", "@fuzdev/fuz_code": "^0.46.3", "@fuzdev/fuz_css": "^0.63.2", - "@fuzdev/fuz_ui": "^0.206.4", + "@fuzdev/fuz_ui": "^0.206.5", "@fuzdev/fuz_util": "^0.65.2", "@fuzdev/gro": "^0.206.0", "@fuzdev/mdz": "^0.2.0", @@ -28,7 +28,6 @@ "eslint": "^9.39.1", "eslint-plugin-svelte": "^3.13.1", "esm-env": "^1.2.2", - "magic-string": "^0.30.21", "svelte": "^5.56.0", "svelte-check": "^4.3.6", "svelte-docinfo": "^0.5.4", @@ -776,9 +775,9 @@ } }, "node_modules/@fuzdev/fuz_ui": { - "version": "0.206.4", - "resolved": "https://registry.npmjs.org/@fuzdev/fuz_ui/-/fuz_ui-0.206.4.tgz", - "integrity": "sha512-+NhAi+sUDIkhBO/GCWPOEdEwmki03IDvmRCOR14YM35I5wByfTnAb+R2rEqEgXeCQgbLvOXr7FPrJz5zQ7ddLA==", + "version": "0.206.5", + "resolved": "https://registry.npmjs.org/@fuzdev/fuz_ui/-/fuz_ui-0.206.5.tgz", + "integrity": "sha512-P+9U7xuGs1O1NrusiItcCQF/Sx7HPs/Tukg6cyWqDOatdRtro/nIVlzASZvk7/34fzGrwXYiHobRmY1jBchxHA==", "dev": true, "license": "MIT", "engines": { diff --git a/package.json b/package.json index 12ebfe8..6845c4c 100644 --- a/package.json +++ b/package.json @@ -26,7 +26,7 @@ "@fuzdev/blake3_wasm": "^0.1.1", "@fuzdev/fuz_code": "^0.46.3", "@fuzdev/fuz_css": "^0.63.2", - "@fuzdev/fuz_ui": "^0.206.4", + "@fuzdev/fuz_ui": "^0.206.5", "@fuzdev/fuz_util": "^0.65.2", "@fuzdev/gro": "^0.206.0", "@fuzdev/mdz": "^0.2.0", @@ -42,7 +42,6 @@ "eslint": "^9.39.1", "eslint-plugin-svelte": "^3.13.1", "esm-env": "^1.2.2", - "magic-string": "^0.30.21", "svelte": "^5.56.0", "svelte-check": "^4.3.6", "svelte-docinfo": "^0.5.4", diff --git a/src/routes/docs/benchmarks/+page.svelte b/src/routes/docs/benchmarks/+page.svelte index e1d809f..3892522 100644 --- a/src/routes/docs/benchmarks/+page.svelte +++ b/src/routes/docs/benchmarks/+page.svelte @@ -127,15 +127,17 @@

    The parse entries that build a full JS AST are comparable in mechanism: tsv and oxc-parser both serialize the AST to JSON in Rust and deserialize it in JS, native and wasm alike. But - the deliverables differ — tsv's default wire (tsv-json / tsv_wasm-json) - carries a per-node loc (line/column) object that oxc-parser's default span-only - AST omits, and that loc is roughly half the wire bytes and most of its JSON.parse - cost. The tsv-json-no-locations / tsv_wasm-json-no-locations entries - drop it, emitting the same span-only shape oxc does, so those are the payload-matched, - apples-to-apples comparison with oxc-parser (line/column stays derivable from the - offsets plus source, so nothing is lost). The tsv-internal and tsv_wasm-internal entries build - the native AST but skip JS-side materialization, so they show raw in-engine speed rather than a - cross-tool comparison. + the deliverables differ — tsv's default wire (tsv-json / tsv_wasm-json) carries a per-node loc (line/column) object that oxc-parser's default + span-only AST omits, and that loc is roughly half the wire bytes and most of its + JSON.parse cost. The tsv-json-no-locations / tsv_wasm-json-no-locations entries drop it, emitting the same span-only shape oxc does, so those are the payload-matched, apples-to-apples comparison with oxc-parser (line/column stays derivable from the offsets plus source, so nothing is lost). The + tsv-internal and tsv_wasm-internal entries build the native AST but skip JS-side + materialization, so they show raw in-engine speed rather than a cross-tool comparison.

    {#each parse_groups as group (group.language)} diff --git a/src/routes/docs/benchmarks/BenchmarksCrossRuntime.svelte b/src/routes/docs/benchmarks/BenchmarksCrossRuntime.svelte index ce5749a..71aecab 100644 --- a/src/routes/docs/benchmarks/BenchmarksCrossRuntime.svelte +++ b/src/routes/docs/benchmarks/BenchmarksCrossRuntime.svelte @@ -5,7 +5,7 @@ derive_cross_runtime_groups, format_label, format_speedup, - type BenchmarkRuntime, + order_cross_runtime_runtimes, type CrossRuntimeReport, } from './benchmark_data.ts'; @@ -15,16 +15,14 @@ report: CrossRuntimeReport; } = $props(); - // Lead with node (the flagship N-API runtime), then deno, then bun; ratios anchor - // on the first present (node). The combined report stores runtimes deno-first - // (matching the bench's report.md); the site presents them node-first. - const DISPLAY_ORDER: Array = ['node', 'deno', 'bun']; - const runtimes = $derived(DISPLAY_ORDER.filter((r) => report.runtimes.includes(r))); + // Node-first (the flagship N-API runtime), then deno, then bun — the same + // display order `derive_cross_runtime_groups` anchors its ratios on. + const runtimes = $derived(order_cross_runtime_runtimes(report.runtimes)); const base = $derived(runtimes[0]); // ratio columns compare every other runtime against the base (node) const others = $derived(runtimes.filter((r) => r !== base)); - const groups = $derived(derive_cross_runtime_groups({...report, runtimes})); + const groups = $derived(derive_cross_runtime_groups(report)); const format_ops = (n: number | undefined): string => (n == null ? 'fail' : n.toFixed(2)); @@ -33,6 +31,12 @@
    + {#if report.mixed_vintage} + + {/if} {#each groups as group (group.group)}

    {group_label(group.operation, group.language)}

    diff --git a/src/routes/docs/benchmarks/BenchmarksGroup.svelte b/src/routes/docs/benchmarks/BenchmarksGroup.svelte index 437da48..6f79002 100644 --- a/src/routes/docs/benchmarks/BenchmarksGroup.svelte +++ b/src/routes/docs/benchmarks/BenchmarksGroup.svelte @@ -32,7 +32,9 @@ label: e.name, category: e.category, bar_fraction: e.bar_fraction, - value: format_ns(e.mean_ns), + // per-file mean when the baseline carries it (version 4+), falling back to + // the whole-sweep mean; ratios stay on the sweep mean via `raw` + value: format_ns(e.mean_per_file_ns ?? e.mean_ns), raw: e.mean_ns, annotation: e.disabled ? has_coverage @@ -52,7 +54,7 @@ {group.language} files {#if has_coverage}files handled / total  ·  speedfiles handled / total  ·  avg per file  ·  speed{/if}

    diff --git a/src/routes/docs/benchmarks/BenchmarksMeta.svelte b/src/routes/docs/benchmarks/BenchmarksMeta.svelte index 596ee77..f86df8a 100644 --- a/src/routes/docs/benchmarks/BenchmarksMeta.svelte +++ b/src/routes/docs/benchmarks/BenchmarksMeta.svelte @@ -49,6 +49,9 @@

    run

    • {formatted_date}
    • + {#if baseline.runtime} +
    • runtime: {baseline.runtime}
    • + {/if} {#if baseline.versions.tsv}
    • tsv {baseline.versions.tsv}
    • {/if} diff --git a/src/routes/docs/benchmarks/benchmark_data.ts b/src/routes/docs/benchmarks/benchmark_data.ts index e132313..8e92b7b 100644 --- a/src/routes/docs/benchmarks/benchmark_data.ts +++ b/src/routes/docs/benchmarks/benchmark_data.ts @@ -1,7 +1,12 @@ -// Raw types matching the tsv bench.ts `Baseline` format +// Raw types matching the tsv bench's per-runtime report format +// (`benches/js/results/report..json` — the site's flagship detailed +// view is the Node report, the N-API native path) export interface BenchmarkBaseline { version: number; + // The runtime that produced this report (`node` for the flagship view). + // Present from report `version` 5 on. + runtime?: string; timestamp: string; git_commit: string; corpus: Record; @@ -58,6 +63,8 @@ export interface BaselineEntry { // Files this impl was actually timed on (the per-group intersection in // default mode). Present from baseline `version` 4 on. files_iterated?: number | null; + // Present from report `version` 5 on (matches the report's top-level). + runtime?: string; } export interface BaselineVersions { @@ -105,6 +112,10 @@ export interface BenchmarkGroup { export interface BenchmarkDisplayEntry { name: string; mean_ns: number; + // mean time per FILE (the sweep mean divided by the iterated file count); + // null on older baselines (< version 4) without `files_iterated`, and on + // disabled placeholder entries + mean_per_file_ns: number | null; bar_fraction: number; category: ImplementationCategory; files_processed: number | null; @@ -190,6 +201,10 @@ export const derive_benchmark_groups = (baseline: BenchmarkBaseline): Array = entries.map((e) => ({ name: e.name, mean_ns: e.mean_ns ?? 0, + mean_per_file_ns: + e.mean_ns != null && e.files_iterated != null && e.files_iterated > 0 + ? e.mean_ns / e.files_iterated + : null, bar_fraction: slowest > 0 ? (e.mean_ns ?? 0) / slowest : 0, category: categorize_name(e.name), files_processed: e.files_processed ?? null, @@ -246,6 +261,7 @@ export const derive_benchmark_groups = (baseline: BenchmarkBaseline): Array = needs_oxc ? oxc_templates.map((e) => ({ ...e, + mean_per_file_ns: null, bar_fraction: 0, files_processed: null, files_total: null, @@ -346,7 +363,8 @@ export const derive_conformance_groups = (baseline: BenchmarkBaseline): Array = []; for (const [language, rows] of by_language) { rows.sort( - (a, b) => conformance_row_rank(a.name) - conformance_row_rank(b.name) || a.name.localeCompare(b.name), + (a, b) => + conformance_row_rank(a.name) - conformance_row_rank(b.name) || a.name.localeCompare(b.name), ); result.push({ language, @@ -528,6 +546,10 @@ export interface CrossRuntimeReport { kind: 'combined'; generated: string; runtimes: Array; + // The sibling reports came from different commits/versions — ratios are + // unreliable until every runtime is re-run. Present from combined + // `version` 6 on. + mixed_vintage?: boolean; sources: Array<{ runtime: BenchmarkRuntime; timestamp: string; @@ -555,16 +577,32 @@ export interface CrossRuntimeGroup { const CROSS_RUNTIME_LANG_ORDER: Record = {svelte: 0, typescript: 1, css: 2}; const CROSS_RUNTIME_OP_ORDER: Record = {format: 0, parse: 1}; +// The combined report stores runtimes deno-first (matching the bench's +// `report.md`); the site presents them node-first (the flagship N-API runtime), +// then deno, then bun. +const CROSS_RUNTIME_DISPLAY_ORDER: Array = ['node', 'deno', 'bun']; + +/** + * The report's runtimes in the site's display order — node (the flagship, the + * ratio anchor) first, then deno, then bun. Shared by `derive_cross_runtime_groups` + * and the table headers so the anchor can't drift between them. + */ +export const order_cross_runtime_runtimes = ( + runtimes: Array, +): Array => CROSS_RUNTIME_DISPLAY_ORDER.filter((r) => runtimes.includes(r)); + /** * Groups the combined report's rows by benchmark group, in the same display * order as `derive_benchmark_groups` (format before parse, then svelte / - * typescript / css). The ratio base is the first runtime in `report.runtimes` - * (deno in a full run), matching the bench's `report.md`. + * typescript / css). The ratio base is the first runtime in display order + * (node when present — the flagship N-API path), regardless of the report's + * own deno-first storage order. */ export const derive_cross_runtime_groups = ( report: CrossRuntimeReport, ): Array => { - const base = report.runtimes[0]; + const runtimes = order_cross_runtime_runtimes(report.runtimes); + const base = runtimes[0]; const grouped: Map> = new Map(); for (const row of report.rows) { let rows = grouped.get(row.group); @@ -574,7 +612,7 @@ export const derive_cross_runtime_groups = ( } const base_ops = base ? row.ops_per_second[base] : undefined; const ratio_vs_base: Partial> = {}; - for (const runtime of report.runtimes) { + for (const runtime of runtimes) { const ops = row.ops_per_second[runtime]; if (ops != null && base_ops != null && base_ops > 0) { ratio_vs_base[runtime] = ops / base_ops; @@ -808,9 +846,11 @@ export const baseline_ratio_color = (direction: BaselineDirection, ratio: number /** * A normalized row for `BenchmarksBaselineGroup` — the shared hover-to-rebaseline * column behind the format, parse, and binary-size groups. `raw` is the number the - * ratio derives from (mean ns for speed, bytes for size); `value` is its formatted - * display. Flattening the group-specific display entries to this one shape lets a - * single component own the anchor state for all three sections. + * ratio derives from (sweep mean ns for speed, bytes for size); `value` is the + * row's displayed measurement (per-file mean time for speed — every entry in a + * group times the same intersection set, so the ratios agree either way — and + * bytes for size). Flattening the group-specific display entries to this one + * shape lets a single component own the anchor state for all three sections. */ export interface BaselineRow { // stable identity for `#each` and anchor matching (the entry name / size label) diff --git a/src/test/benchmark_data.test.ts b/src/test/benchmark_data.test.ts index b654aba..e4948fd 100644 --- a/src/test/benchmark_data.test.ts +++ b/src/test/benchmark_data.test.ts @@ -21,7 +21,8 @@ import { // When `npm run update-benchmarks` pulls in a new shape, these fail loudly. describe('benchmarks.json shape', () => { test('baseline version is current', () => { - assert.isAtLeast(benchmarks_json.version, 4); + // version 5 is the first per-runtime report shape (carries `runtime`) + assert.isAtLeast(benchmarks_json.version, 5); }); test('binary sizes include the flagship tsv builds', () => { @@ -54,6 +55,12 @@ describe('benchmarks.json shape', () => { // shared component reads off the leading row assert.strictEqual(group.entries[0]?.category, 'canonical', `${key} canonical leads`); assert.isNotNull(group.files_iterated, `${key} has no files_iterated`); + for (const entry of group.entries) { + if (entry.disabled) continue; + // the bars render per-file means; a null would silently fall back to the + // whole-sweep mean and misread as per-file latency + assert.isNotNull(entry.mean_per_file_ns, `${key}/${entry.name} has no per-file mean`); + } } }); @@ -204,7 +211,7 @@ describe('benchmarks.json shape', () => { test('flagship report is the node runtime', () => { // the headline detailed view switched to N-API under Node; guards against an // `update-benchmarks` that pulls the wrong runtime's sibling report - assert.strictEqual((benchmarks_json as {runtime?: string}).runtime, 'node'); + assert.strictEqual(benchmarks_json.runtime, 'node'); }); }); @@ -216,7 +223,7 @@ describe('benchmarks_conformance.json shape', () => { test('report is the conformance surface at the current version', () => { assert.isAtLeast(benchmarks_conformance_json.version, 6); assert.strictEqual(benchmarks_conformance_json.corpus_kind, 'conformance'); - assert.strictEqual((benchmarks_conformance_json as {runtime?: string}).runtime, 'node'); + assert.strictEqual(benchmarks_conformance_json.runtime, 'node'); }); test('conformance report is parse-only', () => { @@ -303,6 +310,9 @@ describe('benchmarks_cross_runtime.json shape', () => { assert.isAbove(group.rows.length, 0, group.group); for (const row of group.rows) { assert.isNumber(row.ops_per_second.node, `${group.group}/${row.name} missing node ops`); + // ratios anchor on node (the display-order base, not the report's + // deno-first storage order), so node's own ratio is exactly 1 + assert.strictEqual(row.ratio_vs_base.node, 1, `${group.group}/${row.name} node anchor`); } } }); From 09cfd553a02cf847f3a299ae806230f5d26b2c76 Mon Sep 17 00:00:00 2001 From: Ryan Atkinson Date: Mon, 6 Jul 2026 15:15:58 -0400 Subject: [PATCH 024/218] wip --- .../benchmarks/BenchmarksCrossRuntime.svelte | 9 ++++- .../docs/benchmarks/BenchmarksGroup.svelte | 4 +- .../docs/benchmarks/BenchmarksMeta.svelte | 12 ++++-- src/routes/docs/benchmarks/benchmark_data.ts | 38 ++++++++++--------- src/test/benchmark_data.test.ts | 23 ++++++++++- 5 files changed, 61 insertions(+), 25 deletions(-) diff --git a/src/routes/docs/benchmarks/BenchmarksCrossRuntime.svelte b/src/routes/docs/benchmarks/BenchmarksCrossRuntime.svelte index 71aecab..b388c82 100644 --- a/src/routes/docs/benchmarks/BenchmarksCrossRuntime.svelte +++ b/src/routes/docs/benchmarks/BenchmarksCrossRuntime.svelte @@ -32,7 +32,7 @@
      {#if report.mixed_vintage} -
      {/each}

      - ops/sec (higher is faster); ratios are vs {base} (> 1 = faster than {base}). A + sweeps/sec — one sweep is a full pass over the group's timed file set (higher is faster); ratios + are vs {base} (> 1 = faster than {base}). A fail is an implementation that runtime can't load (see notes above).

    diff --git a/src/routes/docs/benchmarks/BenchmarksBar.svelte b/src/routes/docs/benchmarks/BenchmarksBar.svelte index 887b2f9..940b898 100644 --- a/src/routes/docs/benchmarks/BenchmarksBar.svelte +++ b/src/routes/docs/benchmarks/BenchmarksBar.svelte @@ -109,15 +109,13 @@ .bar-annotation { font-size: var(--font_size_xs); text-align: right; - font-variant-numeric: tabular-nums; white-space: nowrap; } .bar-label { font-size: var(--font_size_sm); text-align: right; - overflow: hidden; - text-overflow: ellipsis; white-space: nowrap; + /* these may overflow slightly/harmlessly, just need to visually check */ } .bar-track { height: 1.2rem; @@ -133,7 +131,6 @@ .bar-value { font-size: var(--font_size_sm); text-align: right; - font-variant-numeric: tabular-nums; white-space: nowrap; } .bar-ratio { diff --git a/src/routes/docs/benchmarks/BenchmarksConformance.svelte b/src/routes/docs/benchmarks/BenchmarksConformance.svelte index fbd7941..b670b3a 100644 --- a/src/routes/docs/benchmarks/BenchmarksConformance.svelte +++ b/src/routes/docs/benchmarks/BenchmarksConformance.svelte @@ -1,9 +1,5 @@

    - tsv is heavily inspired by and borrows architectural patterns from PrettierPrettier, and we're grateful for the hard work of its contributors. tsv offers a speedup over Prettier. These are single-threaded numbers over the full benchmarked corpus: From b4259d21b582908e9e68ad9c1f774b44d0315951 Mon Sep 17 00:00:00 2001 From: Ryan Atkinson Date: Wed, 15 Jul 2026 20:26:39 -0400 Subject: [PATCH 047/218] wip --- src/routes/docs/benchmarks/benchmark_data.ts | 5 +- src/routes/docs/benchmarks/benchmarks.json | 1180 ++++++++--------- .../benchmarks/benchmarks_conformance.json | 156 +-- .../benchmarks/benchmarks_cross_runtime.json | 638 ++++----- 4 files changed, 991 insertions(+), 988 deletions(-) diff --git a/src/routes/docs/benchmarks/benchmark_data.ts b/src/routes/docs/benchmarks/benchmark_data.ts index 0b86c80..ea0eb73 100644 --- a/src/routes/docs/benchmarks/benchmark_data.ts +++ b/src/routes/docs/benchmarks/benchmark_data.ts @@ -798,7 +798,10 @@ export const derive_corpus_repos = ( // map for reports predating `version` 8 (which lack `source.repo`). const url = source.repo?.url ?? corpus_repo_url(source.path); if (!url || by_url.has(url)) continue; - by_url.set(url, {url, label: source.repo?.slug ?? corpus_repo_label(url)}); + by_url.set(url, { + url, + label: source.repo?.slug ?? corpus_repo_label(url), + }); } return [...by_url.values()]; }; diff --git a/src/routes/docs/benchmarks/benchmarks.json b/src/routes/docs/benchmarks/benchmarks.json index 8f27bdc..3a039a2 100644 --- a/src/routes/docs/benchmarks/benchmarks.json +++ b/src/routes/docs/benchmarks/benchmarks.json @@ -2,8 +2,8 @@ "version": 7, "runtime": "node", "corpus_kind": "perf", - "timestamp": "2026-07-08T02:06:48.550Z", - "git_commit": "99ac4c69", + "timestamp": "2026-07-16T00:15:41.741Z", + "git_commit": "eca5466f", "machine": { "cpu_model": "AMD Ryzen 5 PRO 7530U with Radeon Graphics", "os": "linux", @@ -11,9 +11,9 @@ "runtime_version": "24.14.1" }, "corpus": { - "svelte": 762, - "typescript": 2395, - "css": 50 + "svelte": 763, + "typescript": 2437, + "css": 49 }, "corpus_sources": [ { @@ -27,7 +27,7 @@ "repo": { "url": "https://github.com/fuzdev/zzz", "slug": "fuzdev/zzz", - "commit": "8f26d88420150d9c6ac48fdbf2555bcae21b25db", + "commit": "838d499c7cc746ebe1f5da8470e7679c8895aee0", "subpath": "src" } }, @@ -48,46 +48,46 @@ }, { "path": "../fuz_blog/src", - "files": 33, + "files": 37, "by_language": { - "svelte": 18, - "typescript": 14, + "svelte": 20, + "typescript": 16, "css": 1 }, "repo": { "url": "https://github.com/fuzdev/fuz_blog", "slug": "fuzdev/fuz_blog", - "commit": "d1875121e4e0a291914a19795e2aa84c25b505d9", + "commit": "7147f354fac7dcb535f70f241db1dd3543c0a370", "subpath": "src" } }, { "path": "../fuz_code/src", - "files": 63, + "files": 66, "by_language": { - "svelte": 22, - "typescript": 37, - "css": 4 + "svelte": 17, + "typescript": 46, + "css": 3 }, "repo": { "url": "https://github.com/fuzdev/fuz_code", "slug": "fuzdev/fuz_code", - "commit": "ac968a443eb664ffc227c6da9ee62d6dec6083c9", + "commit": "7b3664851737def05ac8d4b646b27643cfb4a39f", "subpath": "src" } }, { "path": "../fuz_css/src", - "files": 124, + "files": 146, "by_language": { - "svelte": 37, - "typescript": 85, + "svelte": 39, + "typescript": 105, "css": 2 }, "repo": { "url": "https://github.com/fuzdev/fuz_css", "slug": "fuzdev/fuz_css", - "commit": "5533218cb13d5f2c9bfc34d052da7e3c54891026", + "commit": "b0b02e804d3db586c37851754401e3f57b449345", "subpath": "src" } }, @@ -102,7 +102,7 @@ "repo": { "url": "https://github.com/fuzdev/fuz_docs", "slug": "fuzdev/fuz_docs", - "commit": "89e180e999f41d39197427fd05e69e9097e1cea9", + "commit": "40b3d2ad892d4434088f6da83e54f7cbf69615e0", "subpath": "src" } }, @@ -147,7 +147,7 @@ "repo": { "url": "https://github.com/fuzdev/fuz_template", "slug": "fuzdev/fuz_template", - "commit": "1a50504ce43c152aff308e52c966559132c30030", + "commit": "c5c0c0332b811c983d4e60031452f668d163d28d", "subpath": "src" } }, @@ -162,7 +162,7 @@ "repo": { "url": "https://github.com/fuzdev/fuz_ui", "slug": "fuzdev/fuz_ui", - "commit": "c2fb3c2a1ef4f6dd07dc183424324047318c5f49", + "commit": "311a8549508ec9c3d0c6ebc895c82d42321daeb3", "subpath": "src" } }, @@ -183,16 +183,16 @@ }, { "path": "../mdz/src", - "files": 59, + "files": 71, "by_language": { - "svelte": 20, - "typescript": 38, + "svelte": 22, + "typescript": 48, "css": 1 }, "repo": { "url": "https://github.com/fuzdev/mdz", "slug": "fuzdev/mdz", - "commit": "bfdbd1b664214b390bbaecdfead7a324d696a14a", + "commit": "f5dbce0755f74961da0636079714e4e00bf667f0", "subpath": "src" } }, @@ -237,7 +237,7 @@ "repo": { "url": "https://github.com/fuzdev/tsv.fuz.dev", "slug": "fuzdev/tsv.fuz.dev", - "commit": "dc9cdb8e487fd801f0779006bc5c0ee6b6621f85", + "commit": "dee909612d74958231dcc2152d6b2cb1b0db3e3c", "subpath": "src" } }, @@ -291,7 +291,7 @@ "repo": { "url": "https://github.com/sveltejs/kit", "slug": "sveltejs/kit", - "commit": "d71dabb7f69627b07969c6c2a944db0b031cdfcb", + "commit": "da5b08ea7f5182f505b5d1cb9b347effbcb35231", "subpath": "packages/kit/src" } }, @@ -306,22 +306,22 @@ "repo": { "url": "https://github.com/sveltejs/svelte", "slug": "sveltejs/svelte", - "commit": "8fb7ceeba5dd1d3b7fc3f587f4e2138bf1b978ed", + "commit": "b4d1583ae20f3869a88a731d9a265c546c099f66", "subpath": "packages/svelte/src" } }, { "path": "../svelte.dev/apps/svelte.dev/src", - "files": 144, + "files": 145, "by_language": { "svelte": 60, - "typescript": 84, + "typescript": 85, "css": 0 }, "repo": { "url": "https://github.com/sveltejs/svelte.dev", "slug": "sveltejs/svelte.dev", - "commit": "d30592556bfdd9949c2cb1ebb7f58b9c28f85cec", + "commit": "c21c2d0f011915b2a783c612c978a348cec98a5c", "subpath": "apps/svelte.dev/src" } }, @@ -336,7 +336,7 @@ "repo": { "url": "https://github.com/sveltejs/svelte.dev", "slug": "sveltejs/svelte.dev", - "commit": "d30592556bfdd9949c2cb1ebb7f58b9c28f85cec", + "commit": "c21c2d0f011915b2a783c612c978a348cec98a5c", "subpath": "packages/repl/src" } }, @@ -351,7 +351,7 @@ "repo": { "url": "https://github.com/sveltejs/svelte.dev", "slug": "sveltejs/svelte.dev", - "commit": "d30592556bfdd9949c2cb1ebb7f58b9c28f85cec", + "commit": "c21c2d0f011915b2a783c612c978a348cec98a5c", "subpath": "packages/site-kit/src" } } @@ -360,800 +360,800 @@ "tsv": "0.1.0", "svelte": "5.56.4", "acorn": "8.16.0", - "acorn_ts": "1.0.10", + "acorn_ts": "1.0.11", "prettier": "3.9.0", "prettier_svelte": "4.1.1", - "oxc_parser": "0.139.0", - "oxfmt": "0.57.0", - "biome": "2.5.2" + "oxc_parser": "0.140.0", + "oxfmt": "0.59.0", + "biome": "2.5.4" }, "binary_sizes": [ { "label": "tsv (ffi)", - "bytes": 3348832, + "bytes": 3407520, "kind": "native", - "gzip_bytes": 1444707 + "gzip_bytes": 1473224 }, { "label": "tsv format (ffi)", - "bytes": 3085648, + "bytes": 3143024, "kind": "native", - "gzip_bytes": 1337366 + "gzip_bytes": 1366105 }, { "label": "tsv parse (ffi)", - "bytes": 1568432, + "bytes": 1602672, "kind": "native", - "gzip_bytes": 691800 + "gzip_bytes": 704951 }, { "label": "tsv (napi)", - "bytes": 3482128, + "bytes": 3540848, "kind": "native", - "gzip_bytes": 1489183 + "gzip_bytes": 1517414 }, { "label": "tsv_format_wasm", - "bytes": 2214519, + "bytes": 2261296, "kind": "wasm", - "gzip_bytes": 763363 + "gzip_bytes": 794602 }, { "label": "tsv_parse_wasm", - "bytes": 1036989, + "bytes": 1057603, "kind": "wasm", - "gzip_bytes": 381243 + "gzip_bytes": 389582 }, { "label": "tsv_wasm", - "bytes": 2444330, + "bytes": 2491362, "kind": "wasm", - "gzip_bytes": 843039 + "gzip_bytes": 875347 }, { "label": "biome (wasm)", - "bytes": 37540009, + "bytes": 38584187, "kind": "wasm", - "gzip_bytes": 9006428 + "gzip_bytes": 9281487 }, { "label": "oxc-parser (napi)", - "bytes": 2428632, + "bytes": 2354904, "kind": "native", - "gzip_bytes": 977389 + "gzip_bytes": 954754 }, { "label": "oxfmt (napi)", - "bytes": 9061136, + "bytes": 8917776, "kind": "native", - "gzip_bytes": 3631974 + "gzip_bytes": 3586269 }, { "label": "oxc-parser (wasm)", - "bytes": 1616596, + "bytes": 1531455, "kind": "wasm", - "gzip_bytes": 501431 + "gzip_bytes": 495227 } ], "entries": [ { "name": "svelte/compiler", "group": "parse/svelte", - "mean_ns": 437128687.45454544, - "p50_ns": 436616391, - "p75_ns": 441021842.75, - "p90_ns": 445745147.9, - "p95_ns": 449164035.45, - "p99_ns": 452189995.09000003, - "min_ns": 430164267, - "max_ns": 452946485, - "std_dev_ns": 4524124.712778736, - "cv": 0.010349640375065007, - "ops_per_second": 2.2876558521544856, + "mean_ns": 447339614.1818182, + "p50_ns": 446240894, + "p75_ns": 451111701, + "p90_ns": 457976256, + "p95_ns": 464629570, + "p99_ns": 470677924.40000004, + "min_ns": 442688667, + "max_ns": 472190013, + "std_dev_ns": 4933722.594169536, + "cv": 0.011029031272343918, + "ops_per_second": 2.235438061592186, "sample_size": 11, - "files_processed": 762, - "files_total": 762, - "files_iterated": 762, + "files_processed": 763, + "files_total": 763, + "files_iterated": 763, "runtime": "node" }, { "name": "tsv-json", "group": "parse/svelte", - "mean_ns": 209792668.95, - "p50_ns": 209751909.5, - "p75_ns": 211004208.75, - "p90_ns": 215354438.3, - "p95_ns": 215905263.1, - "p99_ns": 216284608.63, - "min_ns": 208687062, - "max_ns": 216394921, - "std_dev_ns": 1008963.4866455498, - "cv": 0.0048093362446617076, - "ops_per_second": 4.76661079247879, - "sample_size": 20, - "files_processed": 762, - "files_total": 762, - "files_iterated": 762, + "mean_ns": 215171513, + "p50_ns": 214558414.5, + "p75_ns": 217842026, + "p90_ns": 218923022.1, + "p95_ns": 219063741.85, + "p99_ns": 219130613.53, + "min_ns": 212126483, + "max_ns": 219145354, + "std_dev_ns": 2646489.822478956, + "cv": 0.012299443293308794, + "ops_per_second": 4.647455353441698, + "sample_size": 24, + "files_processed": 763, + "files_total": 763, + "files_iterated": 763, "runtime": "node" }, { "name": "tsv-json-no-locations", "group": "parse/svelte", - "mean_ns": 133062831.83870968, - "p50_ns": 133073686.5, - "p75_ns": 134466361.25, - "p90_ns": 136806237.2, - "p95_ns": 136908214.75, - "p99_ns": 137379380.55, - "min_ns": 131471131, - "max_ns": 137463291, - "std_dev_ns": 952981.2076673248, - "cv": 0.007161888819730428, - "ops_per_second": 7.515246640866147, - "sample_size": 31, - "files_processed": 762, - "files_total": 762, - "files_iterated": 762, + "mean_ns": 136124893.45945945, + "p50_ns": 135970730, + "p75_ns": 137925210, + "p90_ns": 138865033, + "p95_ns": 139075628.8, + "p99_ns": 139091043.52, + "min_ns": 133615681, + "max_ns": 139099177, + "std_dev_ns": 1834282.8925741522, + "cv": 0.013474999656256379, + "ops_per_second": 7.346194913995057, + "sample_size": 37, + "files_processed": 763, + "files_total": 763, + "files_iterated": 763, "runtime": "node" }, { "name": "tsv_wasm-json", "group": "parse/svelte", - "mean_ns": 232987546.05555555, - "p50_ns": 233017529, - "p75_ns": 234530174.25, - "p90_ns": 237902072.5, - "p95_ns": 238729860.55, - "p99_ns": 239072143.25, - "min_ns": 231877615, - "max_ns": 239152232, - "std_dev_ns": 919979.7858631251, - "cv": 0.003948622153579648, - "ops_per_second": 4.292074906705749, - "sample_size": 18, - "files_processed": 762, - "files_total": 762, - "files_iterated": 762, + "mean_ns": 239118337, + "p50_ns": 238069355, + "p75_ns": 243537130, + "p90_ns": 244283174, + "p95_ns": 244685278, + "p99_ns": 244940574, + "min_ns": 234170486, + "max_ns": 245004398, + "std_dev_ns": 3814109.8642763034, + "cv": 0.01595072093645542, + "ops_per_second": 4.1820297537449, + "sample_size": 21, + "files_processed": 763, + "files_total": 763, + "files_iterated": 763, "runtime": "node" }, { "name": "tsv_wasm-json-no-locations", "group": "parse/svelte", - "mean_ns": 152465764.39285713, - "p50_ns": 152526789, - "p75_ns": 154080564, - "p90_ns": 156701070, - "p95_ns": 156778149, - "p99_ns": 158019072.52, - "min_ns": 150819386, - "max_ns": 158602397, - "std_dev_ns": 1162059.0354691567, - "cv": 0.007621770304282146, - "ops_per_second": 6.5588494832407696, - "sample_size": 28, - "files_processed": 762, - "files_total": 762, - "files_iterated": 762, + "mean_ns": 156136315.15151516, + "p50_ns": 155336306, + "p75_ns": 158317362, + "p90_ns": 159514124.6, + "p95_ns": 159781601.2, + "p99_ns": 160128001.64, + "min_ns": 153129079, + "max_ns": 160151193, + "std_dev_ns": 2250222.6645511542, + "cv": 0.014411910914943338, + "ops_per_second": 6.404659921874018, + "sample_size": 33, + "files_processed": 763, + "files_total": 763, + "files_iterated": 763, "runtime": "node" }, { "name": "tsv-internal", "group": "parse/svelte", - "mean_ns": 21408451.805263158, - "p50_ns": 21329142, - "p75_ns": 21904131, - "p90_ns": 22089408.4, - "p95_ns": 22177898.2, - "p99_ns": 22401088.4, - "min_ns": 21163682, - "max_ns": 22552958, - "std_dev_ns": 261734.6196352469, - "cv": 0.012225761209453772, - "ops_per_second": 46.71052391346464, - "sample_size": 190, - "files_processed": 762, - "files_total": 762, - "files_iterated": 762, + "mean_ns": 21107882.333333332, + "p50_ns": 20939483, + "p75_ns": 21520190, + "p90_ns": 21684446, + "p95_ns": 21796098.4, + "p99_ns": 21943351.32, + "min_ns": 20706273, + "max_ns": 21987371, + "std_dev_ns": 349471.32487507124, + "cv": 0.01655643703883975, + "ops_per_second": 47.37566678684821, + "sample_size": 225, + "files_processed": 763, + "files_total": 763, + "files_iterated": 763, "runtime": "node" }, { "name": "tsv_wasm-internal", "group": "parse/svelte", - "mean_ns": 43426482.06666667, - "p50_ns": 43129848.5, - "p75_ns": 43749523.5, - "p90_ns": 44539613.8, - "p95_ns": 45148119.35, - "p99_ns": 48339428.269999996, - "min_ns": 39202531, - "max_ns": 50599110, - "std_dev_ns": 1119788.5228051157, - "cv": 0.025785844708444475, - "ops_per_second": 23.02742364589511, - "sample_size": 90, - "files_processed": 762, - "files_total": 762, - "files_iterated": 762, + "mean_ns": 36926367.86764706, + "p50_ns": 37761837.5, + "p75_ns": 40590030.5, + "p90_ns": 41538579, + "p95_ns": 42050564.5, + "p99_ns": 42599705.25, + "min_ns": 28609958, + "max_ns": 42781237, + "std_dev_ns": 4415963.897212026, + "cv": 0.11958836333537859, + "ops_per_second": 27.08091961777122, + "sample_size": 136, + "files_processed": 763, + "files_total": 763, + "files_iterated": 763, "runtime": "node" }, { "name": "prettier", "group": "format/svelte", - "mean_ns": 4382127598.714286, - "p50_ns": 4382005767, - "p75_ns": 4393716290.5, - "p90_ns": 4415934311.2, - "p95_ns": 4428634888.6, - "p99_ns": 4438795350.52, - "min_ns": 4344810712, - "max_ns": 4441335466, - "std_dev_ns": 32230102.407873627, - "cv": 0.007354898204545646, - "ops_per_second": 0.22819965358685573, - "sample_size": 7, - "files_processed": 762, - "files_total": 762, - "files_iterated": 762, + "mean_ns": 4471389548.333333, + "p50_ns": 4443221170, + "p75_ns": 4549812450.5, + "p90_ns": 4633226047.4, + "p95_ns": 4677811261.7, + "p99_ns": 4713479433.14, + "min_ns": 4414423312, + "max_ns": 4722396476, + "std_dev_ns": 63436270.564138755, + "cv": 0.014187149180009156, + "ops_per_second": 0.22364412431315459, + "sample_size": 6, + "files_processed": 763, + "files_total": 763, + "files_iterated": 763, "runtime": "node" }, { "name": "tsv", "group": "format/svelte", - "mean_ns": 77271724.69387755, - "p50_ns": 77163643, - "p75_ns": 78953471, - "p90_ns": 80002218.4, - "p95_ns": 80218096, - "p99_ns": 82808738.24, - "min_ns": 76771207, - "max_ns": 84553656, - "std_dev_ns": 562423.4638081954, - "cv": 0.00727851573180633, - "ops_per_second": 12.941344378705613, - "sample_size": 49, - "files_processed": 762, - "files_total": 762, - "files_iterated": 762, + "mean_ns": 68629776.13461539, + "p50_ns": 68564213, + "p75_ns": 70730671, + "p90_ns": 71067604.2, + "p95_ns": 71156349, + "p99_ns": 71293163.4, + "min_ns": 68239242, + "max_ns": 71475201, + "std_dev_ns": 475041.82611961645, + "cv": 0.006921803521372926, + "ops_per_second": 14.570934896225333, + "sample_size": 52, + "files_processed": 763, + "files_total": 763, + "files_iterated": 763, "runtime": "node" }, { "name": "tsv_wasm", "group": "format/svelte", - "mean_ns": 121403586.43589744, - "p50_ns": 120928072, - "p75_ns": 123328708, - "p90_ns": 124377342.3, - "p95_ns": 125770249.69999999, - "p99_ns": 128313347.69999999, - "min_ns": 119815365, - "max_ns": 129508879, - "std_dev_ns": 1520451.007994127, - "cv": 0.012523938152329162, - "ops_per_second": 8.236988950305946, - "sample_size": 39, - "files_processed": 762, - "files_total": 762, - "files_iterated": 762, + "mean_ns": 125437704.925, + "p50_ns": 125111866.5, + "p75_ns": 126811968.25, + "p90_ns": 131013833.1, + "p95_ns": 133430926.7, + "p99_ns": 133875215.12, + "min_ns": 119804914, + "max_ns": 134102543, + "std_dev_ns": 3709061.4868603325, + "cv": 0.02956895208723728, + "ops_per_second": 7.972084634344246, + "sample_size": 40, + "files_processed": 763, + "files_total": 763, + "files_iterated": 763, "runtime": "node" }, { "name": "oxfmt", "group": "format/svelte", - "mean_ns": 4137641287, - "p50_ns": 4137184260, - "p75_ns": 4158187781, - "p90_ns": 4164443145.2, - "p95_ns": 4166528266.6, - "p99_ns": 4168196363.72, - "min_ns": 4101440537, - "max_ns": 4168613388, - "std_dev_ns": 26985998.878662016, - "cv": 0.006522073086289275, - "ops_per_second": 0.2416835899095184, - "sample_size": 5, - "files_processed": 762, - "files_total": 762, - "files_iterated": 762, + "mean_ns": 4369417561.285714, + "p50_ns": 4381486391, + "p75_ns": 4423110874.5, + "p90_ns": 4436920148.2, + "p95_ns": 4439500419.1, + "p99_ns": 4441564635.82, + "min_ns": 4285702265, + "max_ns": 4442080690, + "std_dev_ns": 64002452.31291099, + "cv": 0.014647822373396164, + "ops_per_second": 0.2288634551342232, + "sample_size": 7, + "files_processed": 763, + "files_total": 763, + "files_iterated": 763, "runtime": "node" }, { "name": "biome-wasm", "group": "format/svelte", - "mean_ns": 879934637.3333334, - "p50_ns": 880236810.5, - "p75_ns": 888292419.75, - "p90_ns": 894794986, - "p95_ns": 897129443, - "p99_ns": 898997008.6, - "min_ns": 855586599, - "max_ns": 899463900, - "std_dev_ns": 15013621.284297662, - "cv": 0.017062200585485375, - "ops_per_second": 1.1364480469032656, + "mean_ns": 919138906, + "p50_ns": 919126476.5, + "p75_ns": 925856692.5, + "p90_ns": 929440736, + "p95_ns": 930578349.5, + "p99_ns": 931488440.3, + "min_ns": 907217162, + "max_ns": 931715963, + "std_dev_ns": 9543624.6422586, + "cv": 0.010383223449643203, + "ops_per_second": 1.0879748354379855, "sample_size": 6, - "files_processed": 762, - "files_total": 762, - "files_iterated": 762, + "files_processed": 763, + "files_total": 763, + "files_iterated": 763, "runtime": "node" }, { "name": "acorn-typescript", "group": "parse/typescript", - "mean_ns": 2967220820, - "p50_ns": 2965964145, - "p75_ns": 2966005162, - "p90_ns": 2969726437, - "p95_ns": 2970966862, - "p99_ns": 2971959202, - "min_ns": 2964706686, - "max_ns": 2972207287, - "std_dev_ns": 3378499.634484416, - "cv": 0.0011386074173220502, - "ops_per_second": 0.3370156994247567, - "sample_size": 4, - "files_processed": 2392, - "files_total": 2395, - "files_iterated": 2392, + "mean_ns": 3128149464.8, + "p50_ns": 3128265157, + "p75_ns": 3134995396, + "p90_ns": 3135699313, + "p95_ns": 3135933952, + "p99_ns": 3136121663.2, + "min_ns": 3118724019, + "max_ns": 3136168591, + "std_dev_ns": 7597482.683936056, + "cv": 0.0024287466981446825, + "ops_per_second": 0.3196778195072388, + "sample_size": 5, + "files_processed": 2434, + "files_total": 2437, + "files_iterated": 2434, "runtime": "node" }, { "name": "tsv-json", "group": "parse/typescript", - "mean_ns": 1965377939.75, - "p50_ns": 1965804377, - "p75_ns": 1966434168, - "p90_ns": 1968868789.8, - "p95_ns": 1969680330.4, - "p99_ns": 1970329562.88, - "min_ns": 1964170683, - "max_ns": 1970491871, - "std_dev_ns": 971388.2993397902, - "cv": 0.0004942501285342364, - "ops_per_second": 0.5088079904505298, - "sample_size": 4, - "files_processed": 2395, - "files_total": 2395, - "files_iterated": 2392, + "mean_ns": 2012860691, + "p50_ns": 2012491511, + "p75_ns": 2013025755, + "p90_ns": 2016083350.2, + "p95_ns": 2017102548.6, + "p99_ns": 2017917907.32, + "min_ns": 2009308204, + "max_ns": 2018121747, + "std_dev_ns": 3268248.4967490616, + "cv": 0.0016236834031099182, + "ops_per_second": 0.49680536982576506, + "sample_size": 5, + "files_processed": 2437, + "files_total": 2437, + "files_iterated": 2434, "runtime": "node" }, { "name": "tsv-json-no-locations", "group": "parse/typescript", - "mean_ns": 955511021.5, - "p50_ns": 955050917, - "p75_ns": 956234735.25, - "p90_ns": 957078886.5, - "p95_ns": 957340204.25, - "p99_ns": 957549258.45, - "min_ns": 954290820, - "max_ns": 957601522, - "std_dev_ns": 1300907.4909904622, - "cv": 0.0013614782684015982, - "ops_per_second": 1.0465604032804974, + "mean_ns": 991447544, + "p50_ns": 991790889.5, + "p75_ns": 992641387.5, + "p90_ns": 992889675, + "p95_ns": 992974106.5, + "p99_ns": 993041651.7, + "min_ns": 988885149, + "max_ns": 993058538, + "std_dev_ns": 1599060.9985106883, + "cv": 0.0016128548688105766, + "ops_per_second": 1.0086262314650507, "sample_size": 6, - "files_processed": 2395, - "files_total": 2395, - "files_iterated": 2392, + "files_processed": 2437, + "files_total": 2437, + "files_iterated": 2434, "runtime": "node" }, { "name": "tsv_wasm-json", "group": "parse/typescript", - "mean_ns": 2092504974.4, - "p50_ns": 2089379335, - "p75_ns": 2100911218, - "p90_ns": 2101754089, - "p95_ns": 2102035046, - "p99_ns": 2102259811.6, - "min_ns": 2084393071, - "max_ns": 2102316003, - "std_dev_ns": 8532444.470659439, - "cv": 0.004077622072609892, - "ops_per_second": 0.4778961160112595, + "mean_ns": 2137952532.6, + "p50_ns": 2137949434, + "p75_ns": 2142934848, + "p90_ns": 2144094183, + "p95_ns": 2144480628, + "p99_ns": 2144789784, + "min_ns": 2131022798, + "max_ns": 2144867073, + "std_dev_ns": 6026962.072416319, + "cv": 0.0028190345578378343, + "ops_per_second": 0.46773723211893914, "sample_size": 5, - "files_processed": 2395, - "files_total": 2395, - "files_iterated": 2392, + "files_processed": 2437, + "files_total": 2437, + "files_iterated": 2434, "runtime": "node" }, { "name": "tsv_wasm-json-no-locations", "group": "parse/typescript", - "mean_ns": 1048031766.2, - "p50_ns": 1048479602, - "p75_ns": 1048696590, - "p90_ns": 1048889293.2, - "p95_ns": 1048953527.6, - "p99_ns": 1049004915.12, - "min_ns": 1046404840, - "max_ns": 1049017762, - "std_dev_ns": 1058790.8911589673, - "cv": 0.001010266029433419, - "ops_per_second": 0.9541695512015291, + "mean_ns": 1083325293.2, + "p50_ns": 1083000851, + "p75_ns": 1083766522, + "p90_ns": 1084247724.4, + "p95_ns": 1084408125.2, + "p99_ns": 1084536445.84, + "min_ns": 1082577004, + "max_ns": 1084568526, + "std_dev_ns": 833625.2087291387, + "cv": 0.0007695059036854201, + "ops_per_second": 0.9230837738922645, "sample_size": 5, - "files_processed": 2395, - "files_total": 2395, - "files_iterated": 2392, + "files_processed": 2437, + "files_total": 2437, + "files_iterated": 2434, "runtime": "node" }, { "name": "tsv-internal", "group": "parse/typescript", - "mean_ns": 137482572.02702704, - "p50_ns": 137082327, - "p75_ns": 137612391, - "p90_ns": 139873302.4, - "p95_ns": 140062740, - "p99_ns": 140160483.2, - "min_ns": 136056372, - "max_ns": 140209463, - "std_dev_ns": 1438092.6977912537, - "cv": 0.01046018180041428, - "ops_per_second": 7.273649199721218, - "sample_size": 37, - "files_processed": 2395, - "files_total": 2395, - "files_iterated": 2392, + "mean_ns": 138224012.6875, + "p50_ns": 138058653, + "p75_ns": 139442105, + "p90_ns": 142201952.4, + "p95_ns": 142499972.8, + "p99_ns": 142580364.8, + "min_ns": 136767544, + "max_ns": 142594970, + "std_dev_ns": 1304032.2080032504, + "cv": 0.009434194411295498, + "ops_per_second": 7.23463297408984, + "sample_size": 32, + "files_processed": 2437, + "files_total": 2437, + "files_iterated": 2434, "runtime": "node" }, { "name": "tsv_wasm-internal", "group": "parse/typescript", - "mean_ns": 185893181.86956522, - "p50_ns": 185951421, - "p75_ns": 186885724, - "p90_ns": 190160637.8, - "p95_ns": 190334246.1, - "p99_ns": 190489422.76, - "min_ns": 184637136, - "max_ns": 190527506, - "std_dev_ns": 1018499.6512588013, - "cv": 0.005478951089090762, - "ops_per_second": 5.379433446363112, - "sample_size": 23, - "files_processed": 2395, - "files_total": 2395, - "files_iterated": 2392, + "mean_ns": 181461238.5909091, + "p50_ns": 181644058.5, + "p75_ns": 182662234.25, + "p90_ns": 186091143.5, + "p95_ns": 186646400.9, + "p99_ns": 187115987.78, + "min_ns": 180257801, + "max_ns": 187212563, + "std_dev_ns": 668051.0498416561, + "cv": 0.0036815082660585584, + "ops_per_second": 5.510818771905475, + "sample_size": 22, + "files_processed": 2437, + "files_total": 2437, + "files_iterated": 2434, "runtime": "node" }, { "name": "oxc-parser", "group": "parse/typescript", - "mean_ns": 1242778895.4, - "p50_ns": 1242236446, - "p75_ns": 1245572444, - "p90_ns": 1253627139.8, - "p95_ns": 1256312038.4, - "p99_ns": 1258459957.28, - "min_ns": 1226472744, - "max_ns": 1258996937, - "std_dev_ns": 11637140.274737682, - "cv": 0.009363805836912091, - "ops_per_second": 0.8046483599789008, + "mean_ns": 1305264464.6, + "p50_ns": 1303052331, + "p75_ns": 1315784799, + "p90_ns": 1317236095.2, + "p95_ns": 1317719860.6, + "p99_ns": 1318106872.92, + "min_ns": 1292579213, + "max_ns": 1318203626, + "std_dev_ns": 11371216.016430007, + "cv": 0.00871181000082978, + "ops_per_second": 0.7661282652833511, "sample_size": 5, - "files_processed": 2393, - "files_total": 2395, - "files_iterated": 2392, + "files_processed": 2435, + "files_total": 2437, + "files_iterated": 2434, "runtime": "node" }, { "name": "oxc-parser-wasm", "group": "parse/typescript", - "mean_ns": 1278284391.2, - "p50_ns": 1277503684, - "p75_ns": 1279375787, - "p90_ns": 1280494269.2, - "p95_ns": 1280867096.6, - "p99_ns": 1281165358.52, - "min_ns": 1276292302, - "max_ns": 1281239924, - "std_dev_ns": 2007962.5805837868, - "cv": 0.001570826174837976, - "ops_per_second": 0.7822985298766276, + "mean_ns": 1340864140.6, + "p50_ns": 1339482078, + "p75_ns": 1345894688, + "p90_ns": 1347854462, + "p95_ns": 1348507720, + "p99_ns": 1349030326.4, + "min_ns": 1334671239, + "max_ns": 1349160978, + "std_dev_ns": 6471019.78057924, + "cv": 0.004826007038776976, + "ops_per_second": 0.7457877123572918, "sample_size": 5, - "files_processed": 2393, - "files_total": 2395, - "files_iterated": 2392, + "files_processed": 2435, + "files_total": 2437, + "files_iterated": 2434, "runtime": "node" }, { "name": "prettier", "group": "format/typescript", - "mean_ns": 13271689459.5, - "p50_ns": 13278628109, - "p75_ns": 13287810785.5, - "p90_ns": 13369468124.4, - "p95_ns": 13427209409.7, - "p99_ns": 13473402437.94, - "min_ns": 13241680007, - "max_ns": 13484950695, - "std_dev_ns": 19017356.814433098, - "cv": 0.0014329265970596, - "ops_per_second": 0.07534835734754106, - "sample_size": 6, - "files_processed": 2395, - "files_total": 2395, - "files_iterated": 2393, + "mean_ns": 13701470554.428572, + "p50_ns": 13688704131, + "p75_ns": 13737480943.5, + "p90_ns": 13794213096.6, + "p95_ns": 13807815805.8, + "p99_ns": 13818697973.16, + "min_ns": 13620412338, + "max_ns": 13821418515, + "std_dev_ns": 74004498.3558904, + "cv": 0.005401208436854302, + "ops_per_second": 0.07298486655337746, + "sample_size": 7, + "files_processed": 2437, + "files_total": 2437, + "files_iterated": 2435, "runtime": "node" }, { "name": "tsv", "group": "format/typescript", - "mean_ns": 528027103, - "p50_ns": 526871969, - "p75_ns": 531510214.75, - "p90_ns": 532827519.3, - "p95_ns": 537112641.15, - "p99_ns": 540540738.63, - "min_ns": 525408809, - "max_ns": 541397763, - "std_dev_ns": 2651040.780997908, - "cv": 0.005020652852734168, - "ops_per_second": 1.8938421802942944, - "sample_size": 9, - "files_processed": 2395, - "files_total": 2395, - "files_iterated": 2393, + "mean_ns": 509124494.625, + "p50_ns": 509176305, + "p75_ns": 511313924.5, + "p90_ns": 518118615.6, + "p95_ns": 519801838.8, + "p99_ns": 521148417.36, + "min_ns": 507897695, + "max_ns": 521485062, + "std_dev_ns": 1272951.5968103353, + "cv": 0.002500275689442007, + "ops_per_second": 1.9641561357925994, + "sample_size": 8, + "files_processed": 2437, + "files_total": 2437, + "files_iterated": 2435, "runtime": "node" }, { "name": "tsv_wasm", "group": "format/typescript", - "mean_ns": 792511781.8333334, - "p50_ns": 792332539, - "p75_ns": 792699326.5, - "p90_ns": 792955405.2, - "p95_ns": 792987045.6, - "p99_ns": 793012357.92, - "min_ns": 792089303, - "max_ns": 793018686, - "std_dev_ns": 376288.6243815599, - "cv": 0.00047480508556110537, - "ops_per_second": 1.261810894074887, + "mean_ns": 713786235.5, + "p50_ns": 713440359, + "p75_ns": 715419862.5, + "p90_ns": 723565222.2, + "p95_ns": 729417005.1, + "p99_ns": 734098431.42, + "min_ns": 712205702, + "max_ns": 735268788, + "std_dev_ns": 1350092.421347331, + "cv": 0.0018914520261119985, + "ops_per_second": 1.4009796634695684, "sample_size": 6, - "files_processed": 2395, - "files_total": 2395, - "files_iterated": 2393, + "files_processed": 2437, + "files_total": 2437, + "files_iterated": 2435, "runtime": "node" }, { "name": "oxfmt", "group": "format/typescript", - "mean_ns": 896061266.3333334, - "p50_ns": 893734677.5, - "p75_ns": 900457971.25, - "p90_ns": 904358005, - "p95_ns": 905510124, - "p99_ns": 906431819.2, - "min_ns": 889834375, - "max_ns": 906662243, - "std_dev_ns": 6899702.604315975, - "cv": 0.0077000344324104466, - "ops_per_second": 1.1159951194988955, + "mean_ns": 846371189.8333334, + "p50_ns": 846471155.5, + "p75_ns": 847846588, + "p90_ns": 849893762.5, + "p95_ns": 850845486.75, + "p99_ns": 851606866.15, + "min_ns": 842128092, + "max_ns": 851797211, + "std_dev_ns": 3489476.8747702804, + "cv": 0.004122868212772489, + "ops_per_second": 1.1815146971116999, "sample_size": 6, - "files_processed": 2393, - "files_total": 2395, - "files_iterated": 2393, + "files_processed": 2435, + "files_total": 2437, + "files_iterated": 2435, "runtime": "node" }, { "name": "biome-wasm", "group": "format/typescript", - "mean_ns": 4318335799.25, - "p50_ns": 4306837547, - "p75_ns": 4456404724, - "p90_ns": 8127666755.200001, - "p95_ns": 9351420765.599998, - "p99_ns": 10330423973.92, - "min_ns": 4249152724, - "max_ns": 10575174776, - "std_dev_ns": 95350007.87554793, - "cv": 0.022080267100142638, - "ops_per_second": 0.2315706898416001, - "sample_size": 4, - "files_processed": 2395, - "files_total": 2395, - "files_iterated": 2393, + "mean_ns": 4543705777.666667, + "p50_ns": 4573988027, + "p75_ns": 6561237028, + "p90_ns": 9142297675, + "p95_ns": 10002651224, + "p99_ns": 10690934063.2, + "min_ns": 4509551914, + "max_ns": 10863004773, + "std_dev_ns": 32392054.778861225, + "cv": 0.007128994781765016, + "ops_per_second": 0.22008467293706038, + "sample_size": 3, + "files_processed": 2437, + "files_total": 2437, + "files_iterated": 2435, "runtime": "node" }, { "name": "svelte/compiler", "group": "parse/css", - "mean_ns": 8137606.311926605, - "p50_ns": 8061052, - "p75_ns": 8438520, - "p90_ns": 8874468, - "p95_ns": 9160344, - "p99_ns": 13137245, - "min_ns": 7814981, - "max_ns": 16680571, - "std_dev_ns": 274966.1389864234, - "cv": 0.0337895602768874, - "ops_per_second": 122.88625938248992, - "sample_size": 545, - "files_processed": 50, - "files_total": 50, - "files_iterated": 50, + "mean_ns": 9347109.578740157, + "p50_ns": 9293490, + "p75_ns": 9633911.5, + "p90_ns": 10107438.4, + "p95_ns": 10412161.9, + "p99_ns": 14669984.380000006, + "min_ns": 8743352, + "max_ns": 18666044, + "std_dev_ns": 408421.8437545641, + "cv": 0.04369498830777727, + "ops_per_second": 106.98494455168078, + "sample_size": 508, + "files_processed": 49, + "files_total": 49, + "files_iterated": 49, "runtime": "node" }, { "name": "tsv-json", "group": "parse/css", - "mean_ns": 19083853.226890758, - "p50_ns": 19016013, - "p75_ns": 19472464, - "p90_ns": 19661320.8, - "p95_ns": 21990420.4, - "p99_ns": 22801392.319999997, - "min_ns": 18292035, - "max_ns": 26741666, - "std_dev_ns": 332553.4007836059, - "cv": 0.017425904340692064, - "ops_per_second": 52.40031916567644, - "sample_size": 238, - "files_processed": 50, - "files_total": 50, - "files_iterated": 50, + "mean_ns": 17351701.454545453, + "p50_ns": 17258450, + "p75_ns": 17805835.75, + "p90_ns": 18130577.5, + "p95_ns": 19443740, + "p99_ns": 20335802.999999996, + "min_ns": 16522292, + "max_ns": 20689750, + "std_dev_ns": 409714.6976459913, + "cv": 0.023612364396614394, + "ops_per_second": 57.63123591191341, + "sample_size": 264, + "files_processed": 49, + "files_total": 49, + "files_iterated": 49, "runtime": "node" }, { "name": "tsv_wasm-json", "group": "parse/css", - "mean_ns": 23239919.98924731, - "p50_ns": 23149887.5, - "p75_ns": 23700500.5, - "p90_ns": 24693934.400000002, - "p95_ns": 25644128.249999996, - "p99_ns": 29415525.08, - "min_ns": 22522200, - "max_ns": 33911285, - "std_dev_ns": 391903.2457802182, - "cv": 0.016863364674299428, - "ops_per_second": 43.02940803852517, - "sample_size": 186, - "files_processed": 50, - "files_total": 50, - "files_iterated": 50, + "mean_ns": 18128549.38, + "p50_ns": 18050173, + "p75_ns": 18459952.5, + "p90_ns": 19304880.2, + "p95_ns": 19990566.349999998, + "p99_ns": 23776334.12000002, + "min_ns": 17674567, + "max_ns": 25381253, + "std_dev_ns": 409620.99314898025, + "cv": 0.022595354132465082, + "ops_per_second": 55.161611612633074, + "sample_size": 250, + "files_processed": 49, + "files_total": 49, + "files_iterated": 49, "runtime": "node" }, { "name": "tsv-internal", "group": "parse/css", - "mean_ns": 5325130.134130146, - "p50_ns": 5313147, - "p75_ns": 5391108.75, - "p90_ns": 5567955.4, - "p95_ns": 5660706.6, - "p99_ns": 5764544.63, - "min_ns": 5248306, - "max_ns": 7547689, - "std_dev_ns": 35326.52318709884, - "cv": 0.006633926739307637, - "ops_per_second": 187.78883798364654, - "sample_size": 753, - "files_processed": 50, - "files_total": 50, - "files_iterated": 50, + "mean_ns": 3450014.9639780736, + "p50_ns": 3443839, + "p75_ns": 3484284, + "p90_ns": 3545613, + "p95_ns": 3571906, + "p99_ns": 3605643.77, + "min_ns": 3383350, + "max_ns": 3882445, + "std_dev_ns": 29379.53872333395, + "cv": 0.008515771389425391, + "ops_per_second": 289.85381525619243, + "sample_size": 1277, + "files_processed": 49, + "files_total": 49, + "files_iterated": 49, "runtime": "node" }, { "name": "tsv_wasm-internal", "group": "parse/css", - "mean_ns": 10451037.582463466, - "p50_ns": 10541305, - "p75_ns": 10579751.5, - "p90_ns": 10971946.2, - "p95_ns": 11044040.2, - "p99_ns": 11093265.1, - "min_ns": 9388893, - "max_ns": 11195653, - "std_dev_ns": 318638.22332264925, - "cv": 0.03048866878608444, - "ops_per_second": 95.6842793942269, - "sample_size": 479, - "files_processed": 50, - "files_total": 50, - "files_iterated": 50, + "mean_ns": 4877677.128735633, + "p50_ns": 4871848, + "p75_ns": 4926748, + "p90_ns": 4998469, + "p95_ns": 5036684, + "p99_ns": 5096582.8, + "min_ns": 4786991, + "max_ns": 5376435, + "std_dev_ns": 33056.1643080926, + "cv": 0.006777030015650351, + "ops_per_second": 205.01561985494007, + "sample_size": 870, + "files_processed": 49, + "files_total": 49, + "files_iterated": 49, "runtime": "node" }, { "name": "prettier", "group": "format/css", - "mean_ns": 532893227.3, - "p50_ns": 531806045, - "p75_ns": 540530734, - "p90_ns": 546946840.1, - "p95_ns": 549484908.05, - "p99_ns": 551515362.41, - "min_ns": 519327581, - "max_ns": 552022976, - "std_dev_ns": 11503133.890251184, - "cv": 0.021586188941702063, - "ops_per_second": 1.8765485256149361, + "mean_ns": 549768072.8, + "p50_ns": 548297856, + "p75_ns": 553199518.75, + "p90_ns": 562004047.5, + "p95_ns": 564494511.75, + "p99_ns": 566486883.15, + "min_ns": 532089189, + "max_ns": 566984976, + "std_dev_ns": 9665727.184464993, + "cv": 0.017581463280028062, + "ops_per_second": 1.8189488431129572, "sample_size": 10, - "files_processed": 50, - "files_total": 50, - "files_iterated": 50, + "files_processed": 49, + "files_total": 49, + "files_iterated": 49, "runtime": "node" }, { "name": "tsv", "group": "format/css", - "mean_ns": 9519586.768736616, - "p50_ns": 9492387, - "p75_ns": 9628547.5, - "p90_ns": 9758825, - "p95_ns": 9791909.8, - "p99_ns": 9940429.159999998, - "min_ns": 9415192, - "max_ns": 13605443, - "std_dev_ns": 90579.24197801178, - "cv": 0.00951503927412943, - "ops_per_second": 105.04657652621135, - "sample_size": 467, - "files_processed": 50, - "files_total": 50, - "files_iterated": 50, + "mean_ns": 6974933.896613191, + "p50_ns": 6969074.5, + "p75_ns": 7088710.75, + "p90_ns": 7235676.4, + "p95_ns": 7304980.55, + "p99_ns": 7450989.88, + "min_ns": 6912267, + "max_ns": 10349625, + "std_dev_ns": 45567.8693977457, + "cv": 0.006533089785965144, + "ops_per_second": 143.37053437675857, + "sample_size": 561, + "files_processed": 49, + "files_total": 49, + "files_iterated": 49, "runtime": "node" }, { "name": "tsv_wasm", "group": "format/css", - "mean_ns": 16024151.540192926, - "p50_ns": 15957500, - "p75_ns": 16451584, - "p90_ns": 16493355.9, - "p95_ns": 16545251.9, - "p99_ns": 16754810.57, - "min_ns": 15276016, - "max_ns": 20051655, - "std_dev_ns": 375496.5918146316, - "cv": 0.02343316529881686, - "ops_per_second": 62.405800237955084, - "sample_size": 311, - "files_processed": 50, - "files_total": 50, - "files_iterated": 50, + "mean_ns": 10012727.79342723, + "p50_ns": 9986147, + "p75_ns": 10152856, + "p90_ns": 10294431.2, + "p95_ns": 10368159, + "p99_ns": 10559467.56, + "min_ns": 9890057, + "max_ns": 13671493, + "std_dev_ns": 93950.38210674978, + "cv": 0.009383095600423962, + "ops_per_second": 99.87288385652923, + "sample_size": 426, + "files_processed": 49, + "files_total": 49, + "files_iterated": 49, "runtime": "node" }, { "name": "oxfmt", "group": "format/css", - "mean_ns": 88231718.66666667, - "p50_ns": 88132250, - "p75_ns": 90943233, - "p90_ns": 92246628.2, - "p95_ns": 93054010.8, - "p99_ns": 94548981.16, - "min_ns": 81055515, - "max_ns": 94978663, - "std_dev_ns": 3242031.8429694143, - "cv": 0.0367445165067858, - "ops_per_second": 11.333792598758398, - "sample_size": 57, - "files_processed": 50, - "files_total": 50, - "files_iterated": 50, + "mean_ns": 18467102.220149253, + "p50_ns": 18446410, + "p75_ns": 18882962, + "p90_ns": 19383110, + "p95_ns": 19690833, + "p99_ns": 20404420.500000004, + "min_ns": 16524016, + "max_ns": 22189701, + "std_dev_ns": 659446.4754952398, + "cv": 0.035709255715047974, + "ops_per_second": 54.150347362506665, + "sample_size": 268, + "files_processed": 49, + "files_total": 49, + "files_iterated": 49, "runtime": "node" }, { "name": "biome-wasm", "group": "format/css", - "mean_ns": 159511772.55555555, - "p50_ns": 158966409.5, - "p75_ns": 161913438, - "p90_ns": 164017725, - "p95_ns": 178104497.79999998, - "p99_ns": 186009062.79, - "min_ns": 156648361, - "max_ns": 186181172, - "std_dev_ns": 2194712.3289459804, - "cv": 0.013758936370552807, - "ops_per_second": 6.269129757502475, - "sample_size": 27, - "files_processed": 50, - "files_total": 50, - "files_iterated": 50, + "mean_ns": 125914966.1923077, + "p50_ns": 126099421, + "p75_ns": 137886415.75, + "p90_ns": 194021788, + "p95_ns": 197866488.25, + "p99_ns": 207447585.65, + "min_ns": 123912984, + "max_ns": 208555623, + "std_dev_ns": 2061309.3913787133, + "cv": 0.016370646426815634, + "ops_per_second": 7.941867676577204, + "sample_size": 26, + "files_processed": 49, + "files_total": 49, + "files_iterated": 49, "runtime": "node" } ], diff --git a/src/routes/docs/benchmarks/benchmarks_conformance.json b/src/routes/docs/benchmarks/benchmarks_conformance.json index 7ccb4f9..2f7c107 100644 --- a/src/routes/docs/benchmarks/benchmarks_conformance.json +++ b/src/routes/docs/benchmarks/benchmarks_conformance.json @@ -2,8 +2,8 @@ "version": 7, "runtime": "node", "corpus_kind": "conformance", - "timestamp": "2026-07-08T02:15:20.689Z", - "git_commit": "99ac4c69", + "timestamp": "2026-07-16T00:24:26.030Z", + "git_commit": "eca5466f", "machine": { "cpu_model": "AMD Ryzen 5 PRO 7530U with Radeon Graphics", "os": "linux", @@ -11,7 +11,7 @@ "runtime_version": "24.14.1" }, "corpus": { - "svelte": 4535, + "svelte": 4539, "typescript": 44224, "css": 22641 }, @@ -93,16 +93,16 @@ }, { "path": "../svelte/packages/svelte/tests", - "files": 4451, + "files": 4455, "by_language": { - "svelte": 4133, + "svelte": 4137, "typescript": 137, "css": 181 }, "repo": { "url": "https://github.com/sveltejs/svelte", "slug": "sveltejs/svelte", - "commit": "8fb7ceeba5dd1d3b7fc3f587f4e2138bf1b978ed", + "commit": "b4d1583ae20f3869a88a731d9a265c546c099f66", "subpath": "packages/svelte/tests" } }, @@ -141,79 +141,79 @@ "tsv": "0.1.0", "svelte": "5.56.4", "acorn": "8.16.0", - "acorn_ts": "1.0.10", + "acorn_ts": "1.0.11", "prettier": "3.9.0", "prettier_svelte": "4.1.1", - "oxc_parser": "0.139.0", - "oxfmt": "0.57.0", - "biome": "2.5.2" + "oxc_parser": "0.140.0", + "oxfmt": "0.59.0", + "biome": "2.5.4" }, "binary_sizes": [ { "label": "tsv (ffi)", - "bytes": 3348832, + "bytes": 3407520, "kind": "native", - "gzip_bytes": 1444707 + "gzip_bytes": 1473224 }, { "label": "tsv format (ffi)", - "bytes": 3085648, + "bytes": 3143024, "kind": "native", - "gzip_bytes": 1337366 + "gzip_bytes": 1366105 }, { "label": "tsv parse (ffi)", - "bytes": 1568432, + "bytes": 1602672, "kind": "native", - "gzip_bytes": 691800 + "gzip_bytes": 704951 }, { "label": "tsv (napi)", - "bytes": 3482128, + "bytes": 3540848, "kind": "native", - "gzip_bytes": 1489183 + "gzip_bytes": 1517414 }, { "label": "tsv_format_wasm", - "bytes": 2214519, + "bytes": 2261296, "kind": "wasm", - "gzip_bytes": 763363 + "gzip_bytes": 794602 }, { "label": "tsv_parse_wasm", - "bytes": 1036989, + "bytes": 1057603, "kind": "wasm", - "gzip_bytes": 381243 + "gzip_bytes": 389582 }, { "label": "tsv_wasm", - "bytes": 2444330, + "bytes": 2491362, "kind": "wasm", - "gzip_bytes": 843039 + "gzip_bytes": 875347 }, { "label": "biome (wasm)", - "bytes": 37540009, + "bytes": 38584187, "kind": "wasm", - "gzip_bytes": 9006428 + "gzip_bytes": 9281487 }, { "label": "oxc-parser (napi)", - "bytes": 2428632, + "bytes": 2354904, "kind": "native", - "gzip_bytes": 977389 + "gzip_bytes": 954754 }, { "label": "oxfmt (napi)", - "bytes": 9061136, + "bytes": 8917776, "kind": "native", - "gzip_bytes": 3631974 + "gzip_bytes": 3586269 }, { "label": "oxc-parser (wasm)", - "bytes": 1616596, + "bytes": 1531455, "kind": "wasm", - "gzip_bytes": 501431 + "gzip_bytes": 495227 } ], "entries": [ @@ -232,9 +232,9 @@ "cv": null, "ops_per_second": null, "sample_size": null, - "files_processed": 4535, - "files_total": 4535, - "files_iterated": 4527, + "files_processed": 4539, + "files_total": 4539, + "files_iterated": 4539, "runtime": "node" }, { @@ -252,9 +252,9 @@ "cv": null, "ops_per_second": null, "sample_size": null, - "files_processed": 4527, - "files_total": 4535, - "files_iterated": 4527, + "files_processed": 4539, + "files_total": 4539, + "files_iterated": 4539, "runtime": "node" }, { @@ -272,9 +272,9 @@ "cv": null, "ops_per_second": null, "sample_size": null, - "files_processed": 4527, - "files_total": 4535, - "files_iterated": 4527, + "files_processed": 4539, + "files_total": 4539, + "files_iterated": 4539, "runtime": "node" }, { @@ -292,9 +292,9 @@ "cv": null, "ops_per_second": null, "sample_size": null, - "files_processed": 4527, - "files_total": 4535, - "files_iterated": 4527, + "files_processed": 4539, + "files_total": 4539, + "files_iterated": 4539, "runtime": "node" }, { @@ -312,9 +312,9 @@ "cv": null, "ops_per_second": null, "sample_size": null, - "files_processed": 4527, - "files_total": 4535, - "files_iterated": 4527, + "files_processed": 4539, + "files_total": 4539, + "files_iterated": 4539, "runtime": "node" }, { @@ -332,9 +332,9 @@ "cv": null, "ops_per_second": null, "sample_size": null, - "files_processed": 4527, - "files_total": 4535, - "files_iterated": 4527, + "files_processed": 4539, + "files_total": 4539, + "files_iterated": 4539, "runtime": "node" }, { @@ -352,9 +352,9 @@ "cv": null, "ops_per_second": null, "sample_size": null, - "files_processed": 4527, - "files_total": 4535, - "files_iterated": 4527, + "files_processed": 4539, + "files_total": 4539, + "files_iterated": 4539, "runtime": "node" }, { @@ -372,9 +372,9 @@ "cv": null, "ops_per_second": null, "sample_size": null, - "files_processed": 43641, + "files_processed": 43647, "files_total": 44224, - "files_iterated": 43613, + "files_iterated": 43619, "runtime": "node" }, { @@ -392,9 +392,9 @@ "cv": null, "ops_per_second": null, "sample_size": null, - "files_processed": 44026, + "files_processed": 44023, "files_total": 44224, - "files_iterated": 43613, + "files_iterated": 43619, "runtime": "node" }, { @@ -412,9 +412,9 @@ "cv": null, "ops_per_second": null, "sample_size": null, - "files_processed": 44026, + "files_processed": 44023, "files_total": 44224, - "files_iterated": 43613, + "files_iterated": 43619, "runtime": "node" }, { @@ -432,9 +432,9 @@ "cv": null, "ops_per_second": null, "sample_size": null, - "files_processed": 44026, + "files_processed": 44023, "files_total": 44224, - "files_iterated": 43613, + "files_iterated": 43619, "runtime": "node" }, { @@ -452,9 +452,9 @@ "cv": null, "ops_per_second": null, "sample_size": null, - "files_processed": 44026, + "files_processed": 44023, "files_total": 44224, - "files_iterated": 43613, + "files_iterated": 43619, "runtime": "node" }, { @@ -472,9 +472,9 @@ "cv": null, "ops_per_second": null, "sample_size": null, - "files_processed": 44026, + "files_processed": 44023, "files_total": 44224, - "files_iterated": 43613, + "files_iterated": 43619, "runtime": "node" }, { @@ -492,9 +492,9 @@ "cv": null, "ops_per_second": null, "sample_size": null, - "files_processed": 44026, + "files_processed": 44023, "files_total": 44224, - "files_iterated": 43613, + "files_iterated": 43619, "runtime": "node" }, { @@ -514,7 +514,7 @@ "sample_size": null, "files_processed": 44014, "files_total": 44224, - "files_iterated": 43613, + "files_iterated": 43619, "runtime": "node" }, { @@ -534,7 +534,7 @@ "sample_size": null, "files_processed": 44014, "files_total": 44224, - "files_iterated": 43613, + "files_iterated": 43619, "runtime": "node" }, { @@ -554,7 +554,7 @@ "sample_size": null, "files_processed": 22402, "files_total": 22641, - "files_iterated": 22378, + "files_iterated": 22388, "runtime": "node" }, { @@ -572,9 +572,9 @@ "cv": null, "ops_per_second": null, "sample_size": null, - "files_processed": 22447, + "files_processed": 22457, "files_total": 22641, - "files_iterated": 22378, + "files_iterated": 22388, "runtime": "node" }, { @@ -592,9 +592,9 @@ "cv": null, "ops_per_second": null, "sample_size": null, - "files_processed": 22447, + "files_processed": 22457, "files_total": 22641, - "files_iterated": 22378, + "files_iterated": 22388, "runtime": "node" }, { @@ -612,9 +612,9 @@ "cv": null, "ops_per_second": null, "sample_size": null, - "files_processed": 22447, + "files_processed": 22457, "files_total": 22641, - "files_iterated": 22378, + "files_iterated": 22388, "runtime": "node" }, { @@ -632,9 +632,9 @@ "cv": null, "ops_per_second": null, "sample_size": null, - "files_processed": 22447, + "files_processed": 22457, "files_total": 22641, - "files_iterated": 22378, + "files_iterated": 22388, "runtime": "node" } ], diff --git a/src/routes/docs/benchmarks/benchmarks_cross_runtime.json b/src/routes/docs/benchmarks/benchmarks_cross_runtime.json index 458af11..c400307 100644 --- a/src/routes/docs/benchmarks/benchmarks_cross_runtime.json +++ b/src/routes/docs/benchmarks/benchmarks_cross_runtime.json @@ -1,7 +1,7 @@ { "version": 7, "kind": "combined", - "generated": "2026-07-08T02:14:34.907Z", + "generated": "2026-07-16T00:23:32.612Z", "runtimes": [ "deno", "node", @@ -12,8 +12,8 @@ "sources": [ { "runtime": "deno", - "timestamp": "2026-07-08T01:58:22.087Z", - "git_commit": "99ac4c69", + "timestamp": "2026-07-16T00:07:00.449Z", + "git_commit": "eca5466f", "tsv": "0.1.0", "machine": { "cpu_model": "AMD Ryzen 5 PRO 7530U with Radeon Graphics", @@ -24,8 +24,8 @@ }, { "runtime": "node", - "timestamp": "2026-07-08T02:06:48.550Z", - "git_commit": "99ac4c69", + "timestamp": "2026-07-16T00:15:41.741Z", + "git_commit": "eca5466f", "tsv": "0.1.0", "machine": { "cpu_model": "AMD Ryzen 5 PRO 7530U with Radeon Graphics", @@ -36,8 +36,8 @@ }, { "runtime": "bun", - "timestamp": "2026-07-08T02:14:34.550Z", - "git_commit": "99ac4c69", + "timestamp": "2026-07-16T00:23:32.242Z", + "git_commit": "eca5466f", "tsv": "0.1.0", "machine": { "cpu_model": "AMD Ryzen 5 PRO 7530U with Radeon Graphics", @@ -52,672 +52,672 @@ "group": "parse/svelte", "name": "svelte/compiler", "ops_per_second": { - "deno": 2.359920004092479, - "node": 2.2876558521544856, - "bun": 1.3844352219897311 + "deno": 2.285628509935161, + "node": 2.235438061592186, + "bun": 1.3578408241683035 }, "mean_ns": { - "deno": 423743177, - "node": 437128687.45454544, - "bun": 722316208.1666666 + "deno": 437516418.6363636, + "node": 447339614.1818182, + "bun": 736463348.4285715 }, "files_iterated": { - "deno": 762, - "node": 762, - "bun": 762 + "deno": 763, + "node": 763, + "bun": 763 } }, { "group": "parse/svelte", "name": "tsv-json", "ops_per_second": { - "deno": 5.099248484705135, - "node": 4.76661079247879, - "bun": 6.14093757514019 + "deno": 4.978937108439607, + "node": 4.647455353441698, + "bun": 6.023643379700957 }, "mean_ns": { - "deno": 196107328.95238096, - "node": 209792668.95, - "bun": 162841583.67741936 + "deno": 200846079.84, + "node": 215171513, + "bun": 166012483.96774194 }, "files_iterated": { - "deno": 762, - "node": 762, - "bun": 762 + "deno": 763, + "node": 763, + "bun": 763 } }, { "group": "parse/svelte", "name": "tsv-json-no-locations", "ops_per_second": { - "deno": 7.920377903163113, - "node": 7.515246640866147, - "bun": 8.561892978045261 + "deno": 7.772867582254782, + "node": 7.346194913995057, + "bun": 8.461785290730548 }, "mean_ns": { - "deno": 126256601.92307693, - "node": 133062831.83870968, - "bun": 116796601.23809524 + "deno": 128652648.38461539, + "node": 136124893.45945945, + "bun": 118178370.83333333 }, "files_iterated": { - "deno": 762, - "node": 762, - "bun": 762 + "deno": 763, + "node": 763, + "bun": 763 } }, { "group": "parse/svelte", "name": "tsv_wasm-json", "ops_per_second": { - "deno": 4.2188563748185235, - "node": 4.292074906705749, - "bun": 5.614484046816944 + "deno": 4.101050687272255, + "node": 4.1820297537449, + "bun": 5.5683396984514 }, "mean_ns": { - "deno": 237031060.3529412, - "node": 232987546.05555555, - "bun": 178110756.33333334 + "deno": 243839951.33333334, + "node": 239118337, + "bun": 179586744.73076922 }, "files_iterated": { - "deno": 762, - "node": 762, - "bun": 762 + "deno": 763, + "node": 763, + "bun": 763 } }, { "group": "parse/svelte", "name": "tsv_wasm-json-no-locations", "ops_per_second": { - "deno": 6.304545396191693, - "node": 6.5588494832407696, - "bun": 7.7712621817481295 + "deno": 6.229954607080464, + "node": 6.404659921874018, + "bun": 7.5936032930944695 }, "mean_ns": { - "deno": 158615718.84375, - "node": 152465764.39285713, - "bun": 128679225.66666667 + "deno": 160514813.2, + "node": 156136315.15151516, + "bun": 131689786.96969697 }, "files_iterated": { - "deno": 762, - "node": 762, - "bun": 762 + "deno": 763, + "node": 763, + "bun": 763 } }, { "group": "parse/svelte", "name": "tsv-internal", "ops_per_second": { - "deno": 46.622126237247144, - "node": 46.71052391346464, - "bun": 49.33251176884337 + "deno": 46.18841596375166, + "node": 47.37566678684821, + "bun": 50.64074253836932 }, "mean_ns": { - "deno": 21449043.205607478, - "node": 21408451.805263158, - "bun": 20270607.843478262 + "deno": 21650450.207792208, + "node": 21107882.333333332, + "bun": 19746945.836 }, "files_iterated": { - "deno": 762, - "node": 762, - "bun": 762 + "deno": 763, + "node": 763, + "bun": 763 } }, { "group": "parse/svelte", "name": "tsv_wasm-internal", "ops_per_second": { - "deno": 30.30129681008136, - "node": 23.02742364589511, - "bun": 15.621611032110227 + "deno": 30.239710009615436, + "node": 27.08091961777122, + "bun": 16.13930130591613 }, "mean_ns": { - "deno": 33001887.881818183, - "node": 43426482.06666667, - "bun": 64013884.2238806 + "deno": 33069100.18918919, + "node": 36926367.86764706, + "bun": 61960550.89655172 }, "files_iterated": { - "deno": 762, - "node": 762, - "bun": 762 + "deno": 763, + "node": 763, + "bun": 763 } }, { "group": "format/svelte", "name": "prettier", "ops_per_second": { - "deno": 0.23835181951591405, - "node": 0.22819965358685573, - "bun": 0.2559909781172722 + "deno": 0.2339152576842328, + "node": 0.22364412431315459, + "bun": 0.2679431102133465 }, "mean_ns": { - "deno": 4195478776, - "node": 4382127598.714286, - "bun": 3906387667.857143 + "deno": 4275052469.428571, + "node": 4471389548.333333, + "bun": 3732135523.857143 }, "files_iterated": { - "deno": 762, - "node": 762, - "bun": 762 + "deno": 763, + "node": 763, + "bun": 763 } }, { "group": "format/svelte", "name": "tsv", "ops_per_second": { - "deno": 12.864407622443247, - "node": 12.941344378705613, - "bun": 12.687546825532584 + "deno": 14.132622722181472, + "node": 14.570934896225333, + "bun": 13.969251979432833 }, "mean_ns": { - "deno": 77733855.25, - "node": 77271724.69387755, - "bun": 78817443.1 + "deno": 70758274.64285715, + "node": 68629776.13461539, + "bun": 71585794.39130434 }, "files_iterated": { - "deno": 762, - "node": 762, - "bun": 762 + "deno": 763, + "node": 763, + "bun": 763 } }, { "group": "format/svelte", "name": "tsv_wasm", "ops_per_second": { - "deno": 8.321818060934318, - "node": 8.236988950305946, - "bun": 9.21333313381072 + "deno": 9.041275686610229, + "node": 7.972084634344246, + "bun": 7.240242113046595 }, "mean_ns": { - "deno": 120166049.375, - "node": 121403586.43589744, - "bun": 108538352.56756757 + "deno": 110603861.07692307, + "node": 125437704.925, + "bun": 138116928.1891892 }, "files_iterated": { - "deno": 762, - "node": 762, - "bun": 762 + "deno": 763, + "node": 763, + "bun": 763 } }, { "group": "format/svelte", "name": "oxfmt", "ops_per_second": { - "deno": 0.24926311452182143, - "node": 0.2416835899095184, - "bun": 0.19541495618147933 + "deno": 0.2386665456843671, + "node": 0.2288634551342232, + "bun": 0.1987945582704412 }, "mean_ns": { - "deno": 4011825022.4, - "node": 4137641287, - "bun": 5117315580.857142 + "deno": 4189946258, + "node": 4369417561.285714, + "bun": 5030318780.857142 }, "files_iterated": { - "deno": 762, - "node": 762, - "bun": 762 + "deno": 763, + "node": 763, + "bun": 763 } }, { "group": "format/svelte", "name": "biome-wasm", "ops_per_second": { - "deno": 1.4860108444222784, - "node": 1.1364480469032656 + "deno": 1.4335186890951448, + "node": 1.0879748354379855 }, "mean_ns": { - "deno": 672942599.1428572, - "node": 879934637.3333334 + "deno": 697584208.4285715, + "node": 919138906 }, "files_iterated": { - "deno": 762, - "node": 762 + "deno": 763, + "node": 763 } }, { "group": "parse/typescript", "name": "acorn-typescript", "ops_per_second": { - "deno": 0.3631740043550423, - "node": 0.3370156994247567, - "bun": 0.16513734236287647 + "deno": 0.35329029052074107, + "node": 0.3196778195072388, + "bun": 0.1495967948405602 }, "mean_ns": { - "deno": 2753501043.6, - "node": 2967220820, - "bun": 6055565541.333333 + "deno": 2830533492.8, + "node": 3128149464.8, + "bun": 6684635196 }, "files_iterated": { - "deno": 2392, - "node": 2392, - "bun": 2392 + "deno": 2434, + "node": 2434, + "bun": 2434 } }, { "group": "parse/typescript", "name": "tsv-json", "ops_per_second": { - "deno": 0.5663841925680717, - "node": 0.5088079904505298, - "bun": 0.7577790647617878 + "deno": 0.5483532036994702, + "node": 0.49680536982576506, + "bun": 0.7396523440970465 }, "mean_ns": { - "deno": 1765585998.2, - "node": 1965377939.75, - "bun": 1319645852.6 + "deno": 1823642122, + "node": 2012860691, + "bun": 1351986521.75 }, "files_iterated": { - "deno": 2392, - "node": 2392, - "bun": 2392 + "deno": 2434, + "node": 2434, + "bun": 2434 } }, { "group": "parse/typescript", "name": "tsv-json-no-locations", "ops_per_second": { - "deno": 1.1690456155223983, - "node": 1.0465604032804974, - "bun": 1.323262537343759 + "deno": 1.1413193328402957, + "node": 1.0086262314650507, + "bun": 1.2917892945450717 }, "mean_ns": { - "deno": 855398614.6666666, - "node": 955511021.5, - "bun": 755707935.3333334 + "deno": 876178972.2, + "node": 991447544, + "bun": 774120055.2 }, "files_iterated": { - "deno": 2392, - "node": 2392, - "bun": 2392 + "deno": 2434, + "node": 2434, + "bun": 2434 } }, { "group": "parse/typescript", "name": "tsv_wasm-json", "ops_per_second": { - "deno": 0.4877980716238244, - "node": 0.4778961160112595, - "bun": 0.6993176883192254 + "deno": 0.47600201582902885, + "node": 0.46773723211893914, + "bun": 0.6844249374667883 }, "mean_ns": { - "deno": 2050028604.4, - "node": 2092504974.4, - "bun": 1429965260 + "deno": 2100831439.25, + "node": 2137952532.6, + "bun": 1461080602.5 }, "files_iterated": { - "deno": 2392, - "node": 2392, - "bun": 2392 + "deno": 2434, + "node": 2434, + "bun": 2434 } }, { "group": "parse/typescript", "name": "tsv_wasm-json-no-locations", "ops_per_second": { - "deno": 0.955610890981428, - "node": 0.9541695512015291, - "bun": 1.202473058037997 + "deno": 0.9340477377279914, + "node": 0.9230837738922645, + "bun": 1.1738954315046863 }, "mean_ns": { - "deno": 1046451028.8, - "node": 1048031766.2, - "bun": 831619464 + "deno": 1070609091.6, + "node": 1083325293.2, + "bun": 851864632.2 }, "files_iterated": { - "deno": 2392, - "node": 2392, - "bun": 2392 + "deno": 2434, + "node": 2434, + "bun": 2434 } }, { "group": "parse/typescript", "name": "tsv-internal", "ops_per_second": { - "deno": 7.361707998044122, - "node": 7.273649199721218, - "bun": 8.095366681946098 + "deno": 7.5837117839562564, + "node": 7.23463297408984, + "bun": 8.334939591955754 }, "mean_ns": { - "deno": 135838041.96875, - "node": 137482572.02702704, - "bun": 123527449.625 + "deno": 131861551.2413793, + "node": 138224012.6875, + "bun": 119976874.33333333 }, "files_iterated": { - "deno": 2392, - "node": 2392, - "bun": 2392 + "deno": 2434, + "node": 2434, + "bun": 2434 } }, { "group": "parse/typescript", "name": "tsv_wasm-internal", "ops_per_second": { - "deno": 4.862750158766582, - "node": 5.379433446363112, - "bun": 5.534716823989978 + "deno": 4.817702444462784, + "node": 5.510818771905475, + "bun": 5.757212881588537 }, "mean_ns": { - "deno": 205644947.27272728, - "node": 185893181.86956522, - "bun": 180677717 + "deno": 207567821.2857143, + "node": 181461238.5909091, + "bun": 173695157.80769232 }, "files_iterated": { - "deno": 2392, - "node": 2392, - "bun": 2392 + "deno": 2434, + "node": 2434, + "bun": 2434 } }, { "group": "parse/typescript", "name": "oxc-parser", "ops_per_second": { - "deno": 0.8581920201813122, - "node": 0.8046483599789008, - "bun": 1.084773253832389 + "deno": 0.8622608285121847, + "node": 0.7661282652833511, + "bun": 1.045945698068123 }, "mean_ns": { - "deno": 1165240385, - "node": 1242778895.4, - "bun": 921851637.1666666 + "deno": 1159741886.6, + "node": 1305264464.6, + "bun": 956072578 }, "files_iterated": { - "deno": 2392, - "node": 2392, - "bun": 2392 + "deno": 2434, + "node": 2434, + "bun": 2434 } }, { "group": "parse/typescript", "name": "oxc-parser-wasm", "ops_per_second": { - "deno": 0.7912789082449665, - "node": 0.7822985298766276 + "deno": 0.7643562384275462, + "node": 0.7457877123572918 }, "mean_ns": { - "deno": 1263776892.8, - "node": 1278284391.2 + "deno": 1308290493, + "node": 1340864140.6 }, "files_iterated": { - "deno": 2392, - "node": 2392 + "deno": 2434, + "node": 2434 } }, { "group": "format/typescript", "name": "prettier", "ops_per_second": { - "deno": 0.08218262308324435, - "node": 0.07534835734754106, - "bun": 0.06676359375259427 + "deno": 0.08168339424657242, + "node": 0.07298486655337746, + "bun": 0.06656272354486883 }, "mean_ns": { - "deno": 12168022417.428572, - "node": 13271689459.5, - "bun": 14978223067.285715 + "deno": 12242390380.857143, + "node": 13701470554.428572, + "bun": 15023423723.428572 }, "files_iterated": { - "deno": 2393, - "node": 2393, - "bun": 2393 + "deno": 2435, + "node": 2435, + "bun": 2435 } }, { "group": "format/typescript", "name": "tsv", "ops_per_second": { - "deno": 1.9076503330897336, - "node": 1.8938421802942944, - "bun": 1.8728488271086947 + "deno": 1.9961240062496248, + "node": 1.9641561357925994, + "bun": 1.9294423038823494 }, "mean_ns": { - "deno": 524205082.375, - "node": 528027103, - "bun": 533945925.3333333 + "deno": 500970880, + "node": 509124494.625, + "bun": 518284479.4 }, "files_iterated": { - "deno": 2393, - "node": 2393, - "bun": 2393 + "deno": 2435, + "node": 2435, + "bun": 2435 } }, { "group": "format/typescript", "name": "tsv_wasm", "ops_per_second": { - "deno": 1.2259922441593323, - "node": 1.261810894074887, - "bun": 1.3752774218783927 + "deno": 1.2700370044501141, + "node": 1.4009796634695684, + "bun": 1.444034749537169 }, "mean_ns": { - "deno": 815665845.1666666, - "node": 792511781.8333334, - "bun": 727126021.3333334 + "deno": 787378632.6666666, + "node": 713786235.5, + "bun": 692504110.6666666 }, "files_iterated": { - "deno": 2393, - "node": 2393, - "bun": 2393 + "deno": 2435, + "node": 2435, + "bun": 2435 } }, { "group": "format/typescript", "name": "oxfmt", "ops_per_second": { - "deno": 1.0957343465666267, - "node": 1.1159951194988955, - "bun": 0.9402447651039646 + "deno": 1.1975316138276806, + "node": 1.1815146971116999, + "bun": 0.9861111200984184 }, "mean_ns": { - "deno": 912629966.5, - "node": 896061266.3333334, - "bun": 1063552850.4 + "deno": 835051023.6666666, + "node": 846371189.8333334, + "bun": 1014084497.8 }, "files_iterated": { - "deno": 2393, - "node": 2393, - "bun": 2393 + "deno": 2435, + "node": 2435, + "bun": 2435 } }, { "group": "format/typescript", "name": "biome-wasm", "ops_per_second": { - "deno": 0.25228126066618684, - "node": 0.2315706898416001 + "deno": 0.24188581102985876, + "node": 0.22008467293706038 }, "mean_ns": { - "deno": 3963829883.2, - "node": 4318335799.25 + "deno": 4134182140.5, + "node": 4543705777.666667 }, "files_iterated": { - "deno": 2393, - "node": 2393 + "deno": 2435, + "node": 2435 } }, { "group": "parse/css", "name": "svelte/compiler", "ops_per_second": { - "deno": 109.3969935050034, - "node": 122.88625938248992, - "bun": 76.86264960036395 + "deno": 98.93298769631505, + "node": 106.98494455168078, + "bun": 68.90093378590163 }, "mean_ns": { - "deno": 9141019.034990791, - "node": 8137606.311926605, - "bun": 13010220.246105919 + "deno": 10107852.024742268, + "node": 9347109.578740157, + "bun": 14513591.399317406 }, "files_iterated": { - "deno": 50, - "node": 50, - "bun": 50 + "deno": 49, + "node": 49, + "bun": 49 } }, { "group": "parse/css", "name": "tsv-json", "ops_per_second": { - "deno": 59.565136276411586, - "node": 52.40031916567644, - "bun": 65.24600109231139 + "deno": 66.34546835074023, + "node": 57.63123591191341, + "bun": 73.53134124860561 }, "mean_ns": { - "deno": 16788344.029962547, - "node": 19083853.226890758, - "bun": 15326609.803797469 + "deno": 15072619.5, + "node": 17351701.454545453, + "bun": 13599643.132022472 }, "files_iterated": { - "deno": 50, - "node": 50, - "bun": 50 + "deno": 49, + "node": 49, + "bun": 49 } }, { "group": "parse/css", "name": "tsv_wasm-json", "ops_per_second": { - "deno": 45.40042853544365, - "node": 43.02940803852517, - "bun": 58.722798915048436 + "deno": 51.91490176297957, + "node": 55.161611612633074, + "bun": 68.54996875475906 }, "mean_ns": { - "deno": 22026223.810185187, - "node": 23239919.98924731, - "bun": 17029161.049469966 + "deno": 19262292.05952381, + "node": 18128549.38, + "bun": 14587898.69879518 }, "files_iterated": { - "deno": 50, - "node": 50, - "bun": 50 + "deno": 49, + "node": 49, + "bun": 49 } }, { "group": "parse/css", "name": "tsv-internal", "ops_per_second": { - "deno": 195.24379041908716, - "node": 187.78883798364654, - "bun": 201.8433374812 + "deno": 302.219358954193, + "node": 289.85381525619243, + "bun": 327.6279956934774 }, "mean_ns": { - "deno": 5121801.814303638, - "node": 5325130.134130146, - "bun": 4954337.4206896555 + "deno": 3308854.8776637726, + "node": 3450014.9639780736, + "bun": 3052242.2172236503 }, "files_iterated": { - "deno": 50, - "node": 50, - "bun": 50 + "deno": 49, + "node": 49, + "bun": 49 } }, { "group": "parse/css", "name": "tsv_wasm-internal", "ops_per_second": { - "deno": 118.15317177491943, - "node": 95.6842793942269, - "bun": 136.9018403203121 + "deno": 181.94047334155198, + "node": 205.01561985494007, + "bun": 218.85532690450955 }, "mean_ns": { - "deno": 8463589.973741794, - "node": 10451037.582463466, - "bun": 7304503.706161138 + "deno": 5496303.1679198, + "node": 4877677.128735633, + "bun": 4569228.513392857 }, "files_iterated": { - "deno": 50, - "node": 50, - "bun": 50 + "deno": 49, + "node": 49, + "bun": 49 } }, { "group": "format/css", "name": "prettier", "ops_per_second": { - "deno": 2.0542349193785063, - "node": 1.8765485256149361, - "bun": 2.04491736733658 + "deno": 1.9553847496366528, + "node": 1.8189488431129572, + "bun": 2.1579001199965315 }, "mean_ns": { - "deno": 486799241.2, - "node": 532893227.3, - "bun": 489017314.8181818 + "deno": 511408304.7777778, + "node": 549768072.8, + "bun": 463413478.1 }, "files_iterated": { - "deno": 50, - "node": 50, - "bun": 50 + "deno": 49, + "node": 49, + "bun": 49 } }, { "group": "format/css", "name": "tsv", "ops_per_second": { - "deno": 108.96736555765507, - "node": 105.04657652621135, - "bun": 107.4758150429946 + "deno": 148.55186580257475, + "node": 143.37053437675857, + "bun": 147.4505147240052 }, "mean_ns": { - "deno": 9177059.52495379, - "node": 9519586.768736616, - "bun": 9304418.85553471 + "deno": 6731655.604575164, + "node": 6974933.896613191, + "bun": 6781936.311797753 }, "files_iterated": { - "deno": 50, - "node": 50, - "bun": 50 + "deno": 49, + "node": 49, + "bun": 49 } }, { "group": "format/css", "name": "tsv_wasm", "ops_per_second": { - "deno": 64.65491414835293, - "node": 62.405800237955084, - "bun": 76.17264922474205 + "deno": 87.91100033975918, + "node": 99.87288385652923, + "bun": 101.73318795414885 }, "mean_ns": { - "deno": 15466728.448598132, - "node": 16024151.540192926, - "bun": 13128071.692105263 + "deno": 11375140.723404255, + "node": 10012727.79342723, + "bun": 9829633.968127491 }, "files_iterated": { - "deno": 50, - "node": 50, - "bun": 50 + "deno": 49, + "node": 49, + "bun": 49 } }, { "group": "format/css", "name": "oxfmt", "ops_per_second": { - "deno": 11.704967558016936, - "node": 11.333792598758398, - "bun": 10.583357868718569 + "deno": 55.35609448255786, + "node": 54.150347362506665, + "bun": 45.66585793057103 }, "mean_ns": { - "deno": 85433812.18644068, - "node": 88231718.66666667, - "bun": 94487969.9245283 + "deno": 18064858.24817518, + "node": 18467102.220149253, + "bun": 21898198.026200872 }, "files_iterated": { - "deno": 50, - "node": 50, - "bun": 50 + "deno": 49, + "node": 49, + "bun": 49 } }, { "group": "format/css", "name": "biome-wasm", "ops_per_second": { - "deno": 11.054056923387016, - "node": 6.269129757502475 + "deno": 10.303043141246484, + "node": 7.941867676577204 }, "mean_ns": { - "deno": 90464524.19512194, - "node": 159511772.55555555 + "deno": 97058702.58823529, + "node": 125914966.1923077 }, "files_iterated": { - "deno": 50, - "node": 50 + "deno": 49, + "node": 49 } } ] From 4eaa9148607086a76b4304267e7fc978ef59c8fc Mon Sep 17 00:00:00 2001 From: Ryan Atkinson Date: Thu, 16 Jul 2026 07:55:05 -0400 Subject: [PATCH 048/218] update --- src/routes/docs/benchmarks/benchmarks.json | 842 +++++++++--------- .../benchmarks/benchmarks_conformance.json | 12 +- .../benchmarks/benchmarks_cross_runtime.json | 430 ++++----- 3 files changed, 642 insertions(+), 642 deletions(-) diff --git a/src/routes/docs/benchmarks/benchmarks.json b/src/routes/docs/benchmarks/benchmarks.json index 3a039a2..eefd677 100644 --- a/src/routes/docs/benchmarks/benchmarks.json +++ b/src/routes/docs/benchmarks/benchmarks.json @@ -2,8 +2,8 @@ "version": 7, "runtime": "node", "corpus_kind": "perf", - "timestamp": "2026-07-16T00:15:41.741Z", - "git_commit": "eca5466f", + "timestamp": "2026-07-16T11:43:29.034Z", + "git_commit": "135b7b93", "machine": { "cpu_model": "AMD Ryzen 5 PRO 7530U with Radeon Graphics", "os": "linux", @@ -237,7 +237,7 @@ "repo": { "url": "https://github.com/fuzdev/tsv.fuz.dev", "slug": "fuzdev/tsv.fuz.dev", - "commit": "dee909612d74958231dcc2152d6b2cb1b0db3e3c", + "commit": "b4259d21b582908e9e68ad9c1f774b44d0315951", "subpath": "src" } }, @@ -394,9 +394,9 @@ }, { "label": "tsv_format_wasm", - "bytes": 2261296, + "bytes": 2261397, "kind": "wasm", - "gzip_bytes": 794602 + "gzip_bytes": 794650 }, { "label": "tsv_parse_wasm", @@ -406,9 +406,9 @@ }, { "label": "tsv_wasm", - "bytes": 2491362, + "bytes": 2491464, "kind": "wasm", - "gzip_bytes": 875347 + "gzip_bytes": 875399 }, { "label": "biome (wasm)", @@ -439,18 +439,18 @@ { "name": "svelte/compiler", "group": "parse/svelte", - "mean_ns": 447339614.1818182, - "p50_ns": 446240894, - "p75_ns": 451111701, - "p90_ns": 457976256, - "p95_ns": 464629570, - "p99_ns": 470677924.40000004, - "min_ns": 442688667, - "max_ns": 472190013, - "std_dev_ns": 4933722.594169536, - "cv": 0.011029031272343918, - "ops_per_second": 2.235438061592186, - "sample_size": 11, + "mean_ns": 454203272.7, + "p50_ns": 452307877, + "p75_ns": 458399053.5, + "p90_ns": 464037260, + "p95_ns": 466877383, + "p99_ns": 469149481.4, + "min_ns": 449538372, + "max_ns": 469717506, + "std_dev_ns": 4803639.789213478, + "cv": 0.01057596912646261, + "ops_per_second": 2.201657407828713, + "sample_size": 10, "files_processed": 763, "files_total": 763, "files_iterated": 763, @@ -459,18 +459,18 @@ { "name": "tsv-json", "group": "parse/svelte", - "mean_ns": 215171513, - "p50_ns": 214558414.5, - "p75_ns": 217842026, - "p90_ns": 218923022.1, - "p95_ns": 219063741.85, - "p99_ns": 219130613.53, - "min_ns": 212126483, - "max_ns": 219145354, - "std_dev_ns": 2646489.822478956, - "cv": 0.012299443293308794, - "ops_per_second": 4.647455353441698, - "sample_size": 24, + "mean_ns": 215081564.7368421, + "p50_ns": 215189540, + "p75_ns": 216663830.5, + "p90_ns": 220507872.8, + "p95_ns": 221245016.95, + "p99_ns": 221476217.61, + "min_ns": 213977606, + "max_ns": 221507381, + "std_dev_ns": 948167.8303000326, + "cv": 0.004408410509102166, + "ops_per_second": 4.649398944179739, + "sample_size": 19, "files_processed": 763, "files_total": 763, "files_iterated": 763, @@ -479,18 +479,18 @@ { "name": "tsv-json-no-locations", "group": "parse/svelte", - "mean_ns": 136124893.45945945, - "p50_ns": 135970730, - "p75_ns": 137925210, - "p90_ns": 138865033, - "p95_ns": 139075628.8, - "p99_ns": 139091043.52, - "min_ns": 133615681, - "max_ns": 139099177, - "std_dev_ns": 1834282.8925741522, - "cv": 0.013474999656256379, - "ops_per_second": 7.346194913995057, - "sample_size": 37, + "mean_ns": 136455370.6875, + "p50_ns": 136247751, + "p75_ns": 138650167, + "p90_ns": 140117388, + "p95_ns": 140433077.8, + "p99_ns": 140673837.16, + "min_ns": 134355882, + "max_ns": 140777218, + "std_dev_ns": 1333831.388734515, + "cv": 0.009774854459845023, + "ops_per_second": 7.328403381719038, + "sample_size": 32, "files_processed": 763, "files_total": 763, "files_iterated": 763, @@ -499,17 +499,17 @@ { "name": "tsv_wasm-json", "group": "parse/svelte", - "mean_ns": 239118337, - "p50_ns": 238069355, - "p75_ns": 243537130, - "p90_ns": 244283174, - "p95_ns": 244685278, - "p99_ns": 244940574, - "min_ns": 234170486, - "max_ns": 245004398, - "std_dev_ns": 3814109.8642763034, - "cv": 0.01595072093645542, - "ops_per_second": 4.1820297537449, + "mean_ns": 242380851.47619048, + "p50_ns": 241554679, + "p75_ns": 243217969, + "p90_ns": 246015818, + "p95_ns": 247299957, + "p99_ns": 247768187.4, + "min_ns": 239665776, + "max_ns": 247885245, + "std_dev_ns": 2512562.793305207, + "cv": 0.010366176940145046, + "ops_per_second": 4.125738456275007, "sample_size": 21, "files_processed": 763, "files_total": 763, @@ -519,18 +519,18 @@ { "name": "tsv_wasm-json-no-locations", "group": "parse/svelte", - "mean_ns": 156136315.15151516, - "p50_ns": 155336306, - "p75_ns": 158317362, - "p90_ns": 159514124.6, - "p95_ns": 159781601.2, - "p99_ns": 160128001.64, - "min_ns": 153129079, - "max_ns": 160151193, - "std_dev_ns": 2250222.6645511542, - "cv": 0.014411910914943338, - "ops_per_second": 6.404659921874018, - "sample_size": 33, + "mean_ns": 156798038.8, + "p50_ns": 156579356.5, + "p75_ns": 157972638, + "p90_ns": 160523542.9, + "p95_ns": 161067885.6, + "p99_ns": 161407787.75, + "min_ns": 154628462, + "max_ns": 161516032, + "std_dev_ns": 1713706.0912863356, + "cv": 0.010929384732115256, + "ops_per_second": 6.377630789601431, + "sample_size": 30, "files_processed": 763, "files_total": 763, "files_iterated": 763, @@ -539,18 +539,18 @@ { "name": "tsv-internal", "group": "parse/svelte", - "mean_ns": 21107882.333333332, - "p50_ns": 20939483, - "p75_ns": 21520190, - "p90_ns": 21684446, - "p95_ns": 21796098.4, - "p99_ns": 21943351.32, - "min_ns": 20706273, - "max_ns": 21987371, - "std_dev_ns": 349471.32487507124, - "cv": 0.01655643703883975, - "ops_per_second": 47.37566678684821, - "sample_size": 225, + "mean_ns": 20890458.785714287, + "p50_ns": 20811285.5, + "p75_ns": 21412932, + "p90_ns": 21589212.6, + "p95_ns": 21645572.95, + "p99_ns": 21758236.37, + "min_ns": 20633297, + "max_ns": 21784005, + "std_dev_ns": 269196.59333167557, + "cv": 0.012886102507033629, + "ops_per_second": 47.86874286762142, + "sample_size": 196, "files_processed": 763, "files_total": 763, "files_iterated": 763, @@ -559,18 +559,18 @@ { "name": "tsv_wasm-internal", "group": "parse/svelte", - "mean_ns": 36926367.86764706, - "p50_ns": 37761837.5, - "p75_ns": 40590030.5, - "p90_ns": 41538579, - "p95_ns": 42050564.5, - "p99_ns": 42599705.25, - "min_ns": 28609958, - "max_ns": 42781237, - "std_dev_ns": 4415963.897212026, - "cv": 0.11958836333537859, - "ops_per_second": 27.08091961777122, - "sample_size": 136, + "mean_ns": 37349926.47014926, + "p50_ns": 38076093, + "p75_ns": 41060368.5, + "p90_ns": 41948649.5, + "p95_ns": 42197316.75, + "p99_ns": 43256069.93999999, + "min_ns": 29812236, + "max_ns": 44793850, + "std_dev_ns": 4259994.387091226, + "cv": 0.11405629916021097, + "ops_per_second": 26.773814422344802, + "sample_size": 134, "files_processed": 763, "files_total": 763, "files_iterated": 763, @@ -579,17 +579,17 @@ { "name": "prettier", "group": "format/svelte", - "mean_ns": 4471389548.333333, - "p50_ns": 4443221170, - "p75_ns": 4549812450.5, - "p90_ns": 4633226047.4, - "p95_ns": 4677811261.7, - "p99_ns": 4713479433.14, - "min_ns": 4414423312, - "max_ns": 4722396476, - "std_dev_ns": 63436270.564138755, - "cv": 0.014187149180009156, - "ops_per_second": 0.22364412431315459, + "mean_ns": 4410834541, + "p50_ns": 4409030122, + "p75_ns": 4424887650.5, + "p90_ns": 4449574229, + "p95_ns": 4463048301.5, + "p99_ns": 4473827559.5, + "min_ns": 4398618080, + "max_ns": 4476522374, + "std_dev_ns": 12538592.212289287, + "cv": 0.002842680244688255, + "ops_per_second": 0.2267144665492906, "sample_size": 6, "files_processed": 763, "files_total": 763, @@ -599,18 +599,18 @@ { "name": "tsv", "group": "format/svelte", - "mean_ns": 68629776.13461539, - "p50_ns": 68564213, - "p75_ns": 70730671, - "p90_ns": 71067604.2, - "p95_ns": 71156349, - "p99_ns": 71293163.4, - "min_ns": 68239242, - "max_ns": 71475201, - "std_dev_ns": 475041.82611961645, - "cv": 0.006921803521372926, - "ops_per_second": 14.570934896225333, - "sample_size": 52, + "mean_ns": 69682693.5, + "p50_ns": 69152510, + "p75_ns": 71057711.5, + "p90_ns": 71481026.5, + "p95_ns": 71580183.45, + "p99_ns": 71657562.64, + "min_ns": 68466829, + "max_ns": 71705144, + "std_dev_ns": 1150612.102643583, + "cv": 0.01651216456843166, + "ops_per_second": 14.35076558858908, + "sample_size": 72, "files_processed": 763, "files_total": 763, "files_iterated": 763, @@ -619,17 +619,17 @@ { "name": "tsv_wasm", "group": "format/svelte", - "mean_ns": 125437704.925, - "p50_ns": 125111866.5, - "p75_ns": 126811968.25, - "p90_ns": 131013833.1, - "p95_ns": 133430926.7, - "p99_ns": 133875215.12, - "min_ns": 119804914, - "max_ns": 134102543, - "std_dev_ns": 3709061.4868603325, - "cv": 0.02956895208723728, - "ops_per_second": 7.972084634344246, + "mean_ns": 126127615.175, + "p50_ns": 126569065, + "p75_ns": 128091580.75, + "p90_ns": 129881477.4, + "p95_ns": 130874369.55, + "p99_ns": 131097384.84, + "min_ns": 119589561, + "max_ns": 131122908, + "std_dev_ns": 3059562.225237535, + "cv": 0.024257671256151497, + "ops_per_second": 7.928477824721544, "sample_size": 40, "files_processed": 763, "files_total": 763, @@ -639,17 +639,17 @@ { "name": "oxfmt", "group": "format/svelte", - "mean_ns": 4369417561.285714, - "p50_ns": 4381486391, - "p75_ns": 4423110874.5, - "p90_ns": 4436920148.2, - "p95_ns": 4439500419.1, - "p99_ns": 4441564635.82, - "min_ns": 4285702265, - "max_ns": 4442080690, - "std_dev_ns": 64002452.31291099, - "cv": 0.014647822373396164, - "ops_per_second": 0.2288634551342232, + "mean_ns": 4349035130.714286, + "p50_ns": 4378245513, + "p75_ns": 4397739938.5, + "p90_ns": 4399973164.6, + "p95_ns": 4400683105.3, + "p99_ns": 4401251057.86, + "min_ns": 4277748939, + "max_ns": 4401393046, + "std_dev_ns": 56604561.29704797, + "cv": 0.013015429766774783, + "ops_per_second": 0.22993605936582995, "sample_size": 7, "files_processed": 763, "files_total": 763, @@ -659,17 +659,17 @@ { "name": "biome-wasm", "group": "format/svelte", - "mean_ns": 919138906, - "p50_ns": 919126476.5, - "p75_ns": 925856692.5, - "p90_ns": 929440736, - "p95_ns": 930578349.5, - "p99_ns": 931488440.3, - "min_ns": 907217162, - "max_ns": 931715963, - "std_dev_ns": 9543624.6422586, - "cv": 0.010383223449643203, - "ops_per_second": 1.0879748354379855, + "mean_ns": 922724214.3333334, + "p50_ns": 921258645, + "p75_ns": 925929470, + "p90_ns": 931597465, + "p95_ns": 933881452, + "p99_ns": 935708641.6, + "min_ns": 912930502, + "max_ns": 936165439, + "std_dev_ns": 8104189.841280956, + "cv": 0.008782894948883745, + "ops_per_second": 1.0837474344623093, "sample_size": 6, "files_processed": 763, "files_total": 763, @@ -679,17 +679,17 @@ { "name": "acorn-typescript", "group": "parse/typescript", - "mean_ns": 3128149464.8, - "p50_ns": 3128265157, - "p75_ns": 3134995396, - "p90_ns": 3135699313, - "p95_ns": 3135933952, - "p99_ns": 3136121663.2, - "min_ns": 3118724019, - "max_ns": 3136168591, - "std_dev_ns": 7597482.683936056, - "cv": 0.0024287466981446825, - "ops_per_second": 0.3196778195072388, + "mean_ns": 3095283600.8, + "p50_ns": 3095095186, + "p75_ns": 3097767418, + "p90_ns": 3099323611.6, + "p95_ns": 3099842342.8, + "p99_ns": 3100257327.76, + "min_ns": 3091472519, + "max_ns": 3100361074, + "std_dev_ns": 3846956.6437835894, + "cv": 0.0012428446436343712, + "ops_per_second": 0.3230721733354392, "sample_size": 5, "files_processed": 2434, "files_total": 2437, @@ -699,18 +699,18 @@ { "name": "tsv-json", "group": "parse/typescript", - "mean_ns": 2012860691, - "p50_ns": 2012491511, - "p75_ns": 2013025755, - "p90_ns": 2016083350.2, - "p95_ns": 2017102548.6, - "p99_ns": 2017917907.32, - "min_ns": 2009308204, - "max_ns": 2018121747, - "std_dev_ns": 3268248.4967490616, - "cv": 0.0016236834031099182, - "ops_per_second": 0.49680536982576506, - "sample_size": 5, + "mean_ns": 2055685813.75, + "p50_ns": 2054412961, + "p75_ns": 2062088510, + "p90_ns": 2064528234.2, + "p95_ns": 2065341475.6, + "p99_ns": 2065992068.72, + "min_ns": 2052635587, + "max_ns": 2066154717, + "std_dev_ns": 4329871.531821806, + "cv": 0.0021062905152432884, + "ops_per_second": 0.4864556603500567, + "sample_size": 4, "files_processed": 2437, "files_total": 2437, "files_iterated": 2434, @@ -719,17 +719,17 @@ { "name": "tsv-json-no-locations", "group": "parse/typescript", - "mean_ns": 991447544, - "p50_ns": 991790889.5, - "p75_ns": 992641387.5, - "p90_ns": 992889675, - "p95_ns": 992974106.5, - "p99_ns": 993041651.7, - "min_ns": 988885149, - "max_ns": 993058538, - "std_dev_ns": 1599060.9985106883, - "cv": 0.0016128548688105766, - "ops_per_second": 1.0086262314650507, + "mean_ns": 998270334.8333334, + "p50_ns": 998682441, + "p75_ns": 999030412, + "p90_ns": 999361650.5, + "p95_ns": 999480538.25, + "p99_ns": 999575648.45, + "min_ns": 996556819, + "max_ns": 999599426, + "std_dev_ns": 1220872.2439011242, + "cv": 0.0012229876029572245, + "ops_per_second": 1.0017326620919327, "sample_size": 6, "files_processed": 2437, "files_total": 2437, @@ -739,17 +739,17 @@ { "name": "tsv_wasm-json", "group": "parse/typescript", - "mean_ns": 2137952532.6, - "p50_ns": 2137949434, - "p75_ns": 2142934848, - "p90_ns": 2144094183, - "p95_ns": 2144480628, - "p99_ns": 2144789784, - "min_ns": 2131022798, - "max_ns": 2144867073, - "std_dev_ns": 6026962.072416319, - "cv": 0.0028190345578378343, - "ops_per_second": 0.46773723211893914, + "mean_ns": 2190385709.6, + "p50_ns": 2189048667, + "p75_ns": 2195488548, + "p90_ns": 2195623038.6, + "p95_ns": 2195667868.8, + "p99_ns": 2195703732.96, + "min_ns": 2183175920, + "max_ns": 2195712699, + "std_dev_ns": 5285125.287642885, + "cv": 0.0024128742551959193, + "ops_per_second": 0.4565405972186589, "sample_size": 5, "files_processed": 2437, "files_total": 2437, @@ -759,17 +759,17 @@ { "name": "tsv_wasm-json-no-locations", "group": "parse/typescript", - "mean_ns": 1083325293.2, - "p50_ns": 1083000851, - "p75_ns": 1083766522, - "p90_ns": 1084247724.4, - "p95_ns": 1084408125.2, - "p99_ns": 1084536445.84, - "min_ns": 1082577004, - "max_ns": 1084568526, - "std_dev_ns": 833625.2087291387, - "cv": 0.0007695059036854201, - "ops_per_second": 0.9230837738922645, + "mean_ns": 1098155893.4, + "p50_ns": 1098004307, + "p75_ns": 1098812393, + "p90_ns": 1099122653, + "p95_ns": 1099226073, + "p99_ns": 1099308809, + "min_ns": 1096818332, + "max_ns": 1099329493, + "std_dev_ns": 966517.5293957684, + "cv": 0.0008801277989806472, + "ops_per_second": 0.9106175234409573, "sample_size": 5, "files_processed": 2437, "files_total": 2437, @@ -779,18 +779,18 @@ { "name": "tsv-internal", "group": "parse/typescript", - "mean_ns": 138224012.6875, - "p50_ns": 138058653, - "p75_ns": 139442105, - "p90_ns": 142201952.4, - "p95_ns": 142499972.8, - "p99_ns": 142580364.8, - "min_ns": 136767544, - "max_ns": 142594970, - "std_dev_ns": 1304032.2080032504, - "cv": 0.009434194411295498, - "ops_per_second": 7.23463297408984, - "sample_size": 32, + "mean_ns": 137932086.30769232, + "p50_ns": 138073024.5, + "p75_ns": 140428980, + "p90_ns": 141767891.5, + "p95_ns": 142291971.75, + "p99_ns": 142733225.2, + "min_ns": 136940380, + "max_ns": 142926911, + "std_dev_ns": 546559.9950337947, + "cv": 0.003962529746809997, + "ops_per_second": 7.24994471387352, + "sample_size": 26, "files_processed": 2437, "files_total": 2437, "files_iterated": 2434, @@ -799,17 +799,17 @@ { "name": "tsv_wasm-internal", "group": "parse/typescript", - "mean_ns": 181461238.5909091, - "p50_ns": 181644058.5, - "p75_ns": 182662234.25, - "p90_ns": 186091143.5, - "p95_ns": 186646400.9, - "p99_ns": 187115987.78, - "min_ns": 180257801, - "max_ns": 187212563, - "std_dev_ns": 668051.0498416561, - "cv": 0.0036815082660585584, - "ops_per_second": 5.510818771905475, + "mean_ns": 183489849.5909091, + "p50_ns": 183663283.5, + "p75_ns": 184686170.25, + "p90_ns": 187722911.1, + "p95_ns": 187769910.1, + "p99_ns": 188076536.44, + "min_ns": 182091250, + "max_ns": 188185543, + "std_dev_ns": 725759.3611214367, + "cv": 0.003955310676527984, + "ops_per_second": 5.449892744636837, "sample_size": 22, "files_processed": 2437, "files_total": 2437, @@ -819,17 +819,17 @@ { "name": "oxc-parser", "group": "parse/typescript", - "mean_ns": 1305264464.6, - "p50_ns": 1303052331, - "p75_ns": 1315784799, - "p90_ns": 1317236095.2, - "p95_ns": 1317719860.6, - "p99_ns": 1318106872.92, - "min_ns": 1292579213, - "max_ns": 1318203626, - "std_dev_ns": 11371216.016430007, - "cv": 0.00871181000082978, - "ops_per_second": 0.7661282652833511, + "mean_ns": 1328575979, + "p50_ns": 1327625911, + "p75_ns": 1336923813, + "p90_ns": 1338162009.6, + "p95_ns": 1338574741.8, + "p99_ns": 1338904927.56, + "min_ns": 1318900753, + "max_ns": 1338987474, + "std_dev_ns": 9202726.679679045, + "cv": 0.006926759797814352, + "ops_per_second": 0.7526855940543842, "sample_size": 5, "files_processed": 2435, "files_total": 2437, @@ -839,17 +839,17 @@ { "name": "oxc-parser-wasm", "group": "parse/typescript", - "mean_ns": 1340864140.6, - "p50_ns": 1339482078, - "p75_ns": 1345894688, - "p90_ns": 1347854462, - "p95_ns": 1348507720, - "p99_ns": 1349030326.4, - "min_ns": 1334671239, - "max_ns": 1349160978, - "std_dev_ns": 6471019.78057924, - "cv": 0.004826007038776976, - "ops_per_second": 0.7457877123572918, + "mean_ns": 1358577531.4, + "p50_ns": 1357675431, + "p75_ns": 1365281550, + "p90_ns": 1365570397.8, + "p95_ns": 1365666680.4, + "p99_ns": 1365743706.48, + "min_ns": 1349320017, + "max_ns": 1365762963, + "std_dev_ns": 7017857.984748716, + "cv": 0.005165592557324929, + "ops_per_second": 0.736063991113934, "sample_size": 5, "files_processed": 2435, "files_total": 2437, @@ -859,18 +859,18 @@ { "name": "prettier", "group": "format/typescript", - "mean_ns": 13701470554.428572, - "p50_ns": 13688704131, - "p75_ns": 13737480943.5, - "p90_ns": 13794213096.6, - "p95_ns": 13807815805.8, - "p99_ns": 13818697973.16, - "min_ns": 13620412338, - "max_ns": 13821418515, - "std_dev_ns": 74004498.3558904, - "cv": 0.005401208436854302, - "ops_per_second": 0.07298486655337746, - "sample_size": 7, + "mean_ns": 13390193976.8, + "p50_ns": 13397850712, + "p75_ns": 13480628592.5, + "p90_ns": 13560690379.6, + "p95_ns": 13575781262.8, + "p99_ns": 13587853969.36, + "min_ns": 13360491961, + "max_ns": 13590872146, + "std_dev_ns": 21843031.171797708, + "cv": 0.0016312707052372197, + "ops_per_second": 0.07468151706634057, + "sample_size": 5, "files_processed": 2437, "files_total": 2437, "files_iterated": 2435, @@ -879,17 +879,17 @@ { "name": "tsv", "group": "format/typescript", - "mean_ns": 509124494.625, - "p50_ns": 509176305, - "p75_ns": 511313924.5, - "p90_ns": 518118615.6, - "p95_ns": 519801838.8, - "p99_ns": 521148417.36, - "min_ns": 507897695, - "max_ns": 521485062, - "std_dev_ns": 1272951.5968103353, - "cv": 0.002500275689442007, - "ops_per_second": 1.9641561357925994, + "mean_ns": 510281312, + "p50_ns": 510621353.5, + "p75_ns": 511585299, + "p90_ns": 518547738.5, + "p95_ns": 523173736.25, + "p99_ns": 526874534.45, + "min_ns": 509042507, + "max_ns": 527799734, + "std_dev_ns": 953832.181018533, + "cv": 0.0018692281268935299, + "ops_per_second": 1.9597033567241435, "sample_size": 8, "files_processed": 2437, "files_total": 2437, @@ -899,17 +899,17 @@ { "name": "tsv_wasm", "group": "format/typescript", - "mean_ns": 713786235.5, - "p50_ns": 713440359, - "p75_ns": 715419862.5, - "p90_ns": 723565222.2, - "p95_ns": 729417005.1, - "p99_ns": 734098431.42, - "min_ns": 712205702, - "max_ns": 735268788, - "std_dev_ns": 1350092.421347331, - "cv": 0.0018914520261119985, - "ops_per_second": 1.4009796634695684, + "mean_ns": 712429650, + "p50_ns": 712594376, + "p75_ns": 713355899.5, + "p90_ns": 721656199, + "p95_ns": 727815761.5, + "p99_ns": 732743411.5, + "min_ns": 710764653, + "max_ns": 733975324, + "std_dev_ns": 959542.0750962407, + "cv": 0.001346858704008516, + "ops_per_second": 1.4036473636379396, "sample_size": 6, "files_processed": 2437, "files_total": 2437, @@ -919,17 +919,17 @@ { "name": "oxfmt", "group": "format/typescript", - "mean_ns": 846371189.8333334, - "p50_ns": 846471155.5, - "p75_ns": 847846588, - "p90_ns": 849893762.5, - "p95_ns": 850845486.75, - "p99_ns": 851606866.15, - "min_ns": 842128092, - "max_ns": 851797211, - "std_dev_ns": 3489476.8747702804, - "cv": 0.004122868212772489, - "ops_per_second": 1.1815146971116999, + "mean_ns": 847114076.6666666, + "p50_ns": 847057173.5, + "p75_ns": 849430498, + "p90_ns": 850355305.5, + "p95_ns": 850425492.25, + "p99_ns": 850481641.65, + "min_ns": 842300354, + "max_ns": 850495679, + "std_dev_ns": 3054424.4941014773, + "cv": 0.003605682609029966, + "ops_per_second": 1.1804785536499742, "sample_size": 6, "files_processed": 2435, "files_total": 2437, @@ -939,17 +939,17 @@ { "name": "biome-wasm", "group": "format/typescript", - "mean_ns": 4543705777.666667, - "p50_ns": 4573988027, - "p75_ns": 6561237028, - "p90_ns": 9142297675, - "p95_ns": 10002651224, - "p99_ns": 10690934063.2, - "min_ns": 4509551914, - "max_ns": 10863004773, - "std_dev_ns": 32392054.778861225, - "cv": 0.007128994781765016, - "ops_per_second": 0.22008467293706038, + "mean_ns": 4640659870.333333, + "p50_ns": 4664197859, + "p75_ns": 6680537998, + "p90_ns": 9261928652.8, + "p95_ns": 10122392204.4, + "p99_ns": 10810763045.68, + "min_ns": 4598996897, + "max_ns": 10982855756, + "std_dev_ns": 36182560.209395595, + "cv": 0.0077968567445984025, + "ops_per_second": 0.21548659629049075, "sample_size": 3, "files_processed": 2437, "files_total": 2437, @@ -959,18 +959,18 @@ { "name": "svelte/compiler", "group": "parse/css", - "mean_ns": 9347109.578740157, - "p50_ns": 9293490, - "p75_ns": 9633911.5, - "p90_ns": 10107438.4, - "p95_ns": 10412161.9, - "p99_ns": 14669984.380000006, - "min_ns": 8743352, - "max_ns": 18666044, - "std_dev_ns": 408421.8437545641, - "cv": 0.04369498830777727, - "ops_per_second": 106.98494455168078, - "sample_size": 508, + "mean_ns": 9038889.063829787, + "p50_ns": 8961776.5, + "p75_ns": 9307395, + "p90_ns": 9753521.9, + "p95_ns": 10124050.150000002, + "p99_ns": 13612548.960000051, + "min_ns": 8653794, + "max_ns": 18954687, + "std_dev_ns": 348025.76061064505, + "cv": 0.03850315654423865, + "ops_per_second": 110.63306485324856, + "sample_size": 517, "files_processed": 49, "files_total": 49, "files_iterated": 49, @@ -979,18 +979,18 @@ { "name": "tsv-json", "group": "parse/css", - "mean_ns": 17351701.454545453, - "p50_ns": 17258450, - "p75_ns": 17805835.75, - "p90_ns": 18130577.5, - "p95_ns": 19443740, - "p99_ns": 20335802.999999996, - "min_ns": 16522292, - "max_ns": 20689750, - "std_dev_ns": 409714.6976459913, - "cv": 0.023612364396614394, - "ops_per_second": 57.63123591191341, - "sample_size": 264, + "mean_ns": 17398039.684410647, + "p50_ns": 17328426, + "p75_ns": 17832813, + "p90_ns": 17992721.2, + "p95_ns": 19576760.4, + "p99_ns": 20362145.840000004, + "min_ns": 16591514, + "max_ns": 20753913, + "std_dev_ns": 355601.88164198975, + "cv": 0.020439192466069817, + "ops_per_second": 57.47773991434453, + "sample_size": 263, "files_processed": 49, "files_total": 49, "files_iterated": 49, @@ -999,18 +999,18 @@ { "name": "tsv_wasm-json", "group": "parse/css", - "mean_ns": 18128549.38, - "p50_ns": 18050173, - "p75_ns": 18459952.5, - "p90_ns": 19304880.2, - "p95_ns": 19990566.349999998, - "p99_ns": 23776334.12000002, - "min_ns": 17674567, - "max_ns": 25381253, - "std_dev_ns": 409620.99314898025, - "cv": 0.022595354132465082, - "ops_per_second": 55.161611612633074, - "sample_size": 250, + "mean_ns": 18287059.184549358, + "p50_ns": 18176678, + "p75_ns": 18667889, + "p90_ns": 19460618.2, + "p95_ns": 20185583.2, + "p99_ns": 23133210.919999998, + "min_ns": 17916961, + "max_ns": 28337630, + "std_dev_ns": 319973.5214247198, + "cv": 0.017497265043854824, + "ops_per_second": 54.68347807639267, + "sample_size": 233, "files_processed": 49, "files_total": 49, "files_iterated": 49, @@ -1019,18 +1019,18 @@ { "name": "tsv-internal", "group": "parse/css", - "mean_ns": 3450014.9639780736, - "p50_ns": 3443839, - "p75_ns": 3484284, - "p90_ns": 3545613, - "p95_ns": 3571906, - "p99_ns": 3605643.77, - "min_ns": 3383350, - "max_ns": 3882445, - "std_dev_ns": 29379.53872333395, - "cv": 0.008515771389425391, - "ops_per_second": 289.85381525619243, - "sample_size": 1277, + "mean_ns": 3426007.1822466613, + "p50_ns": 3420016, + "p75_ns": 3464659.25, + "p90_ns": 3531872.4000000004, + "p95_ns": 3565861.45, + "p99_ns": 3719174.36, + "min_ns": 3366475, + "max_ns": 5318998, + "std_dev_ns": 30650.87400915242, + "cv": 0.008946529408339593, + "ops_per_second": 291.8849689463387, + "sample_size": 1273, "files_processed": 49, "files_total": 49, "files_iterated": 49, @@ -1039,18 +1039,18 @@ { "name": "tsv_wasm-internal", "group": "parse/css", - "mean_ns": 4877677.128735633, - "p50_ns": 4871848, - "p75_ns": 4926748, - "p90_ns": 4998469, - "p95_ns": 5036684, - "p99_ns": 5096582.8, - "min_ns": 4786991, - "max_ns": 5376435, - "std_dev_ns": 33056.1643080926, - "cv": 0.006777030015650351, - "ops_per_second": 205.01561985494007, - "sample_size": 870, + "mean_ns": 4903393.332503113, + "p50_ns": 4899160, + "p75_ns": 4955431.5, + "p90_ns": 5024022.6, + "p95_ns": 5053242.6, + "p99_ns": 5101561.9, + "min_ns": 4853645, + "max_ns": 5268624, + "std_dev_ns": 24113.319974338137, + "cv": 0.004917680132755866, + "ops_per_second": 203.9404004919006, + "sample_size": 803, "files_processed": 49, "files_total": 49, "files_iterated": 49, @@ -1059,17 +1059,17 @@ { "name": "prettier", "group": "format/css", - "mean_ns": 549768072.8, - "p50_ns": 548297856, - "p75_ns": 553199518.75, - "p90_ns": 562004047.5, - "p95_ns": 564494511.75, - "p99_ns": 566486883.15, - "min_ns": 532089189, - "max_ns": 566984976, - "std_dev_ns": 9665727.184464993, - "cv": 0.017581463280028062, - "ops_per_second": 1.8189488431129572, + "mean_ns": 551732011.6, + "p50_ns": 548811461, + "p75_ns": 561576720.25, + "p90_ns": 564489059.2, + "p95_ns": 565986579.1, + "p99_ns": 567184595.02, + "min_ns": 539045160, + "max_ns": 567484099, + "std_dev_ns": 10779738.139714208, + "cv": 0.019537996550994773, + "ops_per_second": 1.8124741341363197, "sample_size": 10, "files_processed": 49, "files_total": 49, @@ -1079,18 +1079,18 @@ { "name": "tsv", "group": "format/css", - "mean_ns": 6974933.896613191, - "p50_ns": 6969074.5, - "p75_ns": 7088710.75, - "p90_ns": 7235676.4, - "p95_ns": 7304980.55, - "p99_ns": 7450989.88, - "min_ns": 6912267, - "max_ns": 10349625, - "std_dev_ns": 45567.8693977457, - "cv": 0.006533089785965144, - "ops_per_second": 143.37053437675857, - "sample_size": 561, + "mean_ns": 7032221.678899082, + "p50_ns": 7009244, + "p75_ns": 7098315.5, + "p90_ns": 7206890.5, + "p95_ns": 7244467.45, + "p99_ns": 7291832.67, + "min_ns": 6934839, + "max_ns": 10835306, + "std_dev_ns": 72742.76588589282, + "cv": 0.010344208303922657, + "ops_per_second": 142.20257063292027, + "sample_size": 654, "files_processed": 49, "files_total": 49, "files_iterated": 49, @@ -1099,18 +1099,18 @@ { "name": "tsv_wasm", "group": "format/css", - "mean_ns": 10012727.79342723, - "p50_ns": 9986147, - "p75_ns": 10152856, - "p90_ns": 10294431.2, - "p95_ns": 10368159, - "p99_ns": 10559467.56, - "min_ns": 9890057, - "max_ns": 13671493, - "std_dev_ns": 93950.38210674978, - "cv": 0.009383095600423962, - "ops_per_second": 99.87288385652923, - "sample_size": 426, + "mean_ns": 10158745.69358178, + "p50_ns": 10110156, + "p75_ns": 10257106.5, + "p90_ns": 10362890, + "p95_ns": 10401973.5, + "p99_ns": 10501883.000000002, + "min_ns": 9975082, + "max_ns": 13912078, + "std_dev_ns": 120001.65250816409, + "cv": 0.011812644604735035, + "ops_per_second": 98.43734946842822, + "sample_size": 483, "files_processed": 49, "files_total": 49, "files_iterated": 49, @@ -1119,18 +1119,18 @@ { "name": "oxfmt", "group": "format/css", - "mean_ns": 18467102.220149253, - "p50_ns": 18446410, - "p75_ns": 18882962, - "p90_ns": 19383110, - "p95_ns": 19690833, - "p99_ns": 20404420.500000004, - "min_ns": 16524016, - "max_ns": 22189701, - "std_dev_ns": 659446.4754952398, - "cv": 0.035709255715047974, - "ops_per_second": 54.150347362506665, - "sample_size": 268, + "mean_ns": 18091033.845588237, + "p50_ns": 18067378, + "p75_ns": 18433522.5, + "p90_ns": 18979253.5, + "p95_ns": 19192316.5, + "p99_ns": 20099620.25, + "min_ns": 16502367, + "max_ns": 20904626, + "std_dev_ns": 587884.7092626577, + "cv": 0.03249591561656505, + "ops_per_second": 55.27600072694931, + "sample_size": 272, "files_processed": 49, "files_total": 49, "files_iterated": 49, @@ -1139,17 +1139,17 @@ { "name": "biome-wasm", "group": "format/css", - "mean_ns": 125914966.1923077, - "p50_ns": 126099421, - "p75_ns": 137886415.75, - "p90_ns": 194021788, - "p95_ns": 197866488.25, - "p99_ns": 207447585.65, - "min_ns": 123912984, - "max_ns": 208555623, - "std_dev_ns": 2061309.3913787133, - "cv": 0.016370646426815634, - "ops_per_second": 7.941867676577204, + "mean_ns": 126426328.38461539, + "p50_ns": 126839392, + "p75_ns": 138513503.5, + "p90_ns": 193632761, + "p95_ns": 202020801.25, + "p99_ns": 208481402.25, + "min_ns": 124102387, + "max_ns": 209127749, + "std_dev_ns": 1965652.0770388045, + "cv": 0.0155478063956653, + "ops_per_second": 7.9097448512290125, "sample_size": 26, "files_processed": 49, "files_total": 49, diff --git a/src/routes/docs/benchmarks/benchmarks_conformance.json b/src/routes/docs/benchmarks/benchmarks_conformance.json index 2f7c107..f95e3ca 100644 --- a/src/routes/docs/benchmarks/benchmarks_conformance.json +++ b/src/routes/docs/benchmarks/benchmarks_conformance.json @@ -2,8 +2,8 @@ "version": 7, "runtime": "node", "corpus_kind": "conformance", - "timestamp": "2026-07-16T00:24:26.030Z", - "git_commit": "eca5466f", + "timestamp": "2026-07-16T11:52:16.141Z", + "git_commit": "135b7b93", "machine": { "cpu_model": "AMD Ryzen 5 PRO 7530U with Radeon Graphics", "os": "linux", @@ -175,9 +175,9 @@ }, { "label": "tsv_format_wasm", - "bytes": 2261296, + "bytes": 2261397, "kind": "wasm", - "gzip_bytes": 794602 + "gzip_bytes": 794650 }, { "label": "tsv_parse_wasm", @@ -187,9 +187,9 @@ }, { "label": "tsv_wasm", - "bytes": 2491362, + "bytes": 2491464, "kind": "wasm", - "gzip_bytes": 875347 + "gzip_bytes": 875399 }, { "label": "biome (wasm)", diff --git a/src/routes/docs/benchmarks/benchmarks_cross_runtime.json b/src/routes/docs/benchmarks/benchmarks_cross_runtime.json index c400307..ca995eb 100644 --- a/src/routes/docs/benchmarks/benchmarks_cross_runtime.json +++ b/src/routes/docs/benchmarks/benchmarks_cross_runtime.json @@ -1,7 +1,7 @@ { "version": 7, "kind": "combined", - "generated": "2026-07-16T00:23:32.612Z", + "generated": "2026-07-16T11:51:31.514Z", "runtimes": [ "deno", "node", @@ -12,8 +12,8 @@ "sources": [ { "runtime": "deno", - "timestamp": "2026-07-16T00:07:00.449Z", - "git_commit": "eca5466f", + "timestamp": "2026-07-16T11:34:23.572Z", + "git_commit": "135b7b93", "tsv": "0.1.0", "machine": { "cpu_model": "AMD Ryzen 5 PRO 7530U with Radeon Graphics", @@ -24,8 +24,8 @@ }, { "runtime": "node", - "timestamp": "2026-07-16T00:15:41.741Z", - "git_commit": "eca5466f", + "timestamp": "2026-07-16T11:43:29.034Z", + "git_commit": "135b7b93", "tsv": "0.1.0", "machine": { "cpu_model": "AMD Ryzen 5 PRO 7530U with Radeon Graphics", @@ -36,8 +36,8 @@ }, { "runtime": "bun", - "timestamp": "2026-07-16T00:23:32.242Z", - "git_commit": "eca5466f", + "timestamp": "2026-07-16T11:51:31.124Z", + "git_commit": "135b7b93", "tsv": "0.1.0", "machine": { "cpu_model": "AMD Ryzen 5 PRO 7530U with Radeon Graphics", @@ -52,14 +52,14 @@ "group": "parse/svelte", "name": "svelte/compiler", "ops_per_second": { - "deno": 2.285628509935161, - "node": 2.235438061592186, - "bun": 1.3578408241683035 + "deno": 2.32203309333886, + "node": 2.201657407828713, + "bun": 1.3515266516636215 }, "mean_ns": { - "deno": 437516418.6363636, - "node": 447339614.1818182, - "bun": 736463348.4285715 + "deno": 430657083.6, + "node": 454203272.7, + "bun": 739904018 }, "files_iterated": { "deno": 763, @@ -71,14 +71,14 @@ "group": "parse/svelte", "name": "tsv-json", "ops_per_second": { - "deno": 4.978937108439607, - "node": 4.647455353441698, - "bun": 6.023643379700957 + "deno": 5.0827943917957965, + "node": 4.649398944179739, + "bun": 6.007332747236763 }, "mean_ns": { - "deno": 200846079.84, - "node": 215171513, - "bun": 166012483.96774194 + "deno": 196742170.33333334, + "node": 215081564.7368421, + "bun": 166463227.87096775 }, "files_iterated": { "deno": 763, @@ -90,14 +90,14 @@ "group": "parse/svelte", "name": "tsv-json-no-locations", "ops_per_second": { - "deno": 7.772867582254782, - "node": 7.346194913995057, - "bun": 8.461785290730548 + "deno": 7.922378990905888, + "node": 7.328403381719038, + "bun": 8.520169721099231 }, "mean_ns": { - "deno": 128652648.38461539, - "node": 136124893.45945945, - "bun": 118178370.83333333 + "deno": 126224711.18181819, + "node": 136455370.6875, + "bun": 117368554 }, "files_iterated": { "deno": 763, @@ -109,14 +109,14 @@ "group": "parse/svelte", "name": "tsv_wasm-json", "ops_per_second": { - "deno": 4.101050687272255, - "node": 4.1820297537449, - "bun": 5.5683396984514 + "deno": 4.161210076022163, + "node": 4.125738456275007, + "bun": 5.562851328976341 }, "mean_ns": { - "deno": 243839951.33333334, - "node": 239118337, - "bun": 179586744.73076922 + "deno": 240314711.76190478, + "node": 242380851.47619048, + "bun": 179763926.96153846 }, "files_iterated": { "deno": 763, @@ -128,14 +128,14 @@ "group": "parse/svelte", "name": "tsv_wasm-json-no-locations", "ops_per_second": { - "deno": 6.229954607080464, - "node": 6.404659921874018, - "bun": 7.5936032930944695 + "deno": 6.299825463509322, + "node": 6.377630789601431, + "bun": 7.655585761307142 }, "mean_ns": { - "deno": 160514813.2, - "node": 156136315.15151516, - "bun": 131689786.96969697 + "deno": 158734556.3448276, + "node": 156798038.8, + "bun": 130623577.5 }, "files_iterated": { "deno": 763, @@ -147,14 +147,14 @@ "group": "parse/svelte", "name": "tsv-internal", "ops_per_second": { - "deno": 46.18841596375166, - "node": 47.37566678684821, - "bun": 50.64074253836932 + "deno": 47.04746259219493, + "node": 47.86874286762142, + "bun": 51.06942307255545 }, "mean_ns": { - "deno": 21650450.207792208, - "node": 21107882.333333332, - "bun": 19746945.836 + "deno": 21255131.412037037, + "node": 20890458.785714287, + "bun": 19581188.504504506 }, "files_iterated": { "deno": 763, @@ -166,14 +166,14 @@ "group": "parse/svelte", "name": "tsv_wasm-internal", "ops_per_second": { - "deno": 30.239710009615436, - "node": 27.08091961777122, - "bun": 16.13930130591613 + "deno": 30.474656127239356, + "node": 26.773814422344802, + "bun": 15.85067482488642 }, "mean_ns": { - "deno": 33069100.18918919, - "node": 36926367.86764706, - "bun": 61960550.89655172 + "deno": 32814152.055555556, + "node": 37349926.47014926, + "bun": 63088796.6 }, "files_iterated": { "deno": 763, @@ -185,14 +185,14 @@ "group": "format/svelte", "name": "prettier", "ops_per_second": { - "deno": 0.2339152576842328, - "node": 0.22364412431315459, - "bun": 0.2679431102133465 + "deno": 0.237793092279713, + "node": 0.2267144665492906, + "bun": 0.2524397368523206 }, "mean_ns": { - "deno": 4275052469.428571, - "node": 4471389548.333333, - "bun": 3732135523.857143 + "deno": 4205336624.428571, + "node": 4410834541, + "bun": 3961341476.857143 }, "files_iterated": { "deno": 763, @@ -204,14 +204,14 @@ "group": "format/svelte", "name": "tsv", "ops_per_second": { - "deno": 14.132622722181472, - "node": 14.570934896225333, - "bun": 13.969251979432833 + "deno": 14.136745274233984, + "node": 14.35076558858908, + "bun": 14.12111063381393 }, "mean_ns": { - "deno": 70758274.64285715, - "node": 68629776.13461539, - "bun": 71585794.39130434 + "deno": 70737640.14285715, + "node": 69682693.5, + "bun": 70815959.58928572 }, "files_iterated": { "deno": 763, @@ -223,14 +223,14 @@ "group": "format/svelte", "name": "tsv_wasm", "ops_per_second": { - "deno": 9.041275686610229, - "node": 7.972084634344246, - "bun": 7.240242113046595 + "deno": 9.056948494404766, + "node": 7.928477824721544, + "bun": 7.193862254275549 }, "mean_ns": { - "deno": 110603861.07692307, - "node": 125437704.925, - "bun": 138116928.1891892 + "deno": 110412464.04545455, + "node": 126127615.175, + "bun": 139007387.7777778 }, "files_iterated": { "deno": 763, @@ -242,14 +242,14 @@ "group": "format/svelte", "name": "oxfmt", "ops_per_second": { - "deno": 0.2386665456843671, - "node": 0.2288634551342232, - "bun": 0.1987945582704412 + "deno": 0.23968786103725603, + "node": 0.22993605936582995, + "bun": 0.1902163231156394 }, "mean_ns": { - "deno": 4189946258, - "node": 4369417561.285714, - "bun": 5030318780.857142 + "deno": 4172092803, + "node": 4349035130.714286, + "bun": 5257172379.428572 }, "files_iterated": { "deno": 763, @@ -261,12 +261,12 @@ "group": "format/svelte", "name": "biome-wasm", "ops_per_second": { - "deno": 1.4335186890951448, - "node": 1.0879748354379855 + "deno": 1.4318975821011795, + "node": 1.0837474344623093 }, "mean_ns": { - "deno": 697584208.4285715, - "node": 919138906 + "deno": 698373970.6666666, + "node": 922724214.3333334 }, "files_iterated": { "deno": 763, @@ -277,14 +277,14 @@ "group": "parse/typescript", "name": "acorn-typescript", "ops_per_second": { - "deno": 0.35329029052074107, - "node": 0.3196778195072388, - "bun": 0.1495967948405602 + "deno": 0.35227894489602546, + "node": 0.3230721733354392, + "bun": 0.1519515615378463 }, "mean_ns": { - "deno": 2830533492.8, - "node": 3128149464.8, - "bun": 6684635196 + "deno": 2838659575, + "node": 3095283600.8, + "bun": 6581044576.833333 }, "files_iterated": { "deno": 2434, @@ -296,14 +296,14 @@ "group": "parse/typescript", "name": "tsv-json", "ops_per_second": { - "deno": 0.5483532036994702, - "node": 0.49680536982576506, - "bun": 0.7396523440970465 + "deno": 0.5528114711248244, + "node": 0.4864556603500567, + "bun": 0.7400072723918691 }, "mean_ns": { - "deno": 1823642122, - "node": 2012860691, - "bun": 1351986521.75 + "deno": 1808934966.5, + "node": 2055685813.75, + "bun": 1351338071 }, "files_iterated": { "deno": 2434, @@ -315,14 +315,14 @@ "group": "parse/typescript", "name": "tsv-json-no-locations", "ops_per_second": { - "deno": 1.1413193328402957, - "node": 1.0086262314650507, - "bun": 1.2917892945450717 + "deno": 1.145465982082649, + "node": 1.0017326620919327, + "bun": 1.283661154144797 }, "mean_ns": { - "deno": 876178972.2, - "node": 991447544, - "bun": 774120055.2 + "deno": 873007156.6, + "node": 998270334.8333334, + "bun": 779021782.1666666 }, "files_iterated": { "deno": 2434, @@ -334,14 +334,14 @@ "group": "parse/typescript", "name": "tsv_wasm-json", "ops_per_second": { - "deno": 0.47600201582902885, - "node": 0.46773723211893914, - "bun": 0.6844249374667883 + "deno": 0.47385486766100227, + "node": 0.4565405972186589, + "bun": 0.6842257166812827 }, "mean_ns": { - "deno": 2100831439.25, - "node": 2137952532.6, - "bun": 1461080602.5 + "deno": 2110350802, + "node": 2190385709.6, + "bun": 1461506014.2 }, "files_iterated": { "deno": 2434, @@ -353,14 +353,14 @@ "group": "parse/typescript", "name": "tsv_wasm-json-no-locations", "ops_per_second": { - "deno": 0.9340477377279914, - "node": 0.9230837738922645, - "bun": 1.1738954315046863 + "deno": 0.9401759352694344, + "node": 0.9106175234409573, + "bun": 1.1666136412897596 }, "mean_ns": { - "deno": 1070609091.6, - "node": 1083325293.2, - "bun": 851864632.2 + "deno": 1063630712.6, + "node": 1098155893.4, + "bun": 857181816.3333334 }, "files_iterated": { "deno": 2434, @@ -372,14 +372,14 @@ "group": "parse/typescript", "name": "tsv-internal", "ops_per_second": { - "deno": 7.5837117839562564, - "node": 7.23463297408984, - "bun": 8.334939591955754 + "deno": 7.593919350391545, + "node": 7.24994471387352, + "bun": 8.29899627514646 }, "mean_ns": { - "deno": 131861551.2413793, - "node": 138224012.6875, - "bun": 119976874.33333333 + "deno": 131684306.06896552, + "node": 137932086.30769232, + "bun": 120496499.4375 }, "files_iterated": { "deno": 2434, @@ -391,14 +391,14 @@ "group": "parse/typescript", "name": "tsv_wasm-internal", "ops_per_second": { - "deno": 4.817702444462784, - "node": 5.510818771905475, - "bun": 5.757212881588537 + "deno": 4.844409174820336, + "node": 5.449892744636837, + "bun": 5.698779253363164 }, "mean_ns": { - "deno": 207567821.2857143, - "node": 181461238.5909091, - "bun": 173695157.80769232 + "deno": 206423521.2, + "node": 183489849.5909091, + "bun": 175476177.5357143 }, "files_iterated": { "deno": 2434, @@ -410,14 +410,14 @@ "group": "parse/typescript", "name": "oxc-parser", "ops_per_second": { - "deno": 0.8622608285121847, - "node": 0.7661282652833511, - "bun": 1.045945698068123 + "deno": 0.8624090264812094, + "node": 0.7526855940543842, + "bun": 1.047915908090529 }, "mean_ns": { - "deno": 1159741886.6, - "node": 1305264464.6, - "bun": 956072578 + "deno": 1159542594.4, + "node": 1328575979, + "bun": 954275044.6666666 }, "files_iterated": { "deno": 2434, @@ -429,12 +429,12 @@ "group": "parse/typescript", "name": "oxc-parser-wasm", "ops_per_second": { - "deno": 0.7643562384275462, - "node": 0.7457877123572918 + "deno": 0.768719704502768, + "node": 0.736063991113934 }, "mean_ns": { - "deno": 1308290493, - "node": 1340864140.6 + "deno": 1300864273.6, + "node": 1358577531.4 }, "files_iterated": { "deno": 2434, @@ -445,14 +445,14 @@ "group": "format/typescript", "name": "prettier", "ops_per_second": { - "deno": 0.08168339424657242, - "node": 0.07298486655337746, - "bun": 0.06656272354486883 + "deno": 0.08265464739794595, + "node": 0.07468151706634057, + "bun": 0.0626242936249232 }, "mean_ns": { - "deno": 12242390380.857143, - "node": 13701470554.428572, - "bun": 15023423723.428572 + "deno": 12098533252.285715, + "node": 13390193976.8, + "bun": 15968243985.142857 }, "files_iterated": { "deno": 2435, @@ -464,14 +464,14 @@ "group": "format/typescript", "name": "tsv", "ops_per_second": { - "deno": 1.9961240062496248, - "node": 1.9641561357925994, - "bun": 1.9294423038823494 + "deno": 1.9912721494847867, + "node": 1.9597033567241435, + "bun": 1.9399248269817906 }, "mean_ns": { - "deno": 500970880, - "node": 509124494.625, - "bun": 518284479.4 + "deno": 502191526.28571427, + "node": 510281312, + "bun": 515483892 }, "files_iterated": { "deno": 2435, @@ -483,14 +483,14 @@ "group": "format/typescript", "name": "tsv_wasm", "ops_per_second": { - "deno": 1.2700370044501141, - "node": 1.4009796634695684, - "bun": 1.444034749537169 + "deno": 1.2720122080964626, + "node": 1.4036473636379396, + "bun": 1.4393877539677782 }, "mean_ns": { - "deno": 787378632.6666666, - "node": 713786235.5, - "bun": 692504110.6666666 + "deno": 786155976.8333334, + "node": 712429650, + "bun": 694739827.5714285 }, "files_iterated": { "deno": 2435, @@ -502,14 +502,14 @@ "group": "format/typescript", "name": "oxfmt", "ops_per_second": { - "deno": 1.1975316138276806, - "node": 1.1815146971116999, - "bun": 0.9861111200984184 + "deno": 1.2039315321874253, + "node": 1.1804785536499742, + "bun": 0.9945970863022248 }, "mean_ns": { - "deno": 835051023.6666666, - "node": 846371189.8333334, - "bun": 1014084497.8 + "deno": 830612018.4285715, + "node": 847114076.6666666, + "bun": 1005432263.75 }, "files_iterated": { "deno": 2435, @@ -521,12 +521,12 @@ "group": "format/typescript", "name": "biome-wasm", "ops_per_second": { - "deno": 0.24188581102985876, - "node": 0.22008467293706038 + "deno": 0.24400636365570735, + "node": 0.21548659629049075 }, "mean_ns": { - "deno": 4134182140.5, - "node": 4543705777.666667 + "deno": 4098253771, + "node": 4640659870.333333 }, "files_iterated": { "deno": 2435, @@ -537,14 +537,14 @@ "group": "parse/css", "name": "svelte/compiler", "ops_per_second": { - "deno": 98.93298769631505, - "node": 106.98494455168078, - "bun": 68.90093378590163 + "deno": 99.27831750991159, + "node": 110.63306485324856, + "bun": 68.18371992928869 }, "mean_ns": { - "deno": 10107852.024742268, - "node": 9347109.578740157, - "bun": 14513591.399317406 + "deno": 10072692.860655738, + "node": 9038889.063829787, + "bun": 14666257.591065291 }, "files_iterated": { "deno": 49, @@ -556,14 +556,14 @@ "group": "parse/css", "name": "tsv-json", "ops_per_second": { - "deno": 66.34546835074023, - "node": 57.63123591191341, - "bun": 73.53134124860561 + "deno": 66.5873934340344, + "node": 57.47773991434453, + "bun": 73.63477107334026 }, "mean_ns": { - "deno": 15072619.5, - "node": 17351701.454545453, - "bun": 13599643.132022472 + "deno": 15017857.71192053, + "node": 17398039.684410647, + "bun": 13580540.625352113 }, "files_iterated": { "deno": 49, @@ -575,14 +575,14 @@ "group": "parse/css", "name": "tsv_wasm-json", "ops_per_second": { - "deno": 51.91490176297957, - "node": 55.161611612633074, - "bun": 68.54996875475906 + "deno": 52.32935697865012, + "node": 54.68347807639267, + "bun": 68.46106080515385 }, "mean_ns": { - "deno": 19262292.05952381, - "node": 18128549.38, - "bun": 14587898.69879518 + "deno": 19109732.237068966, + "node": 18287059.184549358, + "bun": 14606843.48502994 }, "files_iterated": { "deno": 49, @@ -594,14 +594,14 @@ "group": "parse/css", "name": "tsv-internal", "ops_per_second": { - "deno": 302.219358954193, - "node": 289.85381525619243, - "bun": 327.6279956934774 + "deno": 304.7757571691321, + "node": 291.8849689463387, + "bun": 325.19575279279934 }, "mean_ns": { - "deno": 3308854.8776637726, - "node": 3450014.9639780736, - "bun": 3052242.2172236503 + "deno": 3281100.8634294383, + "node": 3426007.1822466613, + "bun": 3075070.9116338207 }, "files_iterated": { "deno": 49, @@ -613,14 +613,14 @@ "group": "parse/css", "name": "tsv_wasm-internal", "ops_per_second": { - "deno": 181.94047334155198, - "node": 205.01561985494007, - "bun": 218.85532690450955 + "deno": 184.7561962029366, + "node": 203.9404004919006, + "bun": 217.84005813175878 }, "mean_ns": { - "deno": 5496303.1679198, - "node": 4877677.128735633, - "bun": 4569228.513392857 + "deno": 5412538.364351245, + "node": 4903393.332503113, + "bun": 4590523.93107221 }, "files_iterated": { "deno": 49, @@ -632,14 +632,14 @@ "group": "format/css", "name": "prettier", "ops_per_second": { - "deno": 1.9553847496366528, - "node": 1.8189488431129572, - "bun": 2.1579001199965315 + "deno": 1.9335173437011668, + "node": 1.8124741341363197, + "bun": 1.912133053851122 }, "mean_ns": { - "deno": 511408304.7777778, - "node": 549768072.8, - "bun": 463413478.1 + "deno": 517192154.1111111, + "node": 551732011.6, + "bun": 522976159 }, "files_iterated": { "deno": 49, @@ -651,14 +651,14 @@ "group": "format/css", "name": "tsv", "ops_per_second": { - "deno": 148.55186580257475, - "node": 143.37053437675857, - "bun": 147.4505147240052 + "deno": 148.60107416363323, + "node": 142.20257063292027, + "bun": 147.4625555531239 }, "mean_ns": { - "deno": 6731655.604575164, - "node": 6974933.896613191, - "bun": 6781936.311797753 + "deno": 6729426.456896552, + "node": 7032221.678899082, + "bun": 6781382.543175488 }, "files_iterated": { "deno": 49, @@ -670,14 +670,14 @@ "group": "format/css", "name": "tsv_wasm", "ops_per_second": { - "deno": 87.91100033975918, - "node": 99.87288385652923, - "bun": 101.73318795414885 + "deno": 88.44974187950501, + "node": 98.43734946842822, + "bun": 101.39867650427693 }, "mean_ns": { - "deno": 11375140.723404255, - "node": 10012727.79342723, - "bun": 9829633.968127491 + "deno": 11305855.492063493, + "node": 10158745.69358178, + "bun": 9862061.660714285 }, "files_iterated": { "deno": 49, @@ -689,14 +689,14 @@ "group": "format/css", "name": "oxfmt", "ops_per_second": { - "deno": 55.35609448255786, - "node": 54.150347362506665, - "bun": 45.66585793057103 + "deno": 56.355769067169135, + "node": 55.27600072694931, + "bun": 47.442921582011735 }, "mean_ns": { - "deno": 18064858.24817518, - "node": 18467102.220149253, - "bun": 21898198.026200872 + "deno": 17744412.26785714, + "node": 18091033.845588237, + "bun": 21077959.92857143 }, "files_iterated": { "deno": 49, @@ -708,12 +708,12 @@ "group": "format/css", "name": "biome-wasm", "ops_per_second": { - "deno": 10.303043141246484, - "node": 7.941867676577204 + "deno": 10.267159807066765, + "node": 7.9097448512290125 }, "mean_ns": { - "deno": 97058702.58823529, - "node": 125914966.1923077 + "deno": 97397919.07317074, + "node": 126426328.38461539 }, "files_iterated": { "deno": 49, From c7e46f7d64f3c66bdc223a96b80be71edbcb84b7 Mon Sep 17 00:00:00 2001 From: Ryan Atkinson Date: Thu, 16 Jul 2026 09:39:00 -0400 Subject: [PATCH 049/218] update docs and add other benchmarks --- CLAUDE.md | 2 +- src/routes/docs/benchmarks/+page.svelte | 181 +++++++++++++----- .../docs/benchmarks/BenchmarksCli.svelte | 113 +++++++++++ .../docs/benchmarks/BenchmarksSummary.svelte | 6 +- src/routes/docs/benchmarks/benchmarks_cli.ts | 84 ++++++++ src/routes/docs/introduction/+page.svelte | 14 +- src/test/benchmark_data.test.ts | 30 +++ 7 files changed, 367 insertions(+), 63 deletions(-) create mode 100644 src/routes/docs/benchmarks/BenchmarksCli.svelte create mode 100644 src/routes/docs/benchmarks/benchmarks_cli.ts diff --git a/CLAUDE.md b/CLAUDE.md index b335632..e1005e9 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -23,7 +23,7 @@ IMPORTANT for AI agents: Do NOT run `gro dev` - the developer will manage the de - Svelte 5 - component framework with runes - SvelteKit - application framework with static adapter -- fuz_css (`@fuzdev/fuz_css`) - CSS framework and design system +- fuz_css (`@fuzdev/fuz_css`) - semantic-first CSS framework and design system - fuz_ui (`@fuzdev/fuz_ui`) - UI components, theming, docs system - fuz_util (`@fuzdev/fuz_util`) - utility functions - fuz_code (`@fuzdev/fuz_code`) - syntax highlighting diff --git a/src/routes/docs/benchmarks/+page.svelte b/src/routes/docs/benchmarks/+page.svelte index c53feb5..2cefe33 100644 --- a/src/routes/docs/benchmarks/+page.svelte +++ b/src/routes/docs/benchmarks/+page.svelte @@ -7,6 +7,7 @@ import {benchmarks_json} from './benchmarks.ts'; import {benchmarks_conformance_json} from './benchmarks_conformance.ts'; import {benchmarks_cross_runtime_json} from './benchmarks_cross_runtime.ts'; + import {benchmarks_cli} from './benchmarks_cli.ts'; import { derive_benchmark_groups, derive_conformance_groups, @@ -20,6 +21,7 @@ import BenchmarksSizes from './BenchmarksSizes.svelte'; import BenchmarksMeta from './BenchmarksMeta.svelte'; import BenchmarksCrossRuntime from './BenchmarksCrossRuntime.svelte'; + import BenchmarksCli from './BenchmarksCli.svelte'; const LIBRARY_ITEM_NAME = 'benchmarks'; @@ -41,15 +43,49 @@

    tsv is a toolchain for TypeScript/JS, CSS, and Svelte in Rust. This page shows how it measures - up compared to Oxc and Biome, which are similar tools with wider language support (tsv doesn't - support JSX/SCSS/etc). + up against Prettier, which tsv closely follows, and against Oxc and Biome, similar tools with + wider language support (tsv doesn't support JSX/TSX, JSON, etc).

    +
    + + +

    - After correctness, performance is tsv's priority. For TypeScript its parser is 1.3x Oxc's - speed and formatting is 1.7x. Each section has notes that attempt to fairly contextualize the - numbers. + After correctness, performance is tsv's priority. The numbers on this page are + single-threaded and in-process — each tool parses or formats one file at a + time, isolating engine speed from multi-core parallelism — measured over a large collection of + real-world repos: {corpus_file_count.toLocaleString('en-US')} files including Svelte's + official repos (svelte, kit, svelte.dev) and the Fuz stack repos. On that basis:

    - +
      +
    • + Formatting TypeScript, tsv is ~1.7x faster than Oxfmt (native-vs-native), + ~26x faster than Prettier (native Rust vs Prettier's JS), and ~6.5x faster than Biome + (wasm-vs-wasm). +
    • +
    • + Formatting CSS, it's ~2.6x faster than Oxfmt; Svelte is ~63x faster than Prettier (which + Oxfmt's Svelte path delegates to internally). +
    • +
    • + Parsing TypeScript, tsv is ~1.3x faster than Oxc payload-matched — the + span-only AST both emit. tsv's default AST adds a per-node line/column loc that + Oxc omits: a richer drop-in deliverable that's correspondingly slower to build, so on the + full AST it's slower, not faster. +
    • +
    • + An independent end-to-end CLI benchmark + — a fork of Oxc's official bench-formatter that adds tsv — corroborates this at + whole-command scale: on a real TypeScript repo, tsv formats ~3x faster than Oxfmt and ~6.5x + faster than Biome using 3–10x less memory. Wall-clock ratios include each tool's multi-file + parallelism, so they scale with core count and are machine-dependent. +
    • +
    +

    Each section below has notes that fairly contextualize its numbers.

    +
    @@ -62,9 +98,8 @@ tsv's formatter is similar to Oxfmt - and Biome. Today it can format Svelte, - TypeScript, and CSS, plus JS (as strict-mode TypeScript) and soon JSON and HTML (without the - Svelte differences): + and Biome. It formats Svelte, TypeScript, and + CSS, plus JS (as strict-mode TypeScript):

    {#each format_groups as group (group.language)} @@ -77,12 +112,11 @@ delegates to Prettier internally (via prettier-plugin-svelte).
  • - Speed is shown relative to prettier (the 1.0x anchor) — the canonical - reference every format entry is measured against, the same baseline the parse groups and - the summary above anchor on, so every section reads consistently. Prettier runs in JS - while the headline tsv entry is native, so the headline ratio is a cross-tier comparison; - for an engine-vs-engine read, compare within a runtime tier: wasm vs wasm, or native vs - native. + Speed is shown relative to prettier (the 1.0x anchor), the canonical format + reference — the same convention as the parse groups, which anchor on their canonical + parser, so every section reads consistently. Prettier runs in JS while the headline tsv + entry is native, so that ratio is cross-tier; for an engine-vs-engine read, compare within + a tier: wasm vs wasm, or native vs native.
  • There's no native Biome entry: its native engine ships only as the biome CLI @@ -141,7 +175,7 @@
  • tsv internal (node napi) and tsv_wasm internal aren't a fair - comparison to the other entries - they skip JS-side AST materialization entirely, so + comparison to the other entries — they skip JS-side AST materialization entirely, so they're included only to show tsv's own JSON-serialization overhead against its non-internal entry.
  • @@ -153,33 +187,32 @@

    Separate from the speed numbers above, this measures parse coverage: how much of a - much larger, deliberately hard corpus each parser accepts - Prettier's format-test suites, + much larger, deliberately hard corpus each parser accepts — Prettier's format-test suites, Svelte's compiler test suite, CSS extracted from web-platform-tests, and test262's expected-valid strict-mode tests. It's a separate corpus from the real-world code timed - above, which is held to a stricter bar - every tool must fully process every file it supports, - or the benchmark fails - so coverage there is 100% by construction and the discriminating - signal is here, on the hard cases. + >'s expected-valid strict-mode tests. The real-world code timed above is held to a stricter + bar — every tool must fully process every file it supports or the benchmark fails — so + coverage there is 100% by construction; the discriminating signal is here, on the hard cases.

    + + +

    + The numbers above measure tsv's engine in-process, one file at a time. This is a separate, + independent benchmark: a fork of Oxc's official + bench-formatter + that + adds tsv, timing the whole CLI end-to-end — process spawn, file discovery, I/O, and + each tool's default multi-file parallelism — plus peak memory. It's the "what you experience + typing the command" measure, run on real repositories. tsv appears in the two JSX-free + scenarios (it has no JSX/TSX parser). +

    + + +
    +

    All numbers are single-threaded: every library formats or parses one file at a time, measured sequentially with no cross-file parallelism. Each row is the total time to process the whole - corpus once on a single core - not the multi-core batch throughput a CLI gets when it formats + corpus once on a single core — not the multi-core batch throughput a CLI gets when it formats many files at once, which most of these tools (tsv included) can do.

    What's measured: {corpus_file_count.toLocaleString('en-US')} files of .svelte, - .ts/.js, and .css - real-world code only, from two + .ts/.js, and .css — real-world code only, from two sources: the author's libraries, apps, and sites (the fuz.dev ecosystem plus personal SvelteKit sites), and upstream framework source (Svelte, SvelteKit, and the svelte.dev site). The CSS set also includes real-authored CSS extracted from those components' - <style> blocks, concatenated per repo - standalone CSS files are rare in + <style> blocks, concatenated per repo — standalone CSS files are rare in this ecosystem, and the same bytes appear in the Svelte rows (rows are never summed). Test files count as real code and stay in; fixture files (the formatter test suites that used to be - part of this corpus, and fixture subtrees inside the measured repos) are excluded - + part of this corpus, and fixture subtrees inside the measured repos) are excluded — deliberately tricky edge cases measure conformance, not typical throughput, and are covered by the parse-conformance section above.

    @@ -280,17 +357,17 @@

    - The same benchmark harness runs under three JS runtimes - Node, Deno, and Bun. The headline + The same benchmark harness runs under three JS runtimes — Node, Deno, and Bun. The headline numbers above are the Node run. The native entry differs by runtime: Node and Bun load tsv's N-API addon, while Deno loads its C-FFI library. They share code but cross a different binding - boundary, so a per-runtime delta on the same row is a runtime effect - the JS engine or the - binding boundary - not a difference in tsv's own engine, which is identical across all three. + boundary, so a per-runtime delta on the same row is a runtime effect — the JS engine or the + binding boundary — not a difference in tsv's own engine, which is identical across all three.

    @@ -402,11 +383,7 @@ TypeScript corpus. The tsv-json-no-locations / tsv-wasm-json-no-locations entries (no-locs in the charts) drop it for a span-only wire of oxc's kind, so they are the payload-matched comparison with - oxc-parser, though the shapes still differ in detail. Line/column stays derivable from the - offsets plus source (see the notes below). No row splits the Rust side from the hand-off; - tsv's harness docs record, unpublished, the two whole Rust sides at about parity and tsv's - loc-stripped wire as the smaller — which would leave most of tsv's margin to the - lighter wire, which JSON.parses faster. The tsv-internal and tsv-wasm-internal + oxc-parser, though the shapes still differ in detail. The tsv-internal and tsv-wasm-internal entries build tsv's in-Rust AST and stop — no serialization, nothing materialized in JS — so they show raw engine speed, and their gap to the JSON rows is what serializing and handing off costs tsv, not a cross-tool comparison. @@ -434,19 +411,16 @@ most noise.
  • - Biome is grayed out across all three parse groups: - @biomejs/js-api - exposes formatting and linting only, so the AST it parses internally never crosses the JS - boundary and can't be measured. + Biome is grayed out across all three parse groups: its in-process API exposes formatting + and linting only, so the AST it parses never reaches JS to be measured.
  • oxc-parser, yuku-parser, and swc parse TypeScript and JS only (and JSX, not measured here) — no CSS, no Svelte, no formatter — so they're timed in the TypeScript parse group alone. - oxc-parser's AST has no line/column option (only a range flag repeating the - offsets as a pair), so the span-only no-locs entries are the one - payload-matched pairing. Its wasm row runs an older release than its native row — the - newest whose wasi binding loads in the harness install — so the wasm-vs-wasm pairing - crosses oxc versions (both listed under + oxc-parser's AST has no line/column option, so the span-only no-locs entries + are the one payload-matched pairing. Its wasm row runs an older release than its native + row — the newest whose wasi binding loads in the harness install — so the wasm-vs-wasm + pairing crosses oxc versions (both listed under {DETAILS_SECTION_TITLE}).
  • @@ -461,12 +435,11 @@
  • rsvelte's is the only Svelte parser here besides tsv's and the svelte/compiler reference, and it matches tsv's default wire in mechanism and payload — a JSON string with per-node - loc, within a few percent of tsv-json's bytes, which the caller - JSON.parses — so rsvelte-parse compares against - tsv-json, not the no-locs entries. Its second entry passes - rsvelte's own skipExpressionLoc, which drops loc only on - embedded JS expressions and keeps the top-level offsets — a different trade than tsv's - span-only wire, hence the entry is named for the option. + loc that the caller JSON.parses — so rsvelte-parse + compares against tsv-json, not the no-locs entries. Its second + entry passes rsvelte's own skipExpressionLoc, which drops loc + only on embedded JS expressions and keeps the top-level offsets — a different trade than + tsv's span-only wire. {#if rsvelte_svelte_target && rsvelte_svelte_target !== svelte_version} Its addon targets its own upstream Svelte, {rsvelte_svelte_target}, a release apart from the {svelte_version} the svelte/compiler row runs (both are listed under Benchmarking @@ -482,12 +455,11 @@ PostCSS is the only CSS parser here besides tsv's and the parseCss reference; none of the Rust CSS tools considered offers a parse call — Lightning CSS ships transform and - bundle calls only, whose visitor callbacks can hand JS the whole stylesheet - but only as a side channel of a transform run, never as a parse product; Biome surfaces no - parser; malva is a formatter. PostCSS is also the parser behind Prettier's CSS printer, so - it's the parse-side counterpart of the Prettier format entry. It isn't payload-matched to - tsv: it keeps selectors and values as strings where parseCss and tsv build - ASTs, a much lighter tree. + bundle but no parse call, Biome surfaces no parser, and malva is a formatter. + PostCSS is also the parser behind Prettier's CSS printer, so it's the parse-side + counterpart of the Prettier format entry. It isn't payload-matched to tsv: it keeps + selectors and values as strings where parseCss and tsv build ASTs, a much + lighter tree.
  • @@ -510,12 +482,10 @@ acorn-typescript) — and aren't files a package ships. Neither publishes a single artifact, and installed size counts every language Prettier supports in two module formats, so each entry is instead a minified, tree-shaken bundle of the least one job needs for tsv's three - languages: what you would deploy to a browser, not what Node loads (a plain - import 'prettier' plus the plugin is several times larger, since Prettier's - package entry registers every language it supports). The full entry is barely larger than - the formatter because the formatter already contains the Svelte parser. Minified JS - compresses much better than wasm, so these read smaller by gz than by raw - bytes — and a size says nothing of the speed measured above. + languages: what you would deploy to a browser, not what Node loads. The full entry is + barely larger than the formatter because the formatter already contains the Svelte parser. + Minified JS compresses much better than wasm, so these read smaller by gz + than by raw bytes.
  • Each group mixes wasm and native builds under one anchor, so a ratio can cross kinds — @@ -525,8 +495,7 @@ @fuzdev/tsv, a JS dispatcher over prebuilt per-platform packages. The (ffi) entries are its C-ABI build, which isn't published — what the engine costs in that configuration, not - something you can install; the cross-runtime section's Deno run loads it, and its - format-only and parse-only variants are built for this table alone and never timed. + something you can install; the cross-runtime section's Deno run loads it.
  • The Parser group is scope as much as engine. yuku-parser parses TypeScript and JS only, @@ -537,9 +506,8 @@ them as what those addons ship, not as parser size.
  • - Biome bundles a parser, formatter, and linter for many languages, but every other native - entry here is an in-process library (rsvelte-fmt's standalone binary aside), and Biome's - native engine ships to npm only as the CLI binary — so only its wasm build is included. + Biome bundles a parser, formatter, and linter for many languages; only its wasm build is + included, since its native engine ships as a CLI binary rather than a library.
  • The {OXC_FULL_LABEL} entry under Full toolchain sums oxc's separate parser @@ -547,27 +515,20 @@ equivalent to tsv's single parse+format build.
  • - That sum is a little unfair to oxc: oxfmt statically links its own copy of the oxc parser - (it must parse to format) without depending on the oxc-parser package or - exposing parsing, so the two independently compiled builds count the parser's code twice — - more than one build exposing both operations (like tsv's) needs — and the summed - gz annotation, two gzip streams rather than one, slightly overstates a - combined download. In the other direction, the oxfmt addon is more than a - formatter for tsv's three languages: it also carries oxc's JSON, TOML, GraphQL, and YAML - formatters, its import and package.json sorters, a language server, and the - oxfmt CLI itself, so part of its size is scope tsv doesn't have. + That sum is a little unfair to oxc: oxfmt statically links its own copy of the oxc parser, + so the two builds count the parser twice, and the summed gz is two gzip + streams rather than one. The other way, the oxfmt addon is more than a + formatter for tsv's three languages — it also formats JSON and YAML, sorts imports, and + carries a language server and the CLI itself.
  • - And a little unfair to tsv the other way: every entry is one artifact file, so - {OXFMT_NATIVE_LABEL} is its .node alone and leaves out the JS in - the oxfmt package that loads it. That JS is nearly as large as the addon — - over half of it Prettier with its parsers and prettier-plugin-svelte for its Svelte path, - nearly all the rest the Tailwind class sorter and the config loader it pulls in. - {RSVELTE_INSTALL_LABEL} likewise omits @rsvelte/fmt's launcher - package (a small script, though the Tailwind class sorter it depends on adds a few - megabytes). The same rule cuts tsv's way once: tsv (napi) is its - .node alone, and the platform package that ships it also carries the - tsv CLI binary, nearly as large again. + Every entry is one artifact file, which undercounts in both directions. + {OXFMT_NATIVE_LABEL} is its .node alone, leaving out the + package's JS that loads it — nearly as large again, over half of it a bundled Prettier, + the one behind its Svelte path — and {RSVELTE_INSTALL_LABEL} omits its + launcher package. tsv (napi) is likewise its .node alone, and + the platform package that ships it also carries the tsv CLI binary, nearly as + large again.
  • oxfmt ships no wasm build, so it's shown grayed-out under Formatter, holding its slot @@ -578,9 +539,8 @@ carrying a CLI and oxc's JS/TS, CSS, and JSON formatters beside its Svelte engine, where the tsv entries are bare libraries. {RSVELTE_INSTALL_LABEL} is what you install to format a project, and the fairer comparison to tsv's single build: over a - directory the benched release exits non-zero without oxfmt, an optional peer dependency it - hands every file type it doesn't format itself; a single .svelte file needs - none. + directory it needs oxfmt, an optional peer dependency it hands every file type it doesn't + format itself.
  • dprint (wasm) and malva (wasm) are two plugins for the same @@ -607,39 +567,34 @@ Within a group every tool is timed on the same file set — the intersection of what every timed tool accepted, so a file one rejects drops out for everyone. The count above each chart is that intersection; where a group runs short of the corpus total, a note under its chart gives - the files and the share of the group's bytes left out, and which rows failed them — some - because the harness's synthetic file.ts name hides a declaration file for what it - is, the rest limits of the tool's own — each excused by name in tsv's harness rather than - skipped silently. These are warm numbers: every row runs warmup sweeps before it is timed, so - caches and allocators are primed and a cold one-shot call pays more; and each native or wasm - call pays a string encode across the binding boundary, and a decode wherever it hands back - text or JSON, which the JS tools skip. Rows run in a fixed order, not interleaved or shuffled: - the canonical row, then tsv's rows, then the alternatives. A forced garbage collection before - each row (not each sweep) bounds what one row's garbage costs the next without removing order - as a variable. Unlike the CLI section's ordering, that residue and any thermal drift on a - machine that throttles run against the rows after tsv's — every alternative — so order bias - there counts for tsv, not against it. The canonical row is the exception: it runs before - tsv's, so the bias runs against tsv in every ratio that divides by one — the summary table, - and the parse comparisons against svelte/compiler, acorn-typescript, and - parseCss. + the files and the share of the group's bytes left out, and which rows failed them. These are + warm numbers: every row runs warmup sweeps before it is timed, so a cold one-shot call pays + more; and each native or wasm call pays a string encode across the binding boundary, and a + decode wherever it hands back text or JSON, which the JS tools skip.

    - Every row of a runtime runs in one process under one set of flags, so its native and wasm rows - share a heap and a configuration. Nothing pins the process to a core or holds the clock steady - — an unpinned run on a laptop CPU — so thermal drift is a live possibility, not a formality. - The tsv-wasm rows run the full parse+format artifact - @fuzdev/tsv-wasm ships, in the bench's Node-target bundle of it, which keeps the - internal parse entry points the published package's public API leaves out — not the smaller - format-only or parse-only packages. Sweep counts differ widely by row because each row gets a - time budget rather than a count: at least {format_count_maybe(sweeps.floor)} - sweeps{canonical_floor_note}, otherwise as many as fit a few seconds (after a warmup on the - same time budget, with a floor of three sweeps), so the multi-second rows stop near that - floor; after outlier cleaning, which can leave a row with fewer timings than the floor it ran, - the report keeps from {format_count_maybe(sweeps.sample_size_min)} to + Rows run in a fixed order, not interleaved or shuffled: the canonical row, then tsv's rows, + then the alternatives. A forced garbage collection before each row limits what one row leaves + for the next, but whatever remains, and any thermal drift, runs against the rows after tsv's — + every alternative — so order bias there counts for tsv, not against it. The canonical row is + the exception: it runs before tsv's, so the bias runs against tsv in every ratio that divides + by one — the summary table, and the parse comparisons against svelte/compiler, + acorn-typescript, and parseCss. +

    +

    + Nothing pins the process to a core or holds the clock steady — an unpinned run on a laptop CPU + — so thermal drift is a live possibility, not a formality. The tsv-wasm rows run + the full parse+format build, not the smaller format-only or parse-only ones. +

    +

    + Sweep counts differ widely by row because each row gets a time budget rather than a count: at + least {format_count_maybe(sweeps.floor)} sweeps{canonical_floor_note}, otherwise as many as + fit a few seconds, so the multi-second rows stop near that floor. After outlier cleaning the + report keeps from {format_count_maybe(sweeps.sample_size_min)} to {format_count_maybe(sweeps.sample_size_max)} timings per row. A low cv over a handful of - sweeps is thinner evidence of quiet than the same cv over hundreds; the instability check - behind the headline ratios reads every row's raw cv and drift but proves less at the floor — - where Prettier, the denominator of every ratio in the summary table, sits. + sweeps is thinner evidence of quiet than the same cv over hundreds, so the instability check + behind the headline ratios proves less for the slow rows that stop there — Prettier among + them, the denominator of every ratio in the summary table.

    @@ -694,12 +649,9 @@ addon, Deno its C-FFI library. They share code but cross a different binding boundary, so a per-runtime delta on the same row is a runtime effect — the JS engine, the host's N-API implementation, or the binding boundary — not a difference in tsv's algorithms. Nor is it - quite one binary: the same engine at the same optimization settings, but the two binding - crates link slightly different code around it, the N-API crate is the one that ships where the - C-ABI build is unpublished, and the N-API build keeps panic unwinding where the FFI one - aborts, which changes code generation and adds the unwind tables the binary-size table counts. - A delta the report finds inside the two measurements' combined noise is marked ≈ - in the tables and reads as parity, not an effect. + quite one binary: the same engine and settings, but the N-API build keeps panic unwinding + where the FFI one aborts. A delta the report finds inside the two measurements' combined noise + is marked ≈ in the tables and reads as parity, not an effect.

  • +
  • + Like for like, against the dispatcher row, CPU work widens tsv's lead on the TypeScript + repo: ~{npm_ts_vs_oxfmt} faster than Oxfmt in wall-clock and ~{npm_ts_cpu_vs_oxfmt} in CPU + work, ~{npm_ts_vs_biome} and ~{npm_ts_cpu_vs_biome} against Biome. Against the bare binary + it narrows instead — Oxfmt ~{ts_wall_vs_oxfmt} to ~{ts_cpu_vs_oxfmt}, Biome + ~{ts_wall_vs_biome} to ~{ts_cpu_vs_biome}. The gap between the two footings is launch cost, + not the engines: a fixed ~{npm_overhead} for tsv's dispatcher, most of it Node's own startup + (a bare node -e "" takes ~{format_ms(node_startup_ms)} on this machine), which + every other npm-bin row pays too.
  • CPU work is a clean engine proxy only while the threads do real work: a JS tool's figure @@ -136,17 +128,15 @@ before reading either as engine speed.
  • - Peak memory is less tied to core count than wall-clock (though nothing here measures it - against thread count), so it should travel better between machines: tsv uses - {format_ratio_range(npm_memory)} less than every other tool in every scenario it faces them - through its npm dispatcher, and {format_ratio_range(memory)} less as the bare binary. The - figure is the largest single process in each command's tree, not the sum (the CPU-work - column does sum the tree), so a row that launches a native binary from Node — Biome's, - rsvelte-fmt's, and tsv's dispatcher — is understated: the smaller processes in its tree - don't count. Prettier's, Oxfmt's, and the bare tsv rows each run as one process - here and are measured whole. The dispatcher's peak, ~{format_mib(npm_memory_mb)}, is still - below every other tool's — and, by the harness's own note, about the size of the launcher - Biome's and rsvelte-fmt's rows leave out. + Peak memory is less tied to core count than wall-clock, so it should travel better between + machines: tsv uses {format_ratio_range(npm_memory)} less than every other tool in every + scenario it faces them through its Node dispatcher, and {format_ratio_range(memory)} less as + the bare binary. The figure is the largest single process in each command's tree, not the + sum (the CPU-work column does sum the tree), so a row that launches a native binary from + Node — Biome's, rsvelte-fmt's, and tsv's dispatcher — is understated: the smaller processes + in its tree don't count. Prettier's, Oxfmt's, and the bare tsv rows each run as + one process here and are measured whole. The dispatcher's peak, + ~{format_mib(npm_memory_mb)}, is still below every other tool's.
  • On the large single file, where a Node bin's fixed launch cost weighs most against a short @@ -161,7 +151,7 @@ staying resident until it exits. That launch cost is fixed, so its share shrinks on a real repo, where the dispatcher takes ~{npm_ts_cost} as long. @fuzdev/tsv-wasm — - the fallback for platforms without a prebuilt binary, not the default — runs the same CLI + the package for platforms without a prebuilt binary, not the default — runs the same CLI over a WASM engine inside Node at ~{wasm_wall} the time and ~{wasm_memory} the memory of the native binary: still well ahead of both Prettier rows on the same file above, behind Oxfmt and Biome. @@ -170,39 +160,32 @@ Formatting configuration is matched: tsv is non-configurable (width 100, tabs, single quotes, no trailing commas), so every formatter it faces is configured to that profile in its own dialect — outputs still differ where the tools decide differently. The preflight - asserts that every formatter reporting a file count reports the same one (the two Prettier - rows report none and sit that check out) and that every formatter finds at least one file to - change, so a mis-scoped tool formatting nothing can't post an unbeatable time. The cost: - these rows aren't comparable with upstream's published numbers, which leave the tools nearer - their defaults. + asserts that every formatter reporting a file count reports the same one and that every + formatter finds at least one file to change, so a mis-scoped tool formatting nothing can't + post an unbeatable time. The cost: these rows aren't comparable with upstream's published + numbers, which leave the tools nearer their defaults.
  • The tools are pinned but one corpus isn't: the TypeScript repo is Outline at its default branch's head, so its file set moves whenever it is re-cloned. Every formatter is scoped to the JSX-free .ts/.js family — the others by their config, tsv (which has none) by the extensions it walks — leaving out the .tsx and - .jsx tsv can't parse, and the preflight file-count check holds the two scopes - to the same set. The single file (the TypeScript compiler's parser.ts at a - pinned release) and the Svelte corpus (a pinned + .jsx tsv can't parse, and the preflight file-count check holds the tools that + report a count to the same set. The single file (the TypeScript compiler's + parser.ts at a pinned release) and the Svelte corpus (a pinned fuzdev/corpora commit) are fixed.
  • - Nothing is skipped and no failure is timed around: every scenario tsv runs in starts with a - preflight parse check, and a run that errors partway fails the scenario instead of being - timed (the scenarios tsv sits out keep hyperfine's --ignore-failure, so a - formatter that errors partway is timed there rather than aborting the scenario). A scenario - whose preflight fails is aborted before timing and shown as aborted rather than dropped — a - crash in one formatter's check must not become a fast partial run. tsv sits out those - scenarios because they contain JSX/TSX; two also measure work tsv doesn't do - (embedded-language formatting in one; import, Tailwind-class, and package.json - sorting in the other). + Nothing is skipped and no failure is timed around: every scenario starts with a preflight + parse check, and a run that errors partway fails the scenario instead of being timed. A + scenario whose preflight fails is aborted before timing and shown as aborted rather than + dropped — a crash in one formatter's check must not become a fast partial run.
  • hyperfine runs commands in the order given, with no interleaving or shuffling, so on a machine that throttles the later tools run warmer{settle_note}. Every scenario tsv runs in - puts the bare binary last, with its npm dispatcher row just before it (the tables sort by - time, not run order), so that drift counts against tsv, not for it. The last decimal of each - ratio is that much noise. + puts the bare binary last, with its Node dispatcher row just before it, so that drift counts + against tsv, not for it.
  • diff --git a/src/routes/docs/benchmarks/benchmarks_cli.ts b/src/routes/docs/benchmarks/benchmarks_cli.ts index 9a96ffd..f215652 100644 --- a/src/routes/docs/benchmarks/benchmarks_cli.ts +++ b/src/routes/docs/benchmarks/benchmarks_cli.ts @@ -136,7 +136,7 @@ export const CLI_DELIVERY_KEY = 'tsv-delivery-paths'; * `@fuzdev/tsv`'s Node bin. It runs in the delivery scenario and beside native * tsv wherever the harness benches it against the other tools' npm bins. */ -export const CLI_TSV_NPM_LABEL = 'tsv via npm dispatcher'; +export const CLI_TSV_NPM_LABEL = 'tsv via Node dispatcher'; /** The delivery scenario's WASM row, as displayed. */ export const CLI_TSV_WASM_LABEL = 'tsv-wasm'; @@ -176,13 +176,13 @@ const SCENARIO_COPY: Record = { [CLI_SVELTE_KEY]: { heading: 'Svelte corpus', description: - 'Two Rust Svelte-native formatters head-to-head on a third-party .svelte corpus, rsvelte-fmt configured to tsv’s fixed style so both do comparable line-break work. Its time includes the oxfmt it spawns for the files it doesn’t format itself — none here, but that is how it ships — and the harness pins its style cache and oxfmt daemon off. rsvelte-fmt 0.7.x aborts nondeterministically on this corpus when its check-mode output has stdout and stderr merged onto one pipe — how the harness’s preflight runs it, and how a CI invocation piping both through tee would. The harness keeps the merged pipe rather than dodge the bug, and never retries: a run is published as it ended, complete or aborted, and about two in three attempts abort.', + 'Two Rust Svelte-native formatters head-to-head on a third-party .svelte corpus, rsvelte-fmt configured to tsv’s fixed style so both do comparable line-break work. Its time includes the oxfmt it spawns for the files it doesn’t format itself — none here, but that is how it ships — and the harness pins its style cache and oxfmt daemon off. rsvelte-fmt 0.7.x aborts nondeterministically on this corpus under the harness’s preflight, a condition the harness keeps rather than works around, and it never retries: a run is published as it ended, complete or aborted.', tsv_only: false }, [CLI_DELIVERY_KEY]: { heading: 'tsv delivery paths', description: - 'Every row is tsv, not another tool: the native binary, the same binary through @fuzdev/tsv’s Node dispatcher (how npx tsv runs it), and @fuzdev/tsv-wasm, the same CLI over a WASM engine, the fallback for platforms without a prebuilt binary. One file, so the gaps are launch and engine cost, not file parallelism (the WASM row’s CPU time exceeds its wall-clock because V8 compiles the module on background threads).', + 'Every row is tsv, not another tool: the native binary, the same binary through @fuzdev/tsv’s Node dispatcher (how npx tsv runs it), and @fuzdev/tsv-wasm, the same CLI over a WASM engine, the package for platforms without a prebuilt binary. One file, so the gaps are launch and engine cost, not file parallelism (the WASM row’s CPU time exceeds its wall-clock, most likely V8 compiling the module on background threads).', tsv_only: true } }; @@ -326,7 +326,7 @@ export const cli_speedup_vs_tsv = ( ): number | undefined => cli_speedup_vs(scenario_key, label, CLI_TSV_LABEL, metric); /** - * How many times faster or lighter tsv through its npm dispatcher is than `label` + * How many times faster or lighter tsv through its Node dispatcher is than `label` * in one CLI scenario — the like-for-like ratio, since the other tools are timed * through their npm bins too. * @@ -356,7 +356,7 @@ export const cli_tsv_npm_memory_mb = ( }; /** - * What the npm dispatcher adds over the bare binary in wall-clock, in + * What the Node dispatcher adds over the bare binary in wall-clock, in * milliseconds, spanned across every scenario that times both rows — Node * starting up to launch the binary, which the page calls a fixed cost. * @@ -375,26 +375,6 @@ export const cli_tsv_npm_overhead_ms_range = ( return { min: Math.min(...overheads), max: Math.max(...overheads) }; }; -/** - * What the npm dispatcher adds over the bare binary as a share of the - * dispatcher row's own run, in one scenario — Node's startup as a fraction of - * wall-clock and of CPU work, which a parallel run pays very differently. - * - * @returns the wall and CPU fractions, or `undefined` when either row is absent - */ -export const cli_tsv_npm_overhead_share = ( - scenario_key: string -): { wall: number; cpu: number } | undefined => { - const results = cli_scenario_find(scenario_key)?.results; - const npm = results?.find((r) => r.label === CLI_TSV_NPM_LABEL); - const tsv = results?.find((r) => r.label === CLI_TSV_LABEL); - if (!npm || !tsv || !npm.wall_ms || !npm.cpu_ms) return undefined; - return { - wall: (npm.wall_ms - tsv.wall_ms) / npm.wall_ms, - cpu: (npm.cpu_ms - tsv.cpu_ms) / npm.cpu_ms - }; -}; - /** * `label`'s measurement over `baseline_label`'s, by one metric, within a * scenario's rows. diff --git a/src/routes/docs/conformance/+page.svelte b/src/routes/docs/conformance/+page.svelte index 08a322e..83f6e5a 100644 --- a/src/routes/docs/conformance/+page.svelte +++ b/src/routes/docs/conformance/+page.svelte @@ -72,12 +72,10 @@
  • One column per engine, not per binding. That is exact for tsv, whose native and wasm rows - the bench holds to byte-identical output (bar one pathologically deep TypeScript file the - check can't digest, which the report discloses). oxc-parser's wasm binding is pinned to an - older release (see the benchmarks' parse notes) and accepts a couple of files the native - one doesn't; the native column stands. yuku-parser's is its wasm binding: the native one - segfaults on some of test262's escaped-identifier tests, and wasm runs the same parser - with the fault contained. + the bench holds to byte-identical output (bar one file the report discloses). oxc-parser's + wasm binding is pinned to an older release (see the benchmarks' parse notes) and accepts a + couple of files the native one doesn't; the native column stands. yuku-parser's is its + wasm binding, since the native one crashes on some of test262's tests.
  • Accepting a file says nothing about producing the right AST — tsv's output is diff --git a/src/test/benchmark_data.prose.test.ts b/src/test/benchmark_data.prose.test.ts index 312d08d..e9ea97a 100644 --- a/src/test/benchmark_data.prose.test.ts +++ b/src/test/benchmark_data.prose.test.ts @@ -14,7 +14,6 @@ import { cli_speedup_vs_tsv_npm, cli_tsv_npm_memory_mb, cli_tsv_npm_overhead_ms_range, - cli_tsv_npm_overhead_share, cli_node_startup_ms, CLI_DELIVERY_KEY, CLI_SCENARIO_KEYS, @@ -242,9 +241,9 @@ describe('prose ratios resolve', () => { }); test('the like-for-like dispatcher claims read the way the numbers run', () => { - // The TLDR and the CLI note lead with tsv through its npm dispatcher against the + // The TLDR and the CLI note lead with tsv through its Node dispatcher against the // other tools' npm bins: "~Nx faster than Oxfmt and ~Mx faster than Biome ... - // using A–Bx less memory than either". The copy has no bare-binary fallback, so + // using less memory than either". The copy has no bare-binary fallback, so // every one must resolve or a sentence prints with a hole in it. for (const key of [CLI_SINGLE_FILE_KEY, CLI_TS_REPO_KEY]) { for (const label of ['oxfmt', 'biome']) { @@ -259,8 +258,7 @@ describe('prose ratios resolve', () => { baseline_label: CLI_TSV_NPM_LABEL }); assert.isDefined(memory); - // floored to one decimal for display, so "less memory" needs its low end to reach 1.1 - assert.isAtLeast(memory.min, 1.1); + assert.isAbove(memory.min, 1); // "~Nx on the TypeScript repo": the dispatcher's own cost there, which the // delivery note says shrinks against the one-file figure const repo_cost = cli_speedup_vs_tsv(CLI_TS_REPO_KEY, CLI_TSV_NPM_LABEL, 'wall_ms'); @@ -361,18 +359,6 @@ describe('prose ratios resolve', () => { } }); - test('the dispatcher overhead reads as a share of wall-clock far above its share of CPU', () => { - // "~N% of its wall-clock on the repo but ~M% of its CPU total": the note's point - // is the asymmetry, so the wall share must clearly exceed the CPU share, and - // both must be shares — inside (0, 1) — or the sentence prints nonsense - const share = cli_tsv_npm_overhead_share(CLI_TS_REPO_KEY); - assert.isDefined(share); - assert.isAbove(share.wall, 0); - assert.isBelow(share.wall, 1); - assert.isAbove(share.cpu, 0); - assert.isAbove(share.wall, share.cpu * 2, 'the wall-clock share is not clearly larger'); - }); - test('the Node launch floor sits inside the dispatcher overhead', () => { // "a bare node -e '' takes ~N ms on this machine": Node's startup is one part // of what the dispatcher row pays over the bare binary, so it must not exceed @@ -383,6 +369,8 @@ describe('prose ratios resolve', () => { assert.isDefined(overhead); assert.isAbove(floor, 0); assert.isBelow(floor, overhead.max); + // "most of it Node's own startup" + assert.isAbove(floor, overhead.max / 2); }); test('the dispatcher overhead is the "fixed cost" the delivery note calls it', () => { @@ -468,7 +456,7 @@ describe('prose ratios resolve', () => { }); test('the run-order note holds: every scenario runs the dispatcher row, then bare tsv, last', () => { - // "Every scenario here puts the bare tsv binary last, with its npm dispatcher + // "Every scenario here puts the bare tsv binary last, with its Node dispatcher // row just before it" — hyperfine reports commands in the order it ran them, // and the generated timings keep that order. An aborted scenario has no timings // to order, so its preflight rows, which the harness runs in the same order, stand in. diff --git a/src/test/benchmarks_cli.test.ts b/src/test/benchmarks_cli.test.ts index 079c4bd..918fe01 100644 --- a/src/test/benchmarks_cli.test.ts +++ b/src/test/benchmarks_cli.test.ts @@ -52,7 +52,7 @@ describe('to_abort_note', () => { ] }) ), - 'Not timed: rsvelte-fmt crashed partway through its parse check; tsv via npm dispatcher could not run; biome rejected 3 files.' + 'Not timed: rsvelte-fmt crashed partway through its parse check; tsv via Node dispatcher could not run; biome rejected 3 files.' ); }); @@ -247,7 +247,7 @@ describe('to_unshimmed_note', () => { test('names the rows by their display labels', () => { assert.strictEqual( to_unshimmed_note(['tsv-npm', 'tsv-wasm']), - 'tsv via npm dispatcher and tsv-wasm ran as a bare Node script, skipping the few milliseconds of pnpm bin shim the other tools’ rows go through.' + 'tsv via Node dispatcher and tsv-wasm ran as a bare Node script, skipping the few milliseconds of pnpm bin shim the other tools’ rows go through.' ); }); }); From a1ccb1a74872051b837a7c26087f3b5a728715c9 Mon Sep 17 00:00:00 2001 From: Ryan Atkinson Date: Mon, 21 Sep 2026 17:41:39 -0400 Subject: [PATCH 186/218] wip --- CLAUDE.md | 6 +-- src/routes/docs/benchmarks/+page.svelte | 31 +++++++------- .../docs/benchmarks/BenchmarksCli.svelte | 7 ++-- .../benchmarks/BenchmarksCliSection.svelte | 12 +++--- src/routes/docs/benchmarks/benchmark_sizes.ts | 2 +- src/routes/docs/benchmarks/benchmarks_cli.ts | 7 ++-- src/routes/docs/conformance/+page.svelte | 19 ++++----- .../docs/conformance/conformance_data.ts | 12 +++--- .../benchmark_cross_runtime.shape.test.ts | 3 +- src/test/benchmark_data.prose.test.ts | 40 +++++++++---------- src/test/benchmark_display.test.ts | 9 +++++ src/test/benchmarks_cli.test.ts | 5 +++ src/test/conformance_data.prose.test.ts | 17 +++++++- src/test/conformance_data.shape.test.ts | 13 ++++-- src/test/conformance_data.test.ts | 34 +++++++++------- 15 files changed, 128 insertions(+), 89 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 4fd42e9..f366d7c 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -157,16 +157,16 @@ in the schema TSDoc in `formatter_benchmark_data.ts`. - `benchmark_data.ts` — per-runtime report types, plus the format/parse, stability, and corpus derivations; imports none of the others - `BenchmarksCorpus.svelte` — the per-source corpus table both pages' `Corpus` sections render, from `benchmark_data.ts`'s `derive_corpus_source_table`; a source no repo names needs a hand label (`CORPUS_SOURCE_LABELS`), and the conformance page hand-labels every source (`CONFORMANCE_SOURCE_LABELS`, which its matrix also reads); the shape test holds both - `benchmark_display.ts` — value formatters, row labels, per-category colors; imports only `benchmark_data.ts`'s types -- `benchmark_sizes.ts`, `benchmark_cross_runtime.ts` — one domain each, built on `benchmark_data.ts` (the cross-runtime one on `benchmark_display.ts` too); the conformance page's `conformance_data.ts` does the same from its own directory — a matrix per language (corpus sources × engines, the aggregate as the leading row), with two hand-stated maps the report has no field for: the source labels and `CONFORMANCE_SELECTORS`, the engine that selected a source and so reads 100% on it by construction; the shape test holds both to the report +- `benchmark_sizes.ts`, `benchmark_cross_runtime.ts` — one domain each, built on `benchmark_data.ts` (the cross-runtime one on `benchmark_display.ts` too); the conformance page's `conformance_data.ts` does the same from its own directory — a matrix per language (corpus sources × engines, the aggregate as the leading row), with hand-stated maps the report has no field for: the engine names, the row notes, the source labels, and `CONFORMANCE_SELECTORS`, the engine that selected a source and so reads 100% on it by construction; the shape test holds each to the report - `benchmark_baseline.ts` + `BenchmarksBaselineGroup.svelte` — hover-to-rebaseline: hovering a row re-anchors that group's ratios, restoring the default anchor on leave; pointer-only by design, and a disabled row never anchors. `BenchmarksCli.svelte`'s tables behave the same way - `formatter_benchmark_data.ts` — the harness report's Zod schemas and `parse_formatter_benchmarks` - `benchmarks_cli.ts` — shapes the CLI report for `BenchmarksCli.svelte` and owns the per-scenario prose and the `cli_*` claim helpers - `benchmarks_prose.ts` — `IN_PROCESS_PAIRS`, the in-process pairings the copy names; the page reads it by key and the prose test iterates it, so a pairing added to the copy is gated by construction - `benchmarks.ts`, `benchmarks_cross_runtime.ts`, `benchmarks_formatters.ts` (and the conformance page's `conformance.ts`) — re-export the JSON with types -- `BenchmarksCliSection.svelte` — the CLI section's prose and its claims; the other `Benchmarks*.svelte` are visualizations +- `BenchmarksCliSection.svelte` — the CLI section's prose and its claims; the other `Benchmarks*.svelte` are visualizations (`BenchmarksSummary.svelte` carries its table's Prettier caption, which the prose test gates) - `benchmarks.css` — classes the components share, imported by the benchmarks and conformance `+page.svelte`s rather than the root stylesheet so they ship with those routes only -The page quotes no hand-written ratios or counts: its prose computes them from +The page quotes no hand-written ratios or counts from the reports: its prose computes them from the same reports the charts render, through tested helpers in the TS modules, so the components' scripts hold no untested reductions. diff --git a/src/routes/docs/benchmarks/+page.svelte b/src/routes/docs/benchmarks/+page.svelte index 4d1c38a..24623bf 100644 --- a/src/routes/docs/benchmarks/+page.svelte +++ b/src/routes/docs/benchmarks/+page.svelte @@ -342,15 +342,16 @@ Oxfmt formats TypeScript, JS, and CSS with its own native engine; for Svelte it delegates to a Prettier it bundles, with a bundled copy of prettier-plugin-svelte — - the embedded <script> still goes through its native engine, the - <style> through that Prettier's CSS printer. + only the embedded <script> goes through its native engine; the markup, + its expressions, and the <style> are that Prettier's.
  • Biome has no dedicated Svelte formatter: its Svelte row runs with html.experimentalFullSupportEnabled, the experimental HTML-superset pipeline - that lets it format .svelte at all; without the flag it returns empty output. - Embedded script and style are formatted too, so the work is comparable. Its row also pays - a cold first sweep each time the harness rebuilds its wasm instance, a few percent. + that lets it format .svelte at all; without the flag it returns only the + script. Embedded script and style are formatted too, so the work is comparable. Its row + also pays a cold first sweep each time the harness rebuilds its wasm instance, a few + percent.
  • There's no native Biome entry: @biomejs/js-api, its in-process API, backs @@ -556,12 +557,12 @@

    One asymmetry in the in-process timings isn't isolated: oxfmt's programmatic - format is async-only, so each call pays an N-API task dispatch and promise - resolution inside its timing that tsv's sync call doesn't, and the native work may run off the - JS thread — still one file at a time, since each call is awaited before the next, but not - strictly one thread. Each row is the total time to process its group's timed files once — not - the multi-core batch throughput a CLI gets when it formats many files at once, which most of - these tools (tsv included) can do. + format is async-only (as is Prettier's, without the N-API hop), so each call pays + an N-API task dispatch and promise resolution inside its timing that tsv's sync call doesn't, + and the native work may run off the JS thread — still one file at a time, since each call is + awaited before the next, but not strictly one thread. Each row is the total time to process + its group's timed files once — not the multi-core batch throughput a CLI gets when it formats + many files at once, which most of these tools (tsv included) can do.

    Within a group every tool is timed on the same file set — the intersection of what every timed @@ -602,8 +603,8 @@

    - Every in-process number on this page is measured on {format_count(corpus_counts.files)} files - of .svelte, .ts/.js, and .css — real-world + Every in-process number on this page comes from {format_count(corpus_counts.files)} files of + .svelte, .ts/.js, and .css — real-world code only, vendored at one pinned commit in the @@ -651,7 +652,9 @@ implementation, or the binding boundary — not a difference in tsv's algorithms. Nor is it quite one binary: the same engine and settings, but the N-API build keeps panic unwinding where the FFI one aborts. A delta the report finds inside the two measurements' combined noise - is marked ≈ in the tables and reads as parity, not an effect. + is marked ≈ in the tables and reads as parity, not an effect. It can't see + variance between whole runs: Bun's allocation-heavy JS rows (Prettier, PostCSS) have sat at + two levels ~10–14% apart.

  • - Nothing is skipped and no failure is timed around: every scenario starts with a preflight - parse check, and a run that errors partway fails the scenario instead of being timed. A - scenario whose preflight fails is aborted before timing and shown as aborted rather than - dropped — a crash in one formatter's check must not become a fast partial run. + Nothing is skipped and no failure is timed around: every scenario here starts with a + preflight parse check, and a run that errors partway fails the scenario instead of being + timed. A scenario whose preflight fails is aborted before timing and shown as aborted rather + than dropped — a crash in one formatter's check must not become a fast partial run.
  • hyperfine runs commands in the order given, with no interleaving or shuffling, so on a machine that throttles the later tools run warmer{settle_note}. Every scenario tsv runs in - puts the bare binary last, with its Node dispatcher row just before it, so that drift counts - against tsv, not for it. + puts the bare binary last, with its Node dispatcher row just before it (the tables sort by + time, not run order), so that drift counts against tsv, not for it.
  • diff --git a/src/routes/docs/benchmarks/benchmark_sizes.ts b/src/routes/docs/benchmarks/benchmark_sizes.ts index 0cd5d06..7ad8e03 100644 --- a/src/routes/docs/benchmarks/benchmark_sizes.ts +++ b/src/routes/docs/benchmarks/benchmark_sizes.ts @@ -8,7 +8,7 @@ import type { BinarySize, ImplementationCategory } from './benchmark_data.ts'; // Binary-size categorization /** The suffix every synthesized canonical bundle's label carries (tsv's `canonical_bundles.ts`). */ -export const JS_BUNDLE_SUFFIX = '(js bundle)'; +const JS_BUNDLE_SUFFIX = '(js bundle)'; /** * The color category for a binary-size label — the size table's analog of diff --git a/src/routes/docs/benchmarks/benchmarks_cli.ts b/src/routes/docs/benchmarks/benchmarks_cli.ts index f215652..eb6f6c4 100644 --- a/src/routes/docs/benchmarks/benchmarks_cli.ts +++ b/src/routes/docs/benchmarks/benchmarks_cli.ts @@ -437,7 +437,7 @@ export const cli_comparison_results = ( * * @param scenarios - the scenarios to read, the rendered ones by default * @returns the low and high ratio, or `undefined` when nothing was measured, or - * when a named tool or the baseline row is missing from a spanned scenario + * when a named tool or the baseline's figure is missing from a spanned scenario */ export const cli_memory_ratio_range = ( options: { scenario_key?: string; labels?: Array; baseline_label?: string } = {}, @@ -454,9 +454,10 @@ export const cli_memory_ratio_range = ( for (const r of compared) { const ratio = cli_ratio_between(scenario.results, r.label, baseline_label, 'memory_mb'); if (ratio === undefined) { - // a named tool without a figure, or a scenario without the baseline row, + // a named tool without a figure, or a scenario without the baseline's, // would silently narrow the span the sentence claims - if (labels || !scenario.results.some((s) => s.label === baseline_label)) return undefined; + const baseline = scenario.results.find((s) => s.label === baseline_label); + if (labels || baseline?.memory_mb == null) return undefined; continue; } ratios.push(ratio); diff --git a/src/routes/docs/conformance/+page.svelte b/src/routes/docs/conformance/+page.svelte index 83f6e5a..f3a0f92 100644 --- a/src/routes/docs/conformance/+page.svelte +++ b/src/routes/docs/conformance/+page.svelte @@ -53,9 +53,10 @@
  • A greyed 100% marks the parser that chose a source, so reads 100% on it by construction: svelte/compiler on the Svelte set (the files it rejects are excluded, so the - others read as drop-in fidelity against it), tsc{tsc_label} on its compiler's - cases, and tsv on test262, so another parser's number there is its rate on tsv's slice, - not on test262. + others read as drop-in fidelity against it) and tsc{tsc_label} on its + compiler's cases. tsv's 100% on test262 is a result: the suite's own metadata picks the + tests, less the Annex B grammar tsv declines (see + Corpus).
  • The other sources keep intentionally-invalid and out-of-scope inputs (wpt's @@ -67,8 +68,7 @@ PostCSS sitting above tsv is two grammars, not a gap. The CSS reference is Svelte's parseCss, which tsv is a drop-in for and no validity oracle in either direction; PostCSS keeps selectors and at-rule preludes as unparsed strings, so it accepts - preprocessor syntax, malformed rules, and modern CSS parseCss doesn't - implement yet. + preprocessor syntax and malformed rules.
  • One column per engine, not per binding. That is exact for tsv, whose native and wasm rows @@ -101,7 +101,7 @@ sources, none of them the real-world code the time: formatter and compiler test suites, read from pinned checkouts, and three conformance suites the harness harvests into caches. Every file is parsed as a module, except test262's, parsed at the goal - each test declares. + each test declares; tsc alone infers the goal itself.

    • @@ -122,9 +122,10 @@ The web-platform-tests CSS is extracted from its tests' <style> blocks.
    • - JSX is out by construction — Prettier's JSX fixtures and the compiler's .tsx - cases are dropped, since tsv rejects JSX by design where oxc-parser, yuku-parser, swc, and - tsc can parse it — so these tables say nothing about that gap. + JSX is out by construction: Prettier's JSX suite and the compiler's .tsx cases + are dropped, and every parser runs in TypeScript mode, where the JSX left in Prettier's JS + fixtures is rejected. tsv rejects JSX by design where oxc-parser, yuku-parser, swc, and tsc + can parse it, so these tables say nothing about that gap.

    diff --git a/src/routes/docs/conformance/conformance_data.ts b/src/routes/docs/conformance/conformance_data.ts index 115fdf5..185d41f 100644 --- a/src/routes/docs/conformance/conformance_data.ts +++ b/src/routes/docs/conformance/conformance_data.ts @@ -108,8 +108,7 @@ export const derive_conformance_groups = (baseline: BenchmarkBaseline): Array = { * rather than by achievement: group key → source path (`*` for every source of * the group) → engine display name. Hand-stated because the report carries no * such field — svelte/compiler's rejects are excluded from the whole Svelte set, - * tsc kept only the compiler cases it parses cleanly, and the test262 cache is - * the expected-valid subset of the tests tsv's runner grades. The shape test - * holds every entry to the report: it must resolve, and its cell must be full. + * and tsc kept only the compiler cases it parses cleanly. test262 has no entry: + * its own metadata picks the expected-valid tests, never tsv's verdict, so tsv's + * 100% there is a result. The shape test holds every entry to the report: it + * must resolve, and its cell must be full. */ export const CONFORMANCE_SELECTORS: Record> = { 'parse/svelte': { '*': 'svelte/compiler' }, - 'parse/typescript': { [SOURCE_TEST262]: 'tsv', [SOURCE_TS_REPO]: 'tsc' } + 'parse/typescript': { [SOURCE_TS_REPO]: 'tsc' } }; /** One engine's coverage of one corpus source, or of the whole group. */ diff --git a/src/test/benchmark_cross_runtime.shape.test.ts b/src/test/benchmark_cross_runtime.shape.test.ts index 9070da0..ae78d84 100644 --- a/src/test/benchmark_cross_runtime.shape.test.ts +++ b/src/test/benchmark_cross_runtime.shape.test.ts @@ -25,7 +25,7 @@ describe('benchmarks_cross_runtime.json shape', () => { }); test('the conformance report is same-vintage with the perf siblings', () => { - // combined `version` 13 records it; a stale one means `update-benchmarks` + // the combined report records it; a stale one means `update-benchmarks` // copied a conformance report from a different refresh than the perf trio, // which the site has no banner for const vintage = benchmarks_cross_runtime_json.conformance_vintage; @@ -72,6 +72,7 @@ describe('benchmarks_cross_runtime.json shape', () => { // runtime, and the site has no annotation for it — recompose from same-box, // same-commit siblings. Every runtime must have reported a count for every // row, or the comparison would pass with nothing compared. + assert.isNotEmpty(benchmarks_cross_runtime_json.rows); for (const row of benchmarks_cross_runtime_json.rows) { for (const runtime of benchmarks_cross_runtime_json.runtimes) { assert.isNumber(row.files_iterated[runtime], `${row.group}/${row.name} ${runtime}`); diff --git a/src/test/benchmark_data.prose.test.ts b/src/test/benchmark_data.prose.test.ts index e9ea97a..012891e 100644 --- a/src/test/benchmark_data.prose.test.ts +++ b/src/test/benchmark_data.prose.test.ts @@ -38,8 +38,8 @@ import { // hand-written numbers, so a renamed entry or a dropped scenario would render // `—` mid-sentence instead of failing. These gate every pair the copy names. /** - * A ratio rendered inside a "~Nx faster than" sentence must clear 1 by enough - * to print as one: `format_ratio_approx` rounds to one decimal, so a ratio in + * A ratio rendered inside a "~Nx faster than" (or "as long", "the memory") sentence + * must clear 1 by enough to print as one: `format_ratio_approx` rounds to one decimal, so a ratio in * `[1, 1.05)` passes an `isAbove(1)` gate and still renders "~1.0x faster", a * claim of nothing. */ @@ -215,12 +215,11 @@ describe('prose ratios resolve', () => { test('every CLI ratio the prose quotes is present', () => { // (the TypeScript-repo wall/CPU pairs are covered by the CPU-work test below) - // the TLDR's "less memory than either" range, scoped to the tools it names, and - // the CLI note's "less than every other tool in every scenario" — both read as - // "less" and both are floored to one decimal for display, so the LOW end must - // reach 1.1 or the range would print "1.0–Nx less memory", a claim of nothing + // the CLI note's "less than every other tool in every scenario", against the bare + // binary and the dispatcher — both read as "less" and both are floored to one + // decimal for display, so the LOW end must reach 1.1 or the range would print + // "1.0–Nx less memory", a claim of nothing for (const range of [ - cli_memory_ratio_range({ scenario_key: CLI_TS_REPO_KEY, labels: ['oxfmt', 'biome'] }), cli_memory_ratio_range(), cli_memory_ratio_range({ baseline_label: CLI_TSV_NPM_LABEL }) ]) { @@ -236,7 +235,7 @@ describe('prose ratios resolve', () => { const ratio = cli_speedup_vs_tsv(CLI_DELIVERY_KEY, label, metric); assert.isDefined(ratio, `${CLI_DELIVERY_KEY}: ${label} ${metric}`); // the copy reads "takes ~Nx as long" / "~Nx the memory", so each must exceed 1 - assert.isAbove(ratio, 1, `${CLI_DELIVERY_KEY}: ${label} ${metric}`); + assert_reads_faster(ratio, `${CLI_DELIVERY_KEY}: ${label} ${metric}`); } }); @@ -265,7 +264,7 @@ describe('prose ratios resolve', () => { const file_cost = cli_speedup_vs_tsv(CLI_DELIVERY_KEY, CLI_TSV_NPM_LABEL, 'wall_ms'); assert.isDefined(repo_cost); assert.isDefined(file_cost); - assert.isAbove(repo_cost, 1); + assert_reads_faster(repo_cost, `${CLI_TS_REPO_KEY}: dispatcher cost`); assert.isBelow(repo_cost, file_cost, 'the dispatcher cost does not shrink on the repo'); // the Svelte bullet's like-for-like pair: that scenario may be published // aborted, but the copy quotes the dispatcher ratio wherever it quotes the @@ -274,7 +273,7 @@ describe('prose ratios resolve', () => { const ratio = cli_speedup_vs_tsv_npm(CLI_SVELTE_KEY, 'rsvelte-fmt', metric); const bare = cli_speedup_vs_tsv(CLI_SVELTE_KEY, 'rsvelte-fmt', metric); assert.strictEqual(ratio !== undefined, bare !== undefined, `${CLI_SVELTE_KEY}: ${metric}`); - if (ratio !== undefined) assert.isAbove(ratio, 1, `${CLI_SVELTE_KEY}: ${metric}`); + if (ratio !== undefined) assert_reads_faster(ratio, `${CLI_SVELTE_KEY}: ${metric}`); } }); @@ -339,24 +338,21 @@ describe('prose ratios resolve', () => { assert_reads_faster(ratio, `${label}: ${name}`); } } - // "launch cost, not the engines ... ~N% of its wall-clock on the repo but ~M% of - // its CPU total": the dispatcher - // must cost the repo run relatively more wall-clock than CPU work - const npm_wall = defined( - cli_speedup_vs_tsv(CLI_TS_REPO_KEY, CLI_TSV_NPM_LABEL, 'wall_ms'), - 'dispatcher wall_ms' - ); - const npm_cpu = defined( - cli_speedup_vs_tsv(CLI_TS_REPO_KEY, CLI_TSV_NPM_LABEL, 'cpu_ms'), - 'dispatcher cpu_ms' - ); - assert.isAbove(npm_wall, npm_cpu); // "even Prettier's CPU time runs above its wall-clock" for (const key of [CLI_SINGLE_FILE_KEY, CLI_TS_REPO_KEY]) { const prettier = cli_scenario_find(key)?.results.find((r) => r.label === 'prettier'); assert(prettier, `${key} has no prettier row`); assert.isAbove(prettier.cpu_ms, prettier.wall_ms, `${key}: prettier CPU > wall`); } + // "on the single file a tool that spins up a worker pool it can't use reads CPU + // above wall-clock too" + const pooled = cli_scenario_find(CLI_SINGLE_FILE_KEY)?.results.filter( + (r) => !cli_label_is_tsv(r.label) && !r.label.startsWith('prettier') + ); + assert( + pooled?.some((r) => r.cpu_ms > r.wall_ms), + 'no pooled tool reads CPU > wall' + ); }); test('the Node launch floor sits inside the dispatcher overhead', () => { diff --git a/src/test/benchmark_display.test.ts b/src/test/benchmark_display.test.ts index 3775ce3..9c07635 100644 --- a/src/test/benchmark_display.test.ts +++ b/src/test/benchmark_display.test.ts @@ -2,6 +2,7 @@ import { assert, describe, test } from 'vitest'; import { format_bytes, + format_gzip_size, format_count, format_coverage_percent, format_label, @@ -147,6 +148,14 @@ describe('format_bytes', () => { }); }); +describe('format_gzip_size', () => { + test('a measured size reads with its unit, an unmeasured one is undefined', () => { + assert.strictEqual(format_gzip_size(716_600), '717 KB gz'); + assert.isUndefined(format_gzip_size(null)); + assert.isUndefined(format_gzip_size(undefined)); + }); +}); + describe('format_percent', () => { test('rounds to one decimal', () => { assert.strictEqual(format_percent(41_125, 378_000), '10.9%'); diff --git a/src/test/benchmarks_cli.test.ts b/src/test/benchmarks_cli.test.ts index 918fe01..7a7a5e0 100644 --- a/src/test/benchmarks_cli.test.ts +++ b/src/test/benchmarks_cli.test.ts @@ -233,6 +233,11 @@ describe('cli claims spanning scenarios', () => { test('a scenario without the baseline row voids the range rather than narrowing it', () => { const no_baseline = scenario('s', { results: [result('oxfmt', 60, 100)] }); assert.isUndefined(cli_memory_ratio_range({}, [facing, no_baseline])); + // the row is there but its memory pass measured nothing + const no_figure = scenario('s', { + results: [result(CLI_TSV_LABEL, 20, null), result('oxfmt', 60, 100)] + }); + assert.isUndefined(cli_memory_ratio_range({}, [facing, no_figure])); }); test('a tsv-only scenario is spanned only by name', () => { diff --git a/src/test/conformance_data.prose.test.ts b/src/test/conformance_data.prose.test.ts index 4648222..474d75a 100644 --- a/src/test/conformance_data.prose.test.ts +++ b/src/test/conformance_data.prose.test.ts @@ -19,10 +19,25 @@ describe('conformance prose reads the report', () => { for (const path of ['benches/js/.cache/wpt_css', '../prettier/tests/format/css']) { const row = css?.sources.find((s) => s.origins[0]?.path === path); assert(row, `css ${path} is missing`); + assert.isNotEmpty(row.cells, path); for (const cell of row.cells) assert.isAbove(cell?.rejected ?? 0, 0, path); } }); + test('"tsv\'s 100% on test262 is a result" the report still carries', () => { + // no selector flags that cell, so nothing else holds the hand-written figure + const typescript = derive_conformance_matrices(conformance_json).find( + (m) => m.language === 'typescript' + ); + const row = typescript?.sources.find( + (s) => s.origins[0]?.path === 'benches/js/.cache/test262_files.json' + ); + const cell = row?.cells[typescript?.engines.findIndex((e) => e.name === 'tsv') ?? -1]; + assert(cell, 'tsv has no test262 cell'); + assert.isFalse(cell.selected); + assert.strictEqual(cell.rejected, 0); + }); + test('the CSS conformance note names the order the table shows', () => { // "PostCSS sitting above tsv is two grammars, not a gap", over a `parseCss` // reference tsv is a drop-in for @@ -55,7 +70,7 @@ describe('conformance prose reads the report', () => { assert.isAtMost(gap, 5, 'the accept sets differ by more than "a couple of files"'); }); - test('the byte check left "one pathologically deep TypeScript file" undigested, on tsv\'s rows', () => { + test('the byte check left "one file the report discloses" undigested, on tsv\'s rows', () => { // the conformance note excuses exactly one file from tsv's native/wasm byte // parity; a growing count is the check quietly covering less const ungraded = Object.entries(conformance_json.output_digest_ungraded ?? {}); diff --git a/src/test/conformance_data.shape.test.ts b/src/test/conformance_data.shape.test.ts index 1662f30..8c43073 100644 --- a/src/test/conformance_data.shape.test.ts +++ b/src/test/conformance_data.shape.test.ts @@ -39,7 +39,9 @@ describe('conformance.json shape', () => { test('every impl of a per-source slice reports the same slice total', () => { // a source row's file count and share are read off its impls' shared total - for (const [group, sources] of Object.entries(conformance_json.coverage_by_source ?? {})) { + const by_group = Object.entries(conformance_json.coverage_by_source ?? {}); + assert.isNotEmpty(by_group, 'the report carries no coverage_by_source'); + for (const [group, sources] of by_group) { for (const [source, by_impl] of Object.entries(sources)) { const totals = new Set(Object.values(by_impl).map((cell) => cell.total)); assert.strictEqual(totals.size, 1, `${group} ${source}: ${[...totals].join(', ')}`); @@ -190,9 +192,12 @@ describe('conformance matrices over the committed report', () => { }); test('only the sources every parser accepts in full are folded', () => { - // the folded row's label says so, and the TypeScript group is the one that has it + // the folded row's label says so const folded = matrices.flatMap((m) => m.sources.filter((s) => s.folded)); - assert.strictEqual(folded.length, 1); - for (const cell of folded[0]?.cells ?? []) assert.strictEqual(cell?.rejected, 0); + assert.isNotEmpty(folded, 'no matrix folds a row'); + for (const row of folded) { + assert.isNotEmpty(row.cells); + for (const cell of row.cells) assert.strictEqual(cell?.rejected, 0); + } }); }); diff --git a/src/test/conformance_data.test.ts b/src/test/conformance_data.test.ts index 85b7a72..39da16f 100644 --- a/src/test/conformance_data.test.ts +++ b/src/test/conformance_data.test.ts @@ -51,7 +51,7 @@ describe('derive_conformance_groups', () => { }); describe('derive_conformance_matrices', () => { - const TEST262 = 'benches/js/.cache/test262_files.json'; + const TS_REPO = 'benches/js/.cache/ts_repo_files.json'; const cell = (processed: number, total: number) => ({ processed, total }); const coverage = (name: string, group: string, processed: number, total: number) => entry({ name, group, files_processed: processed, files_total: total }); @@ -66,11 +66,11 @@ describe('derive_conformance_matrices', () => { ], corpus_sources: [ { - path: TEST262, + path: TS_REPO, files: 60, repo: { - url: 'https://github.com/tc39/test262', - slug: 'tc39/test262', + url: 'https://github.com/microsoft/TypeScript', + slug: 'microsoft/TypeScript', commit: '', subpath: '' } @@ -87,7 +87,7 @@ describe('derive_conformance_matrices', () => { 'tsv-wasm-json': cell(27, 30), tsc: cell(29, 30) }, - [TEST262]: { 'tsv-json': cell(60, 60), 'tsv-wasm-json': cell(60, 60), tsc: cell(59, 60) } + [TS_REPO]: { 'tsv-json': cell(59, 60), 'tsv-wasm-json': cell(59, 60), tsc: cell(60, 60) } }) ); assert.isEmpty(rest); @@ -103,18 +103,22 @@ describe('derive_conformance_matrices', () => { [97, 3, false] ] ); - const [test262, unknown] = matrix.sources; - assert(test262 && unknown, 'two source rows'); - assert.deepEqual(test262.origins, [ - { path: TEST262, label: 'test262', url: 'https://github.com/tc39/test262' } + const [ts_repo, unknown] = matrix.sources; + assert(ts_repo && unknown, 'two source rows'); + assert.deepEqual(ts_repo.origins, [ + { + path: TS_REPO, + label: "TypeScript compiler's cases", + url: 'https://github.com/microsoft/TypeScript' + } ]); - assert.strictEqual(test262.files, 60); - // tsv selected test262, so its full cell is construction; tsc's is a result + assert.strictEqual(ts_repo.files, 60); + // tsc selected its compiler's cases, so its full cell is construction; tsv's is a result assert.deepEqual( - test262.cells.map((c) => [c?.rejected, c?.selected]), + ts_repo.cells.map((c) => [c?.rejected, c?.selected]), [ - [1, false], - [0, true] + [0, true], + [1, false] ] ); // a path without a label or a corpus source still gets its row @@ -154,7 +158,7 @@ describe('derive_conformance_matrices', () => { const [lone] = derive_conformance_matrices( typescript_baseline({ '../a': { 'tsv-json': cell(5, 5), tsc: cell(5, 5) }, - [TEST262]: { 'tsv-json': cell(60, 60), tsc: cell(60, 60) } + [TS_REPO]: { 'tsv-json': cell(60, 60), tsc: cell(60, 60) } }) ); assert.deepEqual( From 1b4a0f6ad09bb41809f12813cf44fc435c30e30e Mon Sep 17 00:00:00 2001 From: Ryan Atkinson Date: Mon, 21 Sep 2026 17:45:31 -0400 Subject: [PATCH 187/218] wip --- src/routes/docs/conformance/+page.svelte | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/routes/docs/conformance/+page.svelte b/src/routes/docs/conformance/+page.svelte index f3a0f92..e398633 100644 --- a/src/routes/docs/conformance/+page.svelte +++ b/src/routes/docs/conformance/+page.svelte @@ -68,7 +68,8 @@ PostCSS sitting above tsv is two grammars, not a gap. The CSS reference is Svelte's parseCss, which tsv is a drop-in for and no validity oracle in either direction; PostCSS keeps selectors and at-rule preludes as unparsed strings, so it accepts - preprocessor syntax and malformed rules. + preprocessor syntax, malformed rules, and modern CSS parseCss doesn't + implement yet.

  • One column per engine, not per binding. That is exact for tsv, whose native and wasm rows From a725571872c402b4e86a0cf675af47fad18a091e Mon Sep 17 00:00:00 2001 From: Ryan Atkinson Date: Mon, 21 Sep 2026 18:03:26 -0400 Subject: [PATCH 188/218] wip --- src/routes/docs/benchmarks/+page.svelte | 130 ++++++++---------- .../benchmarks/BenchmarksCliSection.svelte | 30 ++-- src/routes/docs/benchmarks/benchmarks_cli.ts | 2 +- src/routes/docs/conformance/+page.svelte | 3 +- .../docs/conformance/conformance_data.ts | 3 +- src/test/benchmark_data.prose.test.ts | 24 ++-- 6 files changed, 82 insertions(+), 110 deletions(-) diff --git a/src/routes/docs/benchmarks/+page.svelte b/src/routes/docs/benchmarks/+page.svelte index 24623bf..216cb02 100644 --- a/src/routes/docs/benchmarks/+page.svelte +++ b/src/routes/docs/benchmarks/+page.svelte @@ -174,11 +174,11 @@ parser/formatter), Yuku (TypeScript/JS parser), swc (TypeScript/JS parser), dprint-typescript (TypeScript/JS - formatter), malva (CSS formatter, a third-party - plugin for dprint's host), and PostCSS (CSS parser). What - each parser accepts, as opposed to how fast, is measured on the - page. The parse charts anchor on the JS parsers tsv is a - drop-in for: Svelte's compiler (its template parser and parseCss) and + formatter), malva (CSS formatter), and + PostCSS (CSS parser). What each parser accepts, as opposed + to how fast, is measured on the page. The parse charts anchor + on the JS parsers tsv is a drop-in for: Svelte's compiler (its template parser and + parseCss) and acorn-typescript, the TypeScript parser the Svelte compiler uses.

    @@ -198,9 +198,7 @@

    Except in the CLI section, every timing here is in-process and one file at a time: each tool parses or formats the corpus sequentially, isolating engine speed from multi-core parallelism. - The corpus is {format_count(corpus_counts.files)} files of real-world code — Svelte's own - repos (svelte, kit, svelte.dev), the fuz.dev repos, - and a few of the author's personal SvelteKit apps and sites, itemized under + The corpus is {format_count(corpus_counts.files)} files of real-world code, itemized under Corpus. On that basis:

      @@ -210,9 +208,8 @@ ~{format_ts_vs_biome} faster than Biome (wasm-vs-wasm).
    • - Formatting Svelte, tsv is ~{format_svelte_vs_prettier} faster than Prettier (which Oxfmt's - Svelte path delegates to internally) and ~{format_svelte_vs_biome} faster than Biome, same - pairings. + Formatting Svelte, tsv is ~{format_svelte_vs_prettier} faster than Prettier and + ~{format_svelte_vs_biome} faster than Biome, same pairings.
    • Formatting CSS, it's ~{format_css_vs_oxfmt} faster than Oxfmt and ~{format_css_vs_biome} @@ -300,7 +297,11 @@ @@ -506,21 +496,15 @@ rsvelte's carries the Svelte compiler plus svelte2tsx, HMR diffing and a resolver. Read them as what those addons ship, not as parser size.
    • -
    • - Biome bundles a parser, formatter, and linter for many languages; only its wasm build is - included, since its native engine ships as a CLI binary rather than a library. -
    • +
    • Biome bundles a parser, formatter, and linter for many languages.
    • The {OXC_FULL_LABEL} entry under Full toolchain sums oxc's separate parser (TypeScript and JS/JSX only) and formatter packages, since together they're the closest - equivalent to tsv's single parse+format build. -
    • -
    • - That sum is a little unfair to oxc: oxfmt statically links its own copy of the oxc parser, - so the two builds count the parser twice, and the summed gz is two gzip - streams rather than one. The other way, the oxfmt addon is more than a - formatter for tsv's three languages — it also formats JSON and YAML, sorts imports, and - carries a language server and the CLI itself. + equivalent to tsv's single parse+format build. That sum is a little unfair to oxc: oxfmt + statically links its own copy of the oxc parser, so the two builds count the parser twice. + The other way, the oxfmt addon is more than a formatter for tsv's three + languages — it also formats JSON and YAML, sorts imports, and carries a language server + and the CLI itself.
    • Every entry is one artifact file, which undercounts in both directions. @@ -544,10 +528,9 @@ format itself.
    • - dprint (wasm) and malva (wasm) are two plugins for the same - dprint formatter host — TypeScript/JS and CSS respectively — and neither exposes a parser, - so both sit under Formatter beside tsv's format-only wasm build. That build does Svelte, - TypeScript/JS and CSS in one artifact, so each gap there is scope before it's engine. + dprint (wasm) and malva (wasm) expose no parser, so both sit + under Formatter beside tsv's format-only wasm build. That build does Svelte, TypeScript/JS + and CSS in one artifact, so each gap there is scope before it's engine.
    @@ -584,18 +567,16 @@

    Nothing pins the process to a core or holds the clock steady — an unpinned run on a laptop CPU - — so thermal drift is a live possibility, not a formality. The tsv-wasm rows run - the full parse+format build, not the smaller format-only or parse-only ones. + — so thermal drift is a live possibility, not a formality.

    - Sweep counts differ widely by row because each row gets a time budget rather than a count: at - least {format_count_maybe(sweeps.floor)} sweeps{canonical_floor_note}, otherwise as many as - fit a few seconds, so the multi-second rows stop near that floor. After outlier cleaning the - report keeps from {format_count_maybe(sweeps.sample_size_min)} to - {format_count_maybe(sweeps.sample_size_max)} timings per row. A low cv over a handful of - sweeps is thinner evidence of quiet than the same cv over hundreds, so the instability check - behind the headline ratios proves less for the slow rows that stop there — Prettier among - them, the denominator of every ratio in the summary table. + Each row gets a time budget rather than a sweep count: at least + {format_count_maybe(sweeps.floor)} sweeps{canonical_floor_note}, otherwise as many as fit a + few seconds, so the multi-second rows stop near that floor. After outlier cleaning, rows keep + from {format_count_maybe(sweeps.sample_size_min)} to + {format_count_maybe(sweeps.sample_size_max)} timings. A low cv over a handful of sweeps is + thinner evidence than the same cv over hundreds, so the instability check proves less for the + slow rows — Prettier among them, the denominator of every ratio in the summary table.

    @@ -620,11 +601,10 @@ files are rare in this ecosystem{corpus_counts.harvested_css && corpus.css ? ` — ${format_count(corpus_counts.harvested_css)} of the ${format_count(corpus.css)} CSS entries in the count above` - : ''}. The harness regenerates that harvest from the snapshot rather than reading a file in - it, and the same bytes appear in the Svelte rows (rows are never summed). Test files count as - real code and stay in; fixture files (formatter test suites, and fixture subtrees inside the - measured repos) are excluded — deliberately tricky edge cases measure conformance, not typical - throughput, and the page covers them. + : ''}. Test files count as real code and stay in; fixture files (formatter test suites, and + fixture subtrees inside the measured repos) are excluded — deliberately tricky edge cases + measure conformance, not typical throughput, and the page + covers them.

    Two caveats. The corpus is dominated by the author's own code plus Svelte's, the same code tsv @@ -649,12 +629,10 @@ above are the Node run. The native entry differs by runtime: Node and Bun load tsv's N-API addon, Deno its C-FFI library. They share code but cross a different binding boundary, so a per-runtime delta on the same row is a runtime effect — the JS engine, the host's N-API - implementation, or the binding boundary — not a difference in tsv's algorithms. Nor is it - quite one binary: the same engine and settings, but the N-API build keeps panic unwinding - where the FFI one aborts. A delta the report finds inside the two measurements' combined noise - is marked ≈ in the tables and reads as parity, not an effect. It can't see - variance between whole runs: Bun's allocation-heavy JS rows (Prettier, PostCSS) have sat at - two levels ~10–14% apart. + implementation, or the binding boundary — not a difference in tsv's algorithms. A delta the + report finds inside the two measurements' combined noise is marked ≈ in the + tables and reads as parity, not an effect. It can't see variance between whole runs: Bun's + allocation-heavy JS rows (Prettier, PostCSS) have sat at two levels ~10–14% apart.

  • On the large single file, where a Node bin's fixed launch cost weighs most against a short @@ -146,10 +145,8 @@
  • The delivery table is tsv against tsv, on one file. Through @fuzdev/tsv's Node - dispatcher (npx's own resolution isn't counted) the same binary takes ~{delivery_npm_wall} - as long — Node starting up, the dispatcher resolving and spawning the binary, and Node - staying resident until it exits. That launch cost is fixed, so its share shrinks on a real - repo, where the dispatcher takes ~{npm_ts_cost} as long. + dispatcher the same binary takes ~{delivery_npm_wall} as long. That launch cost is fixed, so + its share shrinks on a real repo, where the dispatcher takes ~{npm_ts_cost} as long. @fuzdev/tsv-wasm — the package for platforms without a prebuilt binary, not the default — runs the same CLI over a WASM engine inside Node at ~{wasm_wall} the time and ~{wasm_memory} the memory of the @@ -168,8 +165,7 @@
  • The tools are pinned but one corpus isn't: the TypeScript repo is Outline at its default branch's head, so its file set moves whenever it is re-cloned. Every formatter is scoped to - the JSX-free .ts/.js family — the others by their config, tsv - (which has none) by the extensions it walks — leaving out the .tsx and + the JSX-free .ts/.js family, leaving out the .tsx and .jsx tsv can't parse, and the preflight file-count check holds the tools that report a count to the same set. The single file (the TypeScript compiler's parser.ts at a pinned release) and the Svelte corpus (a pinned diff --git a/src/routes/docs/benchmarks/benchmarks_cli.ts b/src/routes/docs/benchmarks/benchmarks_cli.ts index eb6f6c4..f2ed296 100644 --- a/src/routes/docs/benchmarks/benchmarks_cli.ts +++ b/src/routes/docs/benchmarks/benchmarks_cli.ts @@ -176,7 +176,7 @@ const SCENARIO_COPY: Record = { [CLI_SVELTE_KEY]: { heading: 'Svelte corpus', description: - 'Two Rust Svelte-native formatters head-to-head on a third-party .svelte corpus, rsvelte-fmt configured to tsv’s fixed style so both do comparable line-break work. Its time includes the oxfmt it spawns for the files it doesn’t format itself — none here, but that is how it ships — and the harness pins its style cache and oxfmt daemon off. rsvelte-fmt 0.7.x aborts nondeterministically on this corpus under the harness’s preflight, a condition the harness keeps rather than works around, and it never retries: a run is published as it ended, complete or aborted.', + 'Two Rust Svelte-native formatters head-to-head on a third-party .svelte corpus, rsvelte-fmt configured to tsv’s fixed style so both do comparable line-break work. Its time includes the oxfmt it spawns for the files it doesn’t format itself. rsvelte-fmt 0.7.x aborts nondeterministically on this corpus under the harness’s preflight, and the harness never retries: a run is published as it ended, complete or aborted.', tsv_only: false }, [CLI_DELIVERY_KEY]: { diff --git a/src/routes/docs/conformance/+page.svelte b/src/routes/docs/conformance/+page.svelte index e398633..bdd617d 100644 --- a/src/routes/docs/conformance/+page.svelte +++ b/src/routes/docs/conformance/+page.svelte @@ -54,8 +54,7 @@ A greyed 100% marks the parser that chose a source, so reads 100% on it by construction: svelte/compiler on the Svelte set (the files it rejects are excluded, so the others read as drop-in fidelity against it) and tsc{tsc_label} on its - compiler's cases. tsv's 100% on test262 is a result: the suite's own metadata picks the - tests, less the Annex B grammar tsv declines (see + compiler's cases. tsv's 100% on test262 is a result, not a selection (see Corpus).
  • diff --git a/src/routes/docs/conformance/conformance_data.ts b/src/routes/docs/conformance/conformance_data.ts index 185d41f..deb709f 100644 --- a/src/routes/docs/conformance/conformance_data.ts +++ b/src/routes/docs/conformance/conformance_data.ts @@ -204,7 +204,8 @@ const to_conformance_cell = ( }); // a source no engine selected and none rejects any of says nothing a reader can -// compare, so two or more of them fold into one row +// compare, so two or more of them fold into one row; a group with a `*` selector +// (Svelte) never folds, so its rows keep showing which 100% is by construction const is_foldable = (row: ConformanceSourceRow): boolean => row.cells.some((cell) => cell !== undefined) && row.cells.every((cell) => cell === undefined || (!cell.selected && cell.rejected === 0)); diff --git a/src/test/benchmark_data.prose.test.ts b/src/test/benchmark_data.prose.test.ts index 012891e..84d3aed 100644 --- a/src/test/benchmark_data.prose.test.ts +++ b/src/test/benchmark_data.prose.test.ts @@ -135,7 +135,7 @@ describe('prose ratios resolve', () => { }); test('oxfmt formats Svelte at Prettier speed, as the note says it delegates', () => { - // "for Svelte it delegates to Prettier internally" — if a future oxfmt grows its + // "for Svelte it delegates to a Prettier it bundles" — if a future oxfmt grows its // own Svelte path the two rows will part ways and the note is stale const ratio = benchmark_speedup(benchmarks_json, 'format/svelte', 'oxfmt', 'prettier'); assert.isDefined(ratio); @@ -170,7 +170,7 @@ describe('prose ratios resolve', () => { test('the pairings the copy calls payload-matched are, and the ones it excludes are not', () => { // The page names four pairings as comparing the same PRODUCT and rules two out - // ("swc ... isn't payload-matched to either tsv wire", "the `no-locs` entries + // ("swc's own AST shape ... matches neither tsv wire", "the `no-locs` entries // are the one payload-matched pairing" for oxc-parser). Those are claims about // the report's `payload` tiers, so read them off it rather than trusting prose. const entry = (group: string, name: string) => { @@ -370,8 +370,7 @@ describe('prose ratios resolve', () => { }); test('the dispatcher overhead is the "fixed cost" the delivery note calls it', () => { - // "a fixed cost of ~A–B ms in every scenario here, so its share shrinks against - // a real repo" — fixed means the absolute figure barely moves between a one-file + // "That launch cost is fixed, so its share shrinks on a real repo" — fixed means the absolute figure barely moves between a one-file // run and a repo, so the span must stay tight around a positive cost const overhead = cli_tsv_npm_overhead_ms_range(); assert.isDefined(overhead); @@ -386,7 +385,7 @@ describe('prose ratios resolve', () => { ); assert(wasm, 'delivery scenario has no tsv-wasm row'); assert.isAbove(wasm.cpu_ms, wasm.wall_ms); - // the Svelte copy: "rsvelte-fmt 0.7.x’s check mode crashes nondeterministically on this corpus" + // the Svelte copy: "rsvelte-fmt 0.7.x aborts nondeterministically on this corpus" const rsvelte_version = benchmarks_cli.versions['rsvelte-fmt']; assert.isDefined(rsvelte_version); assert.match(rsvelte_version, /^0\.7\./, 'the Svelte copy names rsvelte-fmt 0.7.x'); @@ -452,7 +451,7 @@ describe('prose ratios resolve', () => { }); test('the run-order note holds: every scenario runs the dispatcher row, then bare tsv, last', () => { - // "Every scenario here puts the bare tsv binary last, with its Node dispatcher + // "Every scenario tsv runs in puts the bare binary last, with its Node dispatcher // row just before it" — hyperfine reports commands in the order it ran them, // and the generated timings keep that order. An aborted scenario has no timings // to order, so its preflight rows, which the harness runs in the same order, stand in. @@ -493,7 +492,7 @@ describe('prose ratios resolve', () => { }); test("the parse note on oxc-parser's wasm row running an older release reads the report", () => { - // "Its wasm row runs an older release than its native row ... so the wasm-vs-wasm + // "oxc-parser's wasm row runs an older release than its native row ... so the wasm-vs-wasm // pairing crosses oxc versions" — the bindings re-aligning makes the note a fiction const { versions } = benchmarks_json; assert.isDefined(versions.oxc_parser_wasm); @@ -527,19 +526,18 @@ describe('prose ratios resolve', () => { } }); - test('the corpus repos the TLDR names are present', () => { - // "Svelte's own repos (svelte, kit, svelte.dev), the fuz.dev repos, and a few - // of the author's personal SvelteKit sites" — gate the names so the sentence - // can't outlive the corpus + test('the corpus repos the Corpus section names are present', () => { + // "the fuz.dev ecosystem ... and upstream framework source (Svelte, SvelteKit, and + // the svelte.dev site)" — gate the names so the sentence can't outlive the corpus const slugs = new Set( (benchmarks_json.corpus_sources ?? []).map((s) => s.repo?.slug).filter(Boolean) ); for (const slug of ['sveltejs/svelte', 'sveltejs/kit', 'sveltejs/svelte.dev']) { - assert.ok(slugs.has(slug), `TLDR names ${slug} but the corpus lacks it`); + assert.ok(slugs.has(slug), `the page names ${slug} but the corpus lacks it`); } assert.ok( [...slugs].some((slug) => slug?.startsWith('fuzdev/')), - 'TLDR names the fuz.dev repos but the corpus has none' + 'the page names the fuz.dev repos but the corpus has none' ); }); }); From a988006e1bbaef46c06af0c5c4992b8a8baf3f4d Mon Sep 17 00:00:00 2001 From: Ryan Atkinson Date: Tue, 22 Sep 2026 07:53:27 -0400 Subject: [PATCH 189/218] wip --- src/routes/docs/introduction/+page.svelte | 37 ++++++++++++++--------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/src/routes/docs/introduction/+page.svelte b/src/routes/docs/introduction/+page.svelte index 5e0fc9c..f314ddf 100644 --- a/src/routes/docs/introduction/+page.svelte +++ b/src/routes/docs/introduction/+page.svelte @@ -41,10 +41,16 @@ reconstruct_locations(ast, 'const x = 1;');`; tsv is a toolchain for TypeScript/JS, CSS, and Svelte in Rust. It ships a formatter that closely follows Prettier + prettier-plugin-svelte, and a - drop-in replacement for Svelte's parser + + drop-in for Svelte's parser + acorn + acorn-typescript.

    +

    + tsv aims to simplify its covered domains and stay lean, and so it makes opinionated choices. + The formatter has a single non-configurable style, using Svelte's Prettier config. Among other + benefits this means tsv doesn't depend on a JS runtime, which it would need to resolve configs + like Prettier. +

    Compared to Oxc, Biome, and SWC, tsv is a set of focused tools, not an extensible language platform, so the focus is Web standards + Svelte and there's no support for JSX/SCSS/etc. @@ -53,30 +59,33 @@ reconstruct_locations(ast, 'const x = 1;');`;

    Compared to rsvelte, tsv has its own - TS/JS/CSS parsers instead of using Oxc, and rsvelte additionally has a compiler and - linter/typechecker integration (tsv has some in-progress work here, scope unknown, may never - ship). + TS/JS/CSS parsers instead of using Oxc, and rsvelte additionally has a Svelte compiler and + linter/typechecker integration (the full toolchain; tsv has some in-progress work here, scope + unknown and may never ship).

    tsv prioritizes, in order:

    1. correctness (spec conformance for HTML/CSS/JS, fidelity to Svelte and TypeScript)
    2. speed
    3. binary size and memory usage
    4. -
    5. extensibility (valued but deprioritized), modularity, and reusability
    6. +
    7. extensibility, modularity, reusability

    - See the for measurements. Compared to Oxc and Biome, tsv is - smaller and faster at formatting its supported languages, and faster than Oxc at parsing - TypeScript on the same span-only AST payload (Biome exposes no parser to compare), but lacks - their features and broad language support. One reason for tsv to exist is to help find the - performance bonuses left on the table in the Web ecosystem's increasingly-native + Staying simple is an over-arching goal, and sometimes at odds with flexibility. Feedback is + welcome to help navigate these tradeoffs. +

    +

    + See the for measurements. Compared to Oxc/oxfmt and Biome, tsv + is smaller and faster at parsing and formatting its supported languages, but lacks their + features, extensibility, and broad language support. One reason for tsv to exist is to help + find the performance bonuses left on the table in the Web ecosystem's increasingly-native implementations.

    tsv is near production-ready, with a long tail of rare bugs (and numerous fixes to bugs in - Prettier and prettier-plugin-svelte). Reports and feedback are appreciated. See the - issues and - discussions. + acorn-typescript/Prettier/prettier-plugin-svelte), and APIs may still change. Reports and + feedback are appreciated. See the issues + and discussions.

    AI disclosure: this codebase is mostly LLM-generated, and the usual caveats apply. It's a @@ -110,7 +119,7 @@ reconstruct_locations(ast, 'const x = 1;');`; content={'npm i -D @fuzdev/tsv\nnpx tsv format src\nnpx tsv parse src/foo.svelte'} />

    - The right binary installs automatically. Prebuilt for Linux (x64, arm64, and x64 musl), + The right binary installs automatically. Prebuilt for Linux (x64 gnu and musl, arm64 gnu), macOS (arm64 and x64), and Windows x64 — anywhere else, use the WASM build below. The tsv command is tsv's native CLI binary, shipped in the platform package alongside the addon, with multi-file parallelism (--jobs). From baefdb0093548fd16e33500bfecf3a7342ea63da Mon Sep 17 00:00:00 2001 From: Ryan Atkinson Date: Tue, 22 Sep 2026 08:06:44 -0400 Subject: [PATCH 190/218] wip --- src/routes/docs/introduction/+page.svelte | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/routes/docs/introduction/+page.svelte b/src/routes/docs/introduction/+page.svelte index f314ddf..659f543 100644 --- a/src/routes/docs/introduction/+page.svelte +++ b/src/routes/docs/introduction/+page.svelte @@ -119,10 +119,10 @@ reconstruct_locations(ast, 'const x = 1;');`; content={'npm i -D @fuzdev/tsv\nnpx tsv format src\nnpx tsv parse src/foo.svelte'} />

    - The right binary installs automatically. Prebuilt for Linux (x64 gnu and musl, arm64 gnu), - macOS (arm64 and x64), and Windows x64 — anywhere else, use the WASM build below. The - tsv command is tsv's native CLI binary, shipped in the platform package - alongside the addon, with multi-file parallelism (--jobs). + Prebuilt binaries cover Linux (x64 gnu and musl, arm64 gnu), macOS (arm64 and x64), and + Windows x64 — anywhere else, use the WASM build below. The tsv command is tsv's + native CLI binary, shipped in the platform package alongside the addon, with multi-file + parallelism (--jobs).

    The same CLI binaries are also attached to each From 73b104c7494e7cec7da21b905c311327bcfd1bb4 Mon Sep 17 00:00:00 2001 From: Ryan Atkinson Date: Tue, 22 Sep 2026 08:10:20 -0400 Subject: [PATCH 191/218] wip --- src/routes/docs/benchmarks/+page.svelte | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/routes/docs/benchmarks/+page.svelte b/src/routes/docs/benchmarks/+page.svelte index 216cb02..c9f4015 100644 --- a/src/routes/docs/benchmarks/+page.svelte +++ b/src/routes/docs/benchmarks/+page.svelte @@ -612,9 +612,9 @@ this corpus", not a universal figure; the CLI section's Svelte corpus adds those third-party libraries, and shares only its kit and svelte.dev trees with this one. And CSS is the weakest sample: {format_count_maybe(corpus_counts.standalone_css)} standalone files plus the - per-collection <style> concatenations, which keep the one level of indent - they carried inside their tags — so every tool re-indents them, and much of the CSS here - measures a full re-indent rather than the already-formatted steady state. + per-collection <style> extractions from Svelte components, which keep the + one level of indent they carried inside their tags — so every tool re-indents them, and much + of the CSS here measures a full re-indent rather than the already-formatted steady state.

    Each source links its upstream at the commit the snapshot vendored.

    From c7dad1ceec47a64fc8a190e0520370cc881bf346 Mon Sep 17 00:00:00 2001 From: Ryan Atkinson Date: Tue, 22 Sep 2026 08:13:21 -0400 Subject: [PATCH 192/218] wip --- src/routes/docs/benchmarks/+page.svelte | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/routes/docs/benchmarks/+page.svelte b/src/routes/docs/benchmarks/+page.svelte index c9f4015..4129a52 100644 --- a/src/routes/docs/benchmarks/+page.svelte +++ b/src/routes/docs/benchmarks/+page.svelte @@ -612,9 +612,7 @@ this corpus", not a universal figure; the CLI section's Svelte corpus adds those third-party libraries, and shares only its kit and svelte.dev trees with this one. And CSS is the weakest sample: {format_count_maybe(corpus_counts.standalone_css)} standalone files plus the - per-collection <style> extractions from Svelte components, which keep the - one level of indent they carried inside their tags — so every tool re-indents them, and much - of the CSS here measures a full re-indent rather than the already-formatted steady state. + per-collection <style> extractions from Svelte components.

    Each source links its upstream at the commit the snapshot vendored.

    From 2ad6ded5faf93410f7cf86963522436f594818da Mon Sep 17 00:00:00 2001 From: Ryan Atkinson Date: Tue, 22 Sep 2026 09:40:44 -0400 Subject: [PATCH 193/218] wip --- src/routes/docs/benchmarks/+page.svelte | 53 +++++++++---------- .../docs/benchmarks/BenchmarksBar.svelte | 3 +- .../benchmarks/BenchmarksCliSection.svelte | 12 ++--- src/routes/docs/benchmarks/benchmarks_cli.ts | 23 ++++---- src/routes/docs/introduction/+page.svelte | 12 +++-- src/routes/docs/playground/Playground.svelte | 4 +- src/test/benchmark_data.prose.test.ts | 20 +++---- 7 files changed, 63 insertions(+), 64 deletions(-) diff --git a/src/routes/docs/benchmarks/+page.svelte b/src/routes/docs/benchmarks/+page.svelte index 4129a52..e02a46d 100644 --- a/src/routes/docs/benchmarks/+page.svelte +++ b/src/routes/docs/benchmarks/+page.svelte @@ -15,8 +15,8 @@ import { benchmarks_cross_runtime_json } from './benchmarks_cross_runtime.ts'; import { cli_scenario_find, - cli_speedup_vs_tsv, - cli_speedup_vs_tsv_npm, + cli_ratio_vs_tsv, + cli_ratio_vs_tsv_npm, CLI_TS_REPO_KEY, CLI_SVELTE_KEY } from './benchmarks_cli.ts'; @@ -145,42 +145,41 @@ // tools' npm bins is the like-for-like footing the claims lead with; the bare-binary // ratios follow as what the binary does without a Node launcher in front. const cli_npm_ratio = (scenario: string, label: string) => - format_ratio_approx(cli_speedup_vs_tsv_npm(scenario, label, 'wall_ms')); + format_ratio_approx(cli_ratio_vs_tsv_npm(scenario, label, 'wall_ms')); const cli_npm_ts_vs_oxfmt = cli_npm_ratio(CLI_TS_REPO_KEY, 'oxfmt'); const cli_npm_ts_vs_biome = cli_npm_ratio(CLI_TS_REPO_KEY, 'biome'); const cli_ts_wall_vs_oxfmt = format_ratio_approx( - cli_speedup_vs_tsv(CLI_TS_REPO_KEY, 'oxfmt', 'wall_ms') + cli_ratio_vs_tsv(CLI_TS_REPO_KEY, 'oxfmt', 'wall_ms') ); const cli_ts_wall_vs_biome = format_ratio_approx( - cli_speedup_vs_tsv(CLI_TS_REPO_KEY, 'biome', 'wall_ms') + cli_ratio_vs_tsv(CLI_TS_REPO_KEY, 'biome', 'wall_ms') ); // The Svelte head-to-head is published aborted whenever rsvelte-fmt's // nondeterministic crash hits the harness's preflight, so its ratios can be // absent while the scenario itself is present — the prose covers both cases. const cli_svelte = cli_scenario_find(CLI_SVELTE_KEY); - const cli_svelte_timed = cli_speedup_vs_tsv(CLI_SVELTE_KEY, 'rsvelte-fmt', 'wall_ms') != null; + const cli_svelte_timed = cli_ratio_vs_tsv(CLI_SVELTE_KEY, 'rsvelte-fmt', 'wall_ms') != null; const cli_svelte_npm_wall = cli_npm_ratio(CLI_SVELTE_KEY, 'rsvelte-fmt');

    - tsv is a toolchain for TypeScript/JS, CSS, and Svelte in Rust; after correctness, its - priorities are performance and efficiency. This page measures it against - Prettier, which tsv closely follows, and against - Oxc and Biome, similar tools - with more features and wider language support (tsv doesn't support JSX/TSX/SCSS/etc.). Also - compared: rsvelte (Svelte - parser/formatter), Yuku (TypeScript/JS parser), - swc (TypeScript/JS parser), + tsv is a toolchain with parsers and formatters for TypeScript/JS, CSS, and Svelte in Rust. + After correctness, tsv prioritizes performance and efficiency, and this page explores those + measurements. For parser correctness see the page. +

    +

    + This data here compares tsv to Prettier, which tsv closely + follows, and to Oxc and + Biome, which are similar tools with more features and wider + language support - tsv doesn't support JSX/TSX/SCSS/etc, and it supports only one canonical + formatting style. Also compared: rsvelte + (Svelte parser/formatter), Yuku (TypeScript/JS parser), + SWC (TypeScript/JS parser), dprint-typescript (TypeScript/JS - formatter), malva (CSS formatter), and - PostCSS (CSS parser). What each parser accepts, as opposed - to how fast, is measured on the page. The parse charts anchor - on the JS parsers tsv is a drop-in for: Svelte's compiler (its template parser and - parseCss) and - acorn-typescript, the TypeScript - parser the Svelte compiler uses. + formatter), Malva (CSS formatter), and + PostCSS (CSS parser).

    @@ -197,9 +196,9 @@

    Except in the CLI section, every timing here is in-process and one file at a time: each tool - parses or formats the corpus sequentially, isolating engine speed from multi-core parallelism. - The corpus is {format_count(corpus_counts.files)} files of real-world code, itemized under - Corpus. On that basis: + parses or formats the corpus sequentially, isolating base engine speed from multi-core + parallelism. The corpus is {format_count(corpus_counts.files)} files of real-world code, + itemized under Corpus. On that basis:

    • @@ -216,7 +215,7 @@ faster than Biome, same pairings.
    • - End to end as a CLI, in a + End to end as a CLI, measured in a fork of Oxc's bench-formatter : on the JSX-free subset of a real TypeScript repo, with every tool launched through its @@ -360,7 +359,7 @@ dprint-plugin-typescript, the engine deno fmt runs for TypeScript and JS, loaded in-process as its wasm plugin. It rejects CSS and Svelte, and no dprint markup plugin is wired in, so it has no Svelte row - and its CSS slot goes to malva, a + and its CSS slot goes to Malva, a third-party CSS plugin for the same host. This times the engine, not the deno fmt CLI.
    • @@ -528,7 +527,7 @@ format itself.
    • - dprint (wasm) and malva (wasm) expose no parser, so both sit + dprint (wasm) and Malva (wasm) expose no parser, so both sit under Formatter beside tsv's format-only wasm build. That build does Svelte, TypeScript/JS and CSS in one artifact, so each gap there is scope before it's engine.
    • diff --git a/src/routes/docs/benchmarks/BenchmarksBar.svelte b/src/routes/docs/benchmarks/BenchmarksBar.svelte index 9c845d0..dadbab3 100644 --- a/src/routes/docs/benchmarks/BenchmarksBar.svelte +++ b/src/routes/docs/benchmarks/BenchmarksBar.svelte @@ -85,8 +85,7 @@ align-items: center; /* rows sit flush (no inter-row gap) with a little padding, so the anchor * highlight reads as one contiguous, full-height band per row */ - padding-block: var(--space_xs); - padding-right: var(--space_xs); + padding: var(--space_xs); } .bar-row.disabled { opacity: 0.6; diff --git a/src/routes/docs/benchmarks/BenchmarksCliSection.svelte b/src/routes/docs/benchmarks/BenchmarksCliSection.svelte index 713895a..56dce7d 100644 --- a/src/routes/docs/benchmarks/BenchmarksCliSection.svelte +++ b/src/routes/docs/benchmarks/BenchmarksCliSection.svelte @@ -5,8 +5,8 @@ import { benchmarks_cli, cli_memory_ratio_range, - cli_speedup_vs_tsv, - cli_speedup_vs_tsv_npm, + cli_ratio_vs_tsv, + cli_ratio_vs_tsv_npm, cli_tsv_npm_memory_mb, cli_tsv_npm_overhead_ms_range, cli_node_startup_ms, @@ -38,9 +38,9 @@ // like-for-like rows, which the claims lead with; the bare-binary ratios follow // as what the binary does without a Node launcher in front. const npm_ratio = (scenario: string, label: string, metric: CliMetric = 'wall_ms') => - format_ratio_approx(cli_speedup_vs_tsv_npm(scenario, label, metric)); + format_ratio_approx(cli_ratio_vs_tsv_npm(scenario, label, metric)); const bare_ratio = (scenario: string, label: string, metric: CliMetric) => - format_ratio_approx(cli_speedup_vs_tsv(scenario, label, metric)); + format_ratio_approx(cli_ratio_vs_tsv(scenario, label, metric)); const npm_ts_vs_oxfmt = npm_ratio(CLI_TS_REPO_KEY, 'oxfmt'); const npm_ts_vs_biome = npm_ratio(CLI_TS_REPO_KEY, 'biome'); const npm_ts_cpu_vs_oxfmt = npm_ratio(CLI_TS_REPO_KEY, 'oxfmt', 'cpu_ms'); @@ -93,9 +93,7 @@ @fuzdev/tsv, what npx tsv runs, launching the native binary as Biome's and rsvelte-fmt's bins do. tsv runs the binary directly from the platform package, skipping Node: what the - binary costs on its own. Tables facing other tools start their ratios against the dispatcher - row; the last table is tsv against itself, anchored on the bare binary — what the Node - dispatcher and the WASM package each add. + binary costs on its own.

    -

    On Node.js (22+) and Bun, tsv installs as a native addon with prebuilt binaries:

    +

    + tsv is published to npm as + @fuzdev/tsv with native + binaries: +

    - Prebuilt binaries cover Linux (x64 gnu and musl, arm64 gnu), macOS (arm64 and x64), and - Windows x64 — anywhere else, use the WASM build below. The tsv command is tsv's - native CLI binary, shipped in the platform package alongside the addon, with multi-file - parallelism (--jobs). + The native package covers Linux (x64 gnu and musl, arm64 gnu), macOS (arm64 and x64), and + Windows x64 — anywhere else, use the WASM build below.

    The same CLI binaries are also attached to each diff --git a/src/routes/docs/playground/Playground.svelte b/src/routes/docs/playground/Playground.svelte index c34ea5e..282d12c 100644 --- a/src/routes/docs/playground/Playground.svelte +++ b/src/routes/docs/playground/Playground.svelte @@ -129,9 +129,9 @@ {:else if error}

    {error}

    {:else} -

    formatted

    +

    formatted:

    -

    AST

    +

    AST:

    {#if ast?.error} diff --git a/src/test/benchmark_data.prose.test.ts b/src/test/benchmark_data.prose.test.ts index 84d3aed..ac71848 100644 --- a/src/test/benchmark_data.prose.test.ts +++ b/src/test/benchmark_data.prose.test.ts @@ -10,8 +10,8 @@ import { cli_label_is_tsv, cli_memory_ratio_range, cli_scenario_find, - cli_speedup_vs_tsv, - cli_speedup_vs_tsv_npm, + cli_ratio_vs_tsv, + cli_ratio_vs_tsv_npm, cli_tsv_npm_memory_mb, cli_tsv_npm_overhead_ms_range, cli_node_startup_ms, @@ -232,7 +232,7 @@ describe('prose ratios resolve', () => { [CLI_TSV_WASM_LABEL, 'wall_ms'], [CLI_TSV_WASM_LABEL, 'memory_mb'] ] as const) { - const ratio = cli_speedup_vs_tsv(CLI_DELIVERY_KEY, label, metric); + const ratio = cli_ratio_vs_tsv(CLI_DELIVERY_KEY, label, metric); assert.isDefined(ratio, `${CLI_DELIVERY_KEY}: ${label} ${metric}`); // the copy reads "takes ~Nx as long" / "~Nx the memory", so each must exceed 1 assert_reads_faster(ratio, `${CLI_DELIVERY_KEY}: ${label} ${metric}`); @@ -246,7 +246,7 @@ describe('prose ratios resolve', () => { // every one must resolve or a sentence prints with a hole in it. for (const key of [CLI_SINGLE_FILE_KEY, CLI_TS_REPO_KEY]) { for (const label of ['oxfmt', 'biome']) { - const ratio = cli_speedup_vs_tsv_npm(key, label, 'wall_ms'); + const ratio = cli_ratio_vs_tsv_npm(key, label, 'wall_ms'); assert.isDefined(ratio, `${key}: ${label}`); assert_reads_faster(ratio, `${key}: ${label}`); } @@ -260,8 +260,8 @@ describe('prose ratios resolve', () => { assert.isAbove(memory.min, 1); // "~Nx on the TypeScript repo": the dispatcher's own cost there, which the // delivery note says shrinks against the one-file figure - const repo_cost = cli_speedup_vs_tsv(CLI_TS_REPO_KEY, CLI_TSV_NPM_LABEL, 'wall_ms'); - const file_cost = cli_speedup_vs_tsv(CLI_DELIVERY_KEY, CLI_TSV_NPM_LABEL, 'wall_ms'); + const repo_cost = cli_ratio_vs_tsv(CLI_TS_REPO_KEY, CLI_TSV_NPM_LABEL, 'wall_ms'); + const file_cost = cli_ratio_vs_tsv(CLI_DELIVERY_KEY, CLI_TSV_NPM_LABEL, 'wall_ms'); assert.isDefined(repo_cost); assert.isDefined(file_cost); assert_reads_faster(repo_cost, `${CLI_TS_REPO_KEY}: dispatcher cost`); @@ -270,8 +270,8 @@ describe('prose ratios resolve', () => { // aborted, but the copy quotes the dispatcher ratio wherever it quotes the // bare-binary one, so the two must resolve together for (const metric of ['wall_ms', 'memory_mb'] as const) { - const ratio = cli_speedup_vs_tsv_npm(CLI_SVELTE_KEY, 'rsvelte-fmt', metric); - const bare = cli_speedup_vs_tsv(CLI_SVELTE_KEY, 'rsvelte-fmt', metric); + const ratio = cli_ratio_vs_tsv_npm(CLI_SVELTE_KEY, 'rsvelte-fmt', metric); + const bare = cli_ratio_vs_tsv(CLI_SVELTE_KEY, 'rsvelte-fmt', metric); assert.strictEqual(ratio !== undefined, bare !== undefined, `${CLI_SVELTE_KEY}: ${metric}`); if (ratio !== undefined) assert_reads_faster(ratio, `${CLI_SVELTE_KEY}: ${metric}`); } @@ -314,9 +314,9 @@ describe('prose ratios resolve', () => { }; for (const label of ['oxfmt', 'biome']) { const npm = (metric: 'wall_ms' | 'cpu_ms') => - defined(cli_speedup_vs_tsv_npm(CLI_TS_REPO_KEY, label, metric), `${label} ${metric}`); + defined(cli_ratio_vs_tsv_npm(CLI_TS_REPO_KEY, label, metric), `${label} ${metric}`); const bare = (metric: 'wall_ms' | 'cpu_ms') => - defined(cli_speedup_vs_tsv(CLI_TS_REPO_KEY, label, metric), `${label} ${metric}`); + defined(cli_ratio_vs_tsv(CLI_TS_REPO_KEY, label, metric), `${label} ${metric}`); assert.isAbove( npm('cpu_ms'), npm('wall_ms'), From d1863ee4e2713f84ff4ae1fa8c1423c4a96e4b0d Mon Sep 17 00:00:00 2001 From: Ryan Atkinson Date: Tue, 22 Sep 2026 10:04:56 -0400 Subject: [PATCH 194/218] wip --- CLAUDE.md | 7 ++- src/routes/docs/benchmarks/+page.svelte | 31 +++++++++++++ .../docs/benchmarks/BenchmarksCli.svelte | 14 ------ src/routes/docs/benchmarks/benchmarks_cli.ts | 19 +++----- .../benchmarks/benchmarks_formatters.json | 16 ++++++- .../benchmarks/formatter_benchmark_data.ts | 34 +++++++++++--- src/test/benchmarks_cli.shape.test.ts | 45 +++++++++++++++++++ src/test/formatter_benchmark_data.test.ts | 23 +++++++--- 8 files changed, 149 insertions(+), 40 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index f366d7c..df4a7d1 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -87,7 +87,7 @@ src/ ├── benchmark_display.test.ts # unit tests for the value formatters and row labels ├── benchmark_baseline.test.ts # unit tests for the hover-to-rebaseline ratio math ├── benchmarks_cli.test.ts # unit tests for the CLI report shaping and claim helpers - ├── benchmarks_cli.shape.test.ts # shape gates over the CLI-harness data as the page consumes it + ├── benchmarks_cli.shape.test.ts # shape gates over the CLI-harness data as the page consumes it, and its machine and versions against the in-process report's ├── benchmark_test_helpers.ts # fixture factories the benchmark tests share └── formatter_benchmark_data.test.ts # the harness report's validation ``` @@ -137,6 +137,11 @@ A drift that still validates but renames a scenario is caught on the site side: every key in `benchmarks_cli.ts`'s `SCENARIO_COPY` must resolve to generated data, and a test asserts it. +The page states the machine and tool versions once, in the Benchmarking details +section, from tsv's report. `benchmarks_cli.shape.test.ts` holds the harness's +own `machine` and `versions` to it (CPU, OS/arch, Node, and every tool both +time), so refresh the two on the same setup — a one-sided refresh fails there. + ### The CLI comparison The harness is a fork of Oxc's `bench-formatter` that adds tsv, benching it diff --git a/src/routes/docs/benchmarks/+page.svelte b/src/routes/docs/benchmarks/+page.svelte index e02a46d..d957b70 100644 --- a/src/routes/docs/benchmarks/+page.svelte +++ b/src/routes/docs/benchmarks/+page.svelte @@ -14,6 +14,7 @@ import { benchmarks_json } from './benchmarks.ts'; import { benchmarks_cross_runtime_json } from './benchmarks_cross_runtime.ts'; import { + benchmarks_cli, cli_scenario_find, cli_ratio_vs_tsv, cli_ratio_vs_tsv_npm, @@ -103,6 +104,20 @@ sweeps.canonical_floor === sweeps.floor ? '' : ` (${format_count_maybe(sweeps.canonical_floor)} for each group's reference row)`; + // The CLI harness records its own machine and tool versions; the shape test holds + // them to the ones listed below, so only what the harness alone records is quoted: + // when and from which revision it ran, the thread count its wall-clock scales + // with, and the tsv packages it installs. + const cli_date = new Date(benchmarks_cli.timestamp).toLocaleDateString('en-US', { + year: 'numeric', + month: 'long', + day: 'numeric', + // prerendered: pin the zone so the build box's doesn't pick the day + timeZone: 'UTC' + }); + const cli_commit_url = `https://github.com/ryanatkn/oxc-bench-formatter/commit/${benchmarks_cli.git_commit}`; + const cli_tsv_binary = benchmarks_cli.tsv_binary; + const cli_tsv_wasm_version = benchmarks_cli.versions['tsv-wasm']; // Every ratio the TLDR and the section notes quote, computed from the same // reports the charts render so the prose can't drift from them. The pairings and @@ -577,6 +592,22 @@ thinner evidence than the same cv over hundreds, so the instability check proves less for the slow rows — Prettier among them, the denominator of every ratio in the summary table.

    +

    + The CLI section ran on {cli_date}, from + + + its harness at {benchmarks_cli.git_commit} + {benchmarks_cli.git_dirty ? ' with uncommitted changes' : ''}, on the same machine and + Node as these runs and with the same versions of the tools both time, all listed below — + across {benchmarks_cli.machine.threads} threads, which its multi-file wall-clock scales with. + {#if cli_tsv_binary.source === 'package'} + Its native tsv rows run the {cli_tsv_binary.package} binary, + {:else} + Its native tsv rows run a local + build{cli_tsv_binary.built ? ` from ${cli_tsv_binary.built}` : ''}, + {/if} + and its WASM row runs @fuzdev/tsv-wasm {cli_tsv_wasm_version}. +

    diff --git a/src/routes/docs/benchmarks/BenchmarksCli.svelte b/src/routes/docs/benchmarks/BenchmarksCli.svelte index 7dc902c..2412d20 100644 --- a/src/routes/docs/benchmarks/BenchmarksCli.svelte +++ b/src/routes/docs/benchmarks/BenchmarksCli.svelte @@ -17,14 +17,6 @@ report: BenchmarksCliReport; } = $props(); - // listed as the harness reported them, so a formatter added or dropped upstream - // shows up here instead of silently rendering `undefined` for a fixed key - const versions = $derived( - Object.entries(report.versions) - .map(([name, version]) => `${name} ${version}`) - .join(', ') - ); - // the row the pointer is over re-baselines its own table, as the format, parse, // and size groups do (`to_baseline_key`); only one row is ever hovered, so one // slot serves every table @@ -152,12 +144,6 @@ {/each} -

    - - Measured on {report.machine} — {versions}. - -

    - diff --git a/src/routes/docs/benchmarks/benchmark_data.ts b/src/routes/docs/benchmarks/benchmark_data.ts index 18f4cfa..415486e 100644 --- a/src/routes/docs/benchmarks/benchmark_data.ts +++ b/src/routes/docs/benchmarks/benchmark_data.ts @@ -382,20 +382,6 @@ export interface BenchmarkDisplayEntry { coverage_only?: boolean; } -/** The format groups the speedup summary reads, in column order. */ -export const SPEEDUP_LANGUAGES = ['svelte', 'typescript', 'css'] as const; - -export interface SpeedupCell { - language: (typeof SPEEDUP_LANGUAGES)[number]; - speedup: number | undefined; -} - -export interface SpeedupRow { - variant: string; - // tsv's speedup over Prettier, one cell per `SPEEDUP_LANGUAGES` entry - cells: Array; -} - // Implementation categorization const CATEGORY_BY_NAME: Record = { @@ -433,11 +419,6 @@ const CATEGORY_BY_NAME: Record = { export const categorize_name = (name: string): ImplementationCategory => CATEGORY_BY_NAME[name] ?? 'oxc'; -// The speedup summary's rows: tsv's primary format entries over the Prettier row -const PRIMARY_NATIVE_FORMAT = 'tsv'; -const PRIMARY_WASM_FORMAT = 'tsv-wasm'; -const SPEEDUP_BASELINE_FORMAT = 'prettier'; - // Derivation functions // Shared display order for benchmark groups: format before parse, then by @@ -613,17 +594,6 @@ export const derive_benchmark_groups = (baseline: BenchmarkBaseline): Array => { - const to_row = (variant: string, name: string): SpeedupRow => ({ - variant, - cells: SPEEDUP_LANGUAGES.map((language) => ({ - language, - speedup: benchmark_speedup(baseline, `format/${language}`, SPEEDUP_BASELINE_FORMAT, name) - })) - }); - return [to_row('native', PRIMARY_NATIVE_FORMAT), to_row('wasm', PRIMARY_WASM_FORMAT)]; -}; - // Measurement stability /** diff --git a/src/routes/docs/benchmarks/benchmark_display.ts b/src/routes/docs/benchmarks/benchmark_display.ts index 4683a1b..e5c0ac5 100644 --- a/src/routes/docs/benchmarks/benchmark_display.ts +++ b/src/routes/docs/benchmarks/benchmark_display.ts @@ -368,10 +368,13 @@ export const format_runtime_display = ( * count, since one large file is a bigger share of the work than its count suggests. * `by_tool` counts are per row and `omitted_files` is their union, so two rows failing * one file sum past it — the copy says "by row" and flags the overlap when there can be one. + * Rows are named as the chart labels them (`format_label`). */ export const format_group_omissions = (omissions: GroupOmissions): string => { const is_one = omissions.omitted_files === 1; - const tools = omissions.by_tool.map((t) => `${t.name} ${format_count(t.files)}`).join(', '); + const tools = omissions.by_tool + .map((t) => `${format_label(t.name)} ${format_count(t.files)}`) + .join(', '); return `${format_count(omissions.omitted_files)} of ${format_count(omissions.files_total)} files (${format_percent(omissions.omitted_bytes, omissions.bytes_total)} of this group's bytes) left out of every row's timed set, because a row here fails ${ is_one ? 'it' : 'them' } in this harness — files failed, by row${ diff --git a/src/routes/docs/benchmarks/benchmark_sizes.ts b/src/routes/docs/benchmarks/benchmark_sizes.ts index 20f8d8c..c5f5d9f 100644 --- a/src/routes/docs/benchmarks/benchmark_sizes.ts +++ b/src/routes/docs/benchmarks/benchmark_sizes.ts @@ -50,7 +50,8 @@ export type SizeCapability = 'full' | 'formatter' | 'parser'; * bucket: both are dprint plugins loaded over the one `@dprint/formatter` host, * and neither exposes a parser. dprint's covers TypeScript/JS, malva's CSS — * each a slice of what tsv's format-only build does, so pair both against - * `tsv-format-wasm` and read the gap as scope before engine. + * `tsv-format-wasm`: malva's smaller size there is scope, while dprint is larger + * despite it. * - `swc` and rsvelte's addon back parse rows and ship no formatter. Both are far * wider than what the rows measure — swc's `.node` is an entire compiler * (transforms, minifier, bundler) and rsvelte's carries the compiler plus diff --git a/src/routes/docs/benchmarks/benchmarks_cli.ts b/src/routes/docs/benchmarks/benchmarks_cli.ts index 5aac7a1..933af34 100644 --- a/src/routes/docs/benchmarks/benchmarks_cli.ts +++ b/src/routes/docs/benchmarks/benchmarks_cli.ts @@ -161,25 +161,25 @@ const SCENARIO_COPY: Record = { [CLI_TS_REPO_KEY]: { heading: 'TypeScript repo', description: - 'Every formatter scoped to the same file set and pinned to tsv’s fixed style, so they do comparable line-break work over the same files; a preflight check aborts the scenario rather than publish a comparison the tools didn’t run on equal work.', + 'Every formatter scoped to the same JSX-free files and pinned to tsv’s fixed style, each at its default parallelism (none, for Prettier).', tsv_only: false }, [CLI_SINGLE_FILE_KEY]: { heading: 'Large single file', description: - 'With a single input no formatter can parallelize across files, so wall-clock is closer to an engine-plus-startup comparison than the multi-file rows — each tool still pays its own process and thread-pool setup, and every row but the bare tsv binary pays Node’s startup first, a fixed cost that weighs most on the fastest rows.', + 'With one input no formatter can parallelize across files, so wall-clock comes nearer engine speed plus startup: each tool’s own process and thread-pool setup, and Node’s for every row but the bare tsv binary — a fixed cost that weighs most on the fastest rows.', tsv_only: false }, [CLI_SVELTE_KEY]: { heading: 'Svelte corpus', description: - 'Two Rust Svelte-native formatters head-to-head on a third-party .svelte corpus, rsvelte-fmt configured to tsv’s fixed style so both do comparable line-break work. Its time includes the oxfmt it spawns for the files it doesn’t format itself. rsvelte-fmt 0.7.x aborts nondeterministically on this corpus under the harness’s preflight, and the harness never retries: a run is published as it ended, complete or aborted.', + 'Two Rust Svelte-native formatters head-to-head on a third-party .svelte corpus, rsvelte-fmt configured to tsv’s fixed style. Its time includes the oxfmt it launches for non-.svelte files, which walks the corpus and finds none. rsvelte-fmt 0.7.x crashes nondeterministically in the harness’s preflight on this corpus, aborting the scenario; the harness doesn’t retry, and since the crash has never been seen in a timed run, a table from a run that got through is unbiased.', tsv_only: false }, [CLI_DELIVERY_KEY]: { heading: 'tsv delivery paths', description: - 'Every row is tsv, not another tool: the native binary, the same binary through @fuzdev/tsv’s Node dispatcher (how npx tsv runs it), and @fuzdev/tsv-wasm, the same CLI over a WASM engine, the package for platforms without a prebuilt binary. One file, so the gaps are launch and engine cost, not file parallelism (the WASM row’s CPU time exceeds its wall-clock, most likely V8 compiling the module on background threads).', + 'Every row is tsv: the native binary, the same binary through @fuzdev/tsv’s Node dispatcher, and @fuzdev/tsv-wasm, the package for platforms without a prebuilt binary — tsv’s CLI reimplemented in JS over a WASM engine. One file, so the gaps are launch and engine cost, not file parallelism; the WASM row’s CPU ratio runs well past its time ratio, likely V8 tiering up the module on background threads.', tsv_only: true } }; @@ -221,7 +221,7 @@ export const to_abort_note = (scenario: FormatterScenario): string => { if (scenario.timings.length) return `Timed, but no memory was published: ${scenario.aborted}.`; const faults = scenario.preflight.flatMap((entry) => { const label = CLI_LABELS[entry.name] ?? entry.name; - if (entry.crashed) return [`${label} crashed partway through its parse check`]; + if (entry.crashed) return [`${label} crashed partway through its preflight check`]; if (entry.unavailable) return [`${label} could not run`]; if (entry.rejected > 0) return [`${label} rejected ${entry.rejected} files`]; return []; @@ -335,22 +335,6 @@ export const cli_ratio_vs_tsv_npm = ( metric: CliMetric ): number | undefined => cli_ratio_vs(scenario_key, label, CLI_TSV_NPM_LABEL, metric); -/** - * The dispatcher row's highest peak RSS across the scenarios that face other - * tools, in megabytes — the Node launcher's footprint rather than tsv's own. - * - * @param scenarios - the scenarios to read, the rendered ones by default - * @returns the figure, or `undefined` when no such scenario measured one - */ -export const cli_tsv_npm_memory_mb = ( - scenarios: Array = benchmarks_cli.scenarios -): number | undefined => { - const peaks = scenarios - .filter((s) => !s.tsv_only) - .flatMap((s) => s.results.find((r) => r.label === CLI_TSV_NPM_LABEL)?.memory_mb ?? []); - return peaks.length ? Math.max(...peaks) : undefined; -}; - /** * What the Node dispatcher adds over the bare binary in wall-clock, in * milliseconds, spanned across every scenario that times both rows — Node diff --git a/src/routes/docs/benchmarks/benchmarks_prose.ts b/src/routes/docs/benchmarks/benchmarks_prose.ts index 1b788ce..da20e1d 100644 --- a/src/routes/docs/benchmarks/benchmarks_prose.ts +++ b/src/routes/docs/benchmarks/benchmarks_prose.ts @@ -32,10 +32,10 @@ export const IN_PROCESS_PAIRS = { parse_svelte_vs_rsvelte: ['parse/svelte', 'rsvelte-parse', 'tsv-json'], parse_css_compiler_vs_tsv: ['parse/css', 'tsv-json', 'svelte/compiler'], parse_css_postcss_vs_tsv: ['parse/css', 'tsv-json', 'postcss'], - // Gated but not rendered: "tsv's default AST ... lands behind" Oxc is a composite + // Gated but not rendered: "tsv's default AST ... puts it behind Oxc" is a composite // of `parse_ts_vs_oxc` and `parse_ts_loc_cost`, true only while the loc cost // outruns tsv's span-only lead, so the sentence is gated as its own pair. Same - // for "(and behind swc's ...)" against swc's span-only AST. + // for "(and swc ...)" against swc's span-only AST. parse_ts_default_vs_oxc: ['parse/typescript', 'tsv-json', 'oxc-parser'], parse_ts_default_vs_swc: ['parse/typescript', 'tsv-json', 'swc'] } as const satisfies Record; diff --git a/src/routes/docs/conformance/+page.svelte b/src/routes/docs/conformance/+page.svelte index 15bb464..b40936b 100644 --- a/src/routes/docs/conformance/+page.svelte +++ b/src/routes/docs/conformance/+page.svelte @@ -90,9 +90,8 @@ Prettier's .css fixtures): read a row's parsers against each other, not against 100%. tsv, a drop-in for Svelte's parseCss, sits above it by also parsing spec-valid CSS that parseCss rejects. PostCSS leads by parsing - less, not because tsv falls short: it keeps selectors and at-rule preludes as unparsed - strings, so it accepts preprocessor syntax and modern CSS parseCss doesn't - implement yet. + less, not because tsv falls short: it keeps selectors as unparsed strings, so it accepts + preprocessor syntax and modern CSS parseCss doesn't implement yet.
  • oxc-parser's column is its native binding; the wasm one, pinned to an older release (see @@ -110,9 +109,10 @@

    {format_count(corpus_source_table.totals.files)} files from {corpus_source_table.rows.length} sources, none of them the real-world code used in the - : formatter, compiler, and conformance test suites, each from - a pinned checkout. The three harvested into caches — test262, web-platform-tests CSS, and - the TypeScript compiler's cases — link their upstream without a commit. + : formatter, compiler, and conformance test suites. Each links + its upstream at the commit the harness pinned, except the three harvested into caches — + test262, web-platform-tests CSS, and the TypeScript compiler's cases — which carry no + commit.

    • diff --git a/src/test/benchmark_data.prose.test.ts b/src/test/benchmark_data.prose.test.ts index 23c4f4c..adb9e45 100644 --- a/src/test/benchmark_data.prose.test.ts +++ b/src/test/benchmark_data.prose.test.ts @@ -12,7 +12,6 @@ import { cli_scenario_find, cli_ratio_vs_tsv, cli_ratio_vs_tsv_npm, - cli_tsv_npm_memory_mb, cli_tsv_npm_overhead_ms_range, cli_node_startup_ms, CLI_DELIVERY_KEY, @@ -30,6 +29,7 @@ import { categorize_name, derive_benchmark_groups, derive_corpus_counts, + derive_sweep_stats, is_entry_unstable, is_payload_matched } from '$routes/docs/benchmarks/benchmark_data.ts'; @@ -89,8 +89,8 @@ describe('prose ratios resolve', () => { }); test('a group that runs short of the corpus total has a note saying by how much', () => { - // "where a group runs short of the corpus total, a note under its chart gives - // the files ... left out" — the note renders from `omissions`, so the sentence + // "a chart that runs short of the corpus total says beneath it what was left + // out" — the note renders from `omissions`, so the sentence // holds exactly when every shortfall is an omission the report carries const groups = derive_benchmark_groups(benchmarks_json); assert.isNotEmpty(groups); @@ -126,8 +126,9 @@ describe('prose ratios resolve', () => { }); test('oxfmt formats Svelte at Prettier speed, as the note says it delegates', () => { - // "for Svelte it delegates to a Prettier it bundles" — if a future oxfmt grows its - // own Svelte path the two rows will part ways and the note is stale + // "delegates Svelte to a Prettier it bundles", which the TLDR leans on to quote + // only Prettier for Svelte — if a future oxfmt grows its own Svelte path the + // two rows will part ways and both are stale const ratio = benchmark_speedup(benchmarks_json, 'format/svelte', 'oxfmt', 'prettier'); assert.isDefined(ratio); assert.closeTo(ratio, 1, 0.1, 'oxfmt and prettier should be within 10% on format/svelte'); @@ -160,9 +161,9 @@ describe('prose ratios resolve', () => { }); test('the pairings the copy calls payload-matched are, and the ones it excludes are not', () => { - // The page names four pairings as comparing the same PRODUCT and rules two out - // ("swc's own AST shape ... matches neither tsv wire", "the `no-locs` entries - // are the one payload-matched pairing" for oxc-parser). Those are claims about + // The page names four pairings as comparing the same PRODUCT and rules three out + // ("swc's AST ... matches neither tsv wire", and the `no-locs` entries, not the + // default wire, "are the payload-matched comparison with oxc-parser"). Those are claims about // the report's `payload` tiers, so read them off it rather than trusting prose. const entry = (group: string, name: string) => { const found = benchmarks_json.entries.find((e) => e.group === group && e.name === name); @@ -186,7 +187,9 @@ describe('prose ratios resolve', () => { ['parse/typescript', 'tsv-json', 'swc'], ['parse/typescript', 'tsv-json-no-locations', 'swc'], // oxc against tsv's default wire — the pairing the copy says is NOT the matched one - ['parse/typescript', 'tsv-json', 'oxc-parser'] + ['parse/typescript', 'tsv-json', 'oxc-parser'], + // rsvelte's reduced wire "sits near tsv's span-only wire without matching it" + ['parse/svelte', 'tsv-json-no-locations', 'rsvelte-parse-skip-expr-loc'] ] as const) { assert.isFalse(matched(group, a, b), `${group}: ${a} vs ${b} is now payload-matched`); } @@ -235,12 +238,10 @@ describe('prose ratios resolve', () => { // other tools' npm bins: "~Nx faster than Oxfmt and ~Mx faster than Biome ... // using less memory than either". The copy has no bare-binary fallback, so // every one must resolve or a sentence prints with a hole in it. - for (const key of [CLI_SINGLE_FILE_KEY, CLI_TS_REPO_KEY]) { - for (const label of ['oxfmt', 'biome']) { - const ratio = cli_ratio_vs_tsv_npm(key, label, 'wall_ms'); - assert.isDefined(ratio, `${key}: ${label}`); - assert_reads_faster(ratio, `${key}: ${label}`); - } + for (const label of ['oxfmt', 'biome']) { + const ratio = cli_ratio_vs_tsv_npm(CLI_TS_REPO_KEY, label, 'wall_ms'); + assert.isDefined(ratio, `${CLI_TS_REPO_KEY}: ${label}`); + assert_reads_faster(ratio, `${CLI_TS_REPO_KEY}: ${label}`); } const memory = cli_memory_ratio_range({ scenario_key: CLI_TS_REPO_KEY, @@ -249,8 +250,8 @@ describe('prose ratios resolve', () => { }); assert.isDefined(memory); assert.isAbove(memory.min, 1); - // "~Nx on the TypeScript repo": the dispatcher's own cost there, which the - // delivery note says shrinks against the one-file figure + // "~Nx the binary's time on the delivery table's one file, but ~Mx on the + // TypeScript repo": the dispatcher's own cost must shrink on the repo const repo_cost = cli_ratio_vs_tsv(CLI_TS_REPO_KEY, CLI_TSV_NPM_LABEL, 'wall_ms'); const file_cost = cli_ratio_vs_tsv(CLI_DELIVERY_KEY, CLI_TSV_NPM_LABEL, 'wall_ms'); assert.isDefined(repo_cost); @@ -268,9 +269,9 @@ describe('prose ratios resolve', () => { } }); - test("the dispatcher row's peak RSS is \"its Node launcher's, not the binary's\"", () => { - // the harness reports the largest single process in the tree, so the note under - // each table holds only while the launcher outgrows the binary it spawns + test('the process the dispatcher row\'s peak RSS leaves out "is the binary itself"', () => { + // the harness reports the largest single process in the tree, so the memory note + // holds only while the Node launcher outgrows the binary it spawns for (const scenario of benchmarks_cli.scenarios) { const npm = scenario.results.find((r) => r.label === CLI_TSV_NPM_LABEL); const tsv = scenario.results.find((r) => r.label === 'tsv'); @@ -279,31 +280,27 @@ describe('prose ratios resolve', () => { } }); - test('the dispatcher\'s peak memory is "still below every other tool\'s"', () => { - const peak = cli_tsv_npm_memory_mb(); - assert.isDefined(peak); + test('the memory note\'s "every other tool in every scenario" spans every competitor row', () => { + // the unscoped memory range skips a row without a figure, so a missed memory + // pass would narrow the claim silently rather than void it — every competitor + // row must carry one for (const scenario of benchmarks_cli.scenarios.filter((s) => !s.tsv_only)) { for (const r of cli_comparison_results(scenario)) { - // "every other tool in every scenario": the unscoped memory range skips a - // row without a figure, so a missed memory pass would narrow the claim - // silently rather than void it — every competitor row must carry one assert.isNotNull(r.memory_mb, `${scenario.key}: ${r.label} has no memory figure`); - assert.isBelow(peak, r.memory_mb, `${scenario.key}: ${r.label}`); } } }); test('the CLI CPU-work note reads the way the numbers run', () => { - // "read like for like, against the dispatcher row, it widens tsv's lead: ~Nx - // faster in wall-clock and ~Mx in CPU work ... Against the bare binary it - // narrows instead" — two inequalities per tool, in opposite directions. Either - // one flipping on a refresh leaves the note explaining the opposite of what the - // table shows, so both are pinned the way the copy reads. + // "CPU ratios barely move between tsv's two rows ... where wall-clock swings from + // ~A to ~B" — the two CPU leads must sit inside the wall-clock span: dispatcher + // wall < dispatcher CPU <= bare CPU < bare wall. Any one flipping on a refresh + // leaves the note explaining the opposite of what the table shows. const defined = (value: number | undefined, name: string): number => { assert.isDefined(value, `${CLI_TS_REPO_KEY}: ${name}`); return value; }; - for (const label of ['oxfmt', 'biome']) { + for (const label of ['oxfmt']) { const npm = (metric: 'wall_ms' | 'cpu_ms') => defined(cli_ratio_vs_tsv_npm(CLI_TS_REPO_KEY, label, metric), `${label} ${metric}`); const bare = (metric: 'wall_ms' | 'cpu_ms') => @@ -318,6 +315,7 @@ describe('prose ratios resolve', () => { bare('cpu_ms'), `${label}: bare binary, wall lead > CPU lead` ); + assert.isAtMost(npm('cpu_ms'), bare('cpu_ms'), `${label}: dispatcher CPU lead > bare`); // every one of the four renders inside a "~Nx faster than" sentence, and // `format_ratio_approx` is direction-blind, so each must also clear 1 — the // wall-clock dispatcher ratio is gated above, the other three here @@ -335,15 +333,6 @@ describe('prose ratios resolve', () => { assert(prettier, `${key} has no prettier row`); assert.isAbove(prettier.cpu_ms, prettier.wall_ms, `${key}: prettier CPU > wall`); } - // "on the single file a tool that spins up a worker pool it can't use reads CPU - // above wall-clock too" - const pooled = cli_scenario_find(CLI_SINGLE_FILE_KEY)?.results.filter( - (r) => !cli_label_is_tsv(r.label) && !r.label.startsWith('prettier') - ); - assert( - pooled?.some((r) => r.cpu_ms > r.wall_ms), - 'no pooled tool reads CPU > wall' - ); }); test('the Node launch floor sits inside the dispatcher overhead', () => { @@ -361,8 +350,9 @@ describe('prose ratios resolve', () => { }); test('the dispatcher overhead is the "fixed cost" the delivery note calls it', () => { - // "That launch cost is fixed, so its share shrinks on a real repo" — fixed means the absolute figure barely moves between a one-file - // run and a repo, so the span must stay tight around a positive cost + // "tsv's dispatcher adds a fixed ~N ms over the bare binary" — fixed means the + // absolute figure barely moves between a one-file run and a repo, so the span + // must stay tight around a positive cost const overhead = cli_tsv_npm_overhead_ms_range(); assert.isDefined(overhead); assert.isAbove(overhead.min, 0); @@ -370,13 +360,13 @@ describe('prose ratios resolve', () => { }); test('the scenario descriptions state facts the report carries', () => { - // the delivery copy: "the WASM row's CPU time exceeds its wall-clock" - const wasm = cli_scenario_find(CLI_DELIVERY_KEY)?.results.find( - (r) => r.label === CLI_TSV_WASM_LABEL - ); - assert(wasm, 'delivery scenario has no tsv-wasm row'); - assert.isAbove(wasm.cpu_ms, wasm.wall_ms); - // the Svelte copy: "rsvelte-fmt 0.7.x aborts nondeterministically on this corpus" + // the delivery copy: "the WASM row's CPU ratio runs well past its time ratio" + const cpu = cli_ratio_vs_tsv(CLI_DELIVERY_KEY, CLI_TSV_WASM_LABEL, 'cpu_ms'); + const wall = cli_ratio_vs_tsv(CLI_DELIVERY_KEY, CLI_TSV_WASM_LABEL, 'wall_ms'); + assert.isDefined(cpu, 'delivery scenario has no tsv-wasm row'); + assert.isDefined(wall); + assert.isAbove(cpu, wall * 1.5, 'the WASM CPU ratio no longer runs well past its time ratio'); + // the Svelte copy: "rsvelte-fmt 0.7.x crashes nondeterministically in the harness's preflight" const rsvelte_version = benchmarks_cli.versions['rsvelte-fmt']; assert.isDefined(rsvelte_version); assert.match(rsvelte_version, /^0\.7\./, 'the Svelte copy names rsvelte-fmt 0.7.x'); @@ -442,8 +432,8 @@ describe('prose ratios resolve', () => { }); test('the run-order note holds: every scenario runs the dispatcher row, then bare tsv, last', () => { - // "Every scenario tsv runs in puts the bare binary last, with its Node dispatcher - // row just before it" — hyperfine reports commands in the order it ran them, + // "Every scenario puts the bare binary last, with its Node dispatcher row just + // before it" — hyperfine reports commands in the order it ran them, // and the generated timings keep that order. An aborted scenario has no timings // to order, so its preflight rows, which the harness runs in the same order, stand in. for (const key of CLI_SCENARIO_KEYS) { @@ -503,6 +493,15 @@ describe('prose ratios resolve', () => { } }); + test('the slowest rows have "too few timings" for the cross-runtime noise check', () => { + // tsv's report composer judges a delta against noise only where both sides kept + // at least 10 cleaned timings, so the Cross-runtime section's caveat holds while + // some row here keeps fewer + const { sample_size_min } = derive_sweep_stats(benchmarks_json); + assert.isDefined(sample_size_min); + assert.isBelow(sample_size_min, 10); + }); + test('the higher sweep floor is "each group\'s reference row"\'s, and only theirs', () => { // Benchmarking details quotes the lowest floor for every row and a second one in // parentheses for the reference rows, so exactly those rows may sit above it diff --git a/src/test/benchmark_data.shape.test.ts b/src/test/benchmark_data.shape.test.ts index 9871d93..41a9b99 100644 --- a/src/test/benchmark_data.shape.test.ts +++ b/src/test/benchmark_data.shape.test.ts @@ -6,8 +6,7 @@ import { CORPUS_SOURCE_LABELS, categorize_name, derive_corpus_source_table, - derive_benchmark_groups, - derive_speedup_summary + derive_benchmark_groups } from '$routes/docs/benchmarks/benchmark_data.ts'; import { VERSION_LABELS } from '$routes/docs/benchmarks/benchmark_display.ts'; import { conformance_json } from '$routes/docs/conformance/conformance.ts'; @@ -274,19 +273,6 @@ describe('benchmarks.json shape', () => { } }); - test('speedup summary is fully populated, and every cell reads "faster than Prettier"', () => { - const rows = derive_speedup_summary(benchmarks_json); - assert.strictEqual(rows.length, 2); // native + wasm - for (const row of rows) { - // `BenchmarksSummary` captions the table as how much faster tsv is than - // Prettier, so a cell below 1 would render a slowdown under that caption - for (const { language, speedup } of row.cells) { - assert.isDefined(speedup, `${row.variant} ${language}`); - assert.isAbove(speedup, 1, `${row.variant} ${language}`); - } - } - }); - test('flagship report is the node runtime', () => { // the headline detailed view switched to N-API under Node; guards against an // `update-benchmarks` that pulls the wrong runtime's sibling report diff --git a/src/test/benchmark_display.test.ts b/src/test/benchmark_display.test.ts index 86b469c..d688aef 100644 --- a/src/test/benchmark_display.test.ts +++ b/src/test/benchmark_display.test.ts @@ -273,7 +273,7 @@ describe('format_group_omissions', () => { test('several files by several rows flags the overlap', () => { assert.strictEqual( format_group_omissions(omissions), - "2 of 951 files (11.2% of this group's bytes) left out of every row's timed set, because a row here fails them in this harness — files failed, by row (rows can overlap): biome-wasm 2, oxfmt 1" + "2 of 951 files (11.2% of this group's bytes) left out of every row's timed set, because a row here fails them in this harness — files failed, by row (rows can overlap): biome (wasm) 2, oxfmt (node napi) 1" ); }); @@ -284,7 +284,7 @@ describe('format_group_omissions', () => { omitted_files: 1, by_tool: [{ name: 'oxfmt', files: 1, bytes: 112, categories: {} }] }), - "1 of 951 files (11.2% of this group's bytes) left out of every row's timed set, because a row here fails it in this harness — files failed, by row: oxfmt 1" + "1 of 951 files (11.2% of this group's bytes) left out of every row's timed set, because a row here fails it in this harness — files failed, by row: oxfmt (node napi) 1" ); }); }); diff --git a/src/test/benchmark_sizes.shape.test.ts b/src/test/benchmark_sizes.shape.test.ts index 5c84a3f..9afc463 100644 --- a/src/test/benchmark_sizes.shape.test.ts +++ b/src/test/benchmark_sizes.shape.test.ts @@ -168,16 +168,30 @@ describe('benchmarks.json binary sizes', () => { // "barely larger": the formatter already contains the Svelte parser assert.isAbove(full.bytes, formatter.bytes); assert.isBelow(full.bytes, formatter.bytes * 1.01); - // "minified JS compresses much better than wasm" + // "minified JS compresses much better than tsv's wasm" — tsv's only: other wasm + // builds (biome's, dprint's) gzip about as well as the bundles const gz_share = (s: (typeof sizes)[number]) => (s.gzip_bytes ?? NaN) / s.bytes; - const wasm = sizes.filter((s) => s.kind === 'wasm' && s.gzip_bytes != null); - assert.isNotEmpty(wasm); - const best_wasm = Math.min(...wasm.map(gz_share)); + const tsv_wasm = sizes.filter( + (s) => s.kind === 'wasm' && s.label.startsWith('tsv') && s.gzip_bytes != null + ); + assert.isNotEmpty(tsv_wasm); + const best_tsv_wasm = Math.min(...tsv_wasm.map(gz_share)); for (const bundle of bundles) { - assert.isBelow(gz_share(bundle), best_wasm, bundle.label); + assert.isBelow(gz_share(bundle), best_tsv_wasm * 0.8, bundle.label); } }); + test('the dprint and Malva note reads the sizes: Malva smaller on scope, dprint larger regardless', () => { + const size = (label: string) => { + const found = benchmarks_json.binary_sizes.find((s) => s.label === label); + assert(found, `${label} is missing`); + return found.bytes; + }; + const tsv_format = size('tsv-format-wasm'); + assert.isBelow(size('malva (wasm)'), tsv_format); + assert.isAbove(size('dprint (wasm)'), tsv_format); + }); + test('formatter group gets a disabled oxfmt (wasm) placeholder just above oxfmt (napi), since oxfmt has no wasm build', () => { const groups = derive_size_groups(benchmarks_json.binary_sizes); const formatter = groups.find((g) => g.capability === 'formatter'); diff --git a/src/test/benchmarks_cli.shape.test.ts b/src/test/benchmarks_cli.shape.test.ts index 5c6379e..5e5768b 100644 --- a/src/test/benchmarks_cli.shape.test.ts +++ b/src/test/benchmarks_cli.shape.test.ts @@ -150,7 +150,7 @@ describe('benchmarks_cli shape', () => { }); test('every formatter accepts the whole corpus in every timed scenario, as the page claims', () => { - // The page's notes say the preflight parse check found nothing rejected, so + // The page's notes say the preflight asserts every formatter parses every file, so // no formatter is credited for skipping files. That's a claim about the data — // for the scenarios that were timed. An aborted one is the harness saying the // opposite, and the page shows it as an abort, so its rows are exempt. diff --git a/src/test/benchmarks_cli.test.ts b/src/test/benchmarks_cli.test.ts index 7a7a5e0..732d605 100644 --- a/src/test/benchmarks_cli.test.ts +++ b/src/test/benchmarks_cli.test.ts @@ -7,7 +7,6 @@ import { cli_memory_ratio_range, cli_ratio_between, cli_settle_seconds, - cli_tsv_npm_memory_mb, cli_tsv_npm_overhead_ms_range, CLI_TSV_LABEL, CLI_TSV_NPM_LABEL, @@ -52,7 +51,7 @@ describe('to_abort_note', () => { ] }) ), - 'Not timed: rsvelte-fmt crashed partway through its parse check; tsv via Node dispatcher could not run; biome rejected 3 files.' + 'Not timed: rsvelte-fmt crashed partway through its preflight check; tsv via Node dispatcher could not run; biome rejected 3 files.' ); }); @@ -208,14 +207,6 @@ describe('cli claims spanning scenarios', () => { assert.isUndefined(cli_settle_seconds([])); }); - test("the dispatcher's peak memory skips the tsv-only scenarios", () => { - assert.strictEqual(cli_tsv_npm_memory_mb([facing, delivery]), 40); - assert.isUndefined(cli_tsv_npm_memory_mb([delivery])); - assert.isUndefined( - cli_tsv_npm_memory_mb([scenario('s', { results: [result(CLI_TSV_NPM_LABEL, 50, null)] })]) - ); - }); - test('the dispatcher overhead spans every scenario that timed both rows', () => { assert.deepEqual(cli_tsv_npm_overhead_ms_range([facing, delivery]), { min: 30, max: 35 }); assert.isUndefined( diff --git a/src/test/conformance_data.prose.test.ts b/src/test/conformance_data.prose.test.ts index 08063b7..014f374 100644 --- a/src/test/conformance_data.prose.test.ts +++ b/src/test/conformance_data.prose.test.ts @@ -76,8 +76,9 @@ describe('conformance prose reads the report', () => { }); test('the Test corpus section names three harvested suites, linked without a commit', () => { - // "The three the harness harvests into caches — test262, web-platform-tests CSS, - // and the TypeScript compiler's cases — link their upstream without a commit" + // "Each links its upstream at the commit the harness pinned, except the three + // harvested into caches — test262, web-platform-tests CSS, and the TypeScript + // compiler's cases — which carry no commit" const { rows } = derive_corpus_source_table(conformance_json, CONFORMANCE_SOURCE_LABELS); const harvested = rows.filter((row) => row.path.includes('/.cache/')); assert.strictEqual(harvested.length, 3); From 6778caa1ec0ac58640e7b3661d0a6ab060fa4a55 Mon Sep 17 00:00:00 2001 From: Ryan Atkinson Date: Wed, 23 Sep 2026 14:24:31 -0400 Subject: [PATCH 209/218] wip --- CLAUDE.md | 9 +- src/routes/docs/benchmarks/+page.svelte | 216 +++++++------- .../benchmarks/BenchmarksCliSection.svelte | 3 +- .../docs/benchmarks/BenchmarksSizes.svelte | 17 +- .../docs/benchmarks/BenchmarksTools.svelte | 113 +++++++ src/routes/docs/benchmarks/benchmark_data.ts | 2 +- src/routes/docs/benchmarks/benchmark_sizes.ts | 170 +++++------ src/routes/docs/benchmarks/benchmark_tools.ts | 277 ++++++++++++++++++ .../docs/benchmarks/benchmarks_prose.ts | 4 +- src/test/benchmark_data.prose.test.ts | 28 +- src/test/benchmark_sizes.shape.test.ts | 184 +++++------- src/test/benchmark_sizes.test.ts | 65 ++-- src/test/benchmark_tools.shape.test.ts | 76 +++++ src/test/benchmark_tools.test.ts | 91 ++++++ 14 files changed, 899 insertions(+), 356 deletions(-) create mode 100644 src/routes/docs/benchmarks/BenchmarksTools.svelte create mode 100644 src/routes/docs/benchmarks/benchmark_tools.ts create mode 100644 src/test/benchmark_tools.shape.test.ts create mode 100644 src/test/benchmark_tools.test.ts diff --git a/CLAUDE.md b/CLAUDE.md index d00284a..1b3e65d 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -43,7 +43,7 @@ Note: `vite` is deliberately held at 7.x (with `@sveltejs/vite-plugin-svelte` 6. tsv.fuz.dev is the public face of the tsv tool: - Landing page (home) with links to benchmarks and docs -- Benchmarks page with bar charts and tables +- Benchmarks page with bar charts and tables, and a language-support matrix of the tools compared - Docs section (introduction, playground, benchmarks, conformance) - Conformance page with per-corpus-source parse-coverage tables over deliberately hard corpora, and a `Test corpus` section on how each source was chosen - Interactive playground (`/docs/playground`) — edit a deliberately-unformatted Svelte example in a syntax-highlighted editor (fuz_code's `CodeTextarea`); the formatted output below it updates live and the parsed AST follows on a short idle; runs `@fuzdev/tsv-wasm` as lazily-loaded WASM @@ -80,8 +80,10 @@ src/ ├── conformance_data.test.ts # unit tests for the conformance grouping and per-source matrices ├── conformance_data.shape.test.ts # shape gates over the committed conformance report ├── conformance_data.prose.test.ts # gates the claims the conformance page's prose quotes - ├── benchmark_sizes.test.ts # unit tests for the binary-size capability grouping + ├── benchmark_sizes.test.ts # unit tests for the binary-size target and capability grouping ├── benchmark_sizes.shape.test.ts # shape gates over the committed report's binary sizes, and the tldr's like-for-like size claim + ├── benchmark_tools.test.ts # unit tests for the language-support matrix's timed marks + ├── benchmark_tools.shape.test.ts # gates the matrix's rows against the reports: every timed row and CLI row listed, every timed capability stated, every CLI scenario mapped to a column ├── benchmark_cross_runtime.test.ts # unit tests for the combined-report derivations ├── benchmark_cross_runtime.shape.test.ts # shape gates over the committed combined report ├── benchmark_display.test.ts # unit tests for the value formatters and row labels @@ -162,7 +164,8 @@ in the schema TSDoc in `formatter_benchmark_data.ts`. - `benchmark_data.ts` — per-runtime report types, plus the format/parse, stability, and corpus derivations; imports none of the others - `BenchmarksCorpus.svelte` — the per-source corpus table both pages' corpus sections render (`Corpus` on the benchmarks page, `Test corpus` on the conformance page), from `benchmark_data.ts`'s `derive_corpus_source_table`; a source no repo names needs a hand label (`CORPUS_SOURCE_LABELS`), and the conformance page hand-labels every source (`CONFORMANCE_SOURCE_LABELS`, which its matrix also reads); the shape test holds both - `benchmark_display.ts` — value formatters, row labels, per-category colors; imports only `benchmark_data.ts`'s types -- `benchmark_sizes.ts`, `benchmark_cross_runtime.ts` — one domain each, built on `benchmark_data.ts` (the cross-runtime one on `benchmark_display.ts` too); the conformance page's `conformance_data.ts` does the same from its own directory — a matrix per language (corpus sources × engines, the aggregate as the leading row), with hand-stated maps the report has no field for: the engine names, the row notes, the source labels, `CONFORMANCE_ENGINE_VERSIONS` (the version keys each engine column lists, so the page's meta panel skips the report's formatters), and `CONFORMANCE_SELECTORS`, the engine that selected a source and so reads 100% on it by construction; the shape test holds each to the report +- `benchmark_tools.ts` + `BenchmarksTools.svelte` — the language-support matrix: each tool's parse and format support per language, stated by hand (`TOOL_SUPPORT`, verified against the tools' docs and installed packages), with the cells the page times derived from the in-process and CLI reports; the shape test holds the two together +- `benchmark_sizes.ts` (the binary sizes split by target — browser: wasm and JS; native — then grouped by capability), `benchmark_cross_runtime.ts` — one domain each, built on `benchmark_data.ts` (the cross-runtime one on `benchmark_display.ts` too); the conformance page's `conformance_data.ts` does the same from its own directory — a matrix per language (corpus sources × engines, the aggregate as the leading row), with hand-stated maps the report has no field for: the engine names, the row notes, the source labels, `CONFORMANCE_ENGINE_VERSIONS` (the version keys each engine column lists, so the page's meta panel skips the report's formatters), and `CONFORMANCE_SELECTORS`, the engine that selected a source and so reads 100% on it by construction; the shape test holds each to the report - `benchmark_baseline.ts` + `BenchmarksBaselineGroup.svelte` — hover-to-rebaseline: hovering a row re-anchors that group's ratios, restoring the default anchor on leave; pointer-only by design, and a disabled row never anchors. `BenchmarksCli.svelte`'s tables behave the same way - `formatter_benchmark_data.ts` — the harness report's Zod schemas and `parse_formatter_benchmarks` - `benchmarks_cli.ts` — shapes the CLI report for `BenchmarksCli.svelte` and owns the per-scenario prose and the `cli_*` claim helpers diff --git a/src/routes/docs/benchmarks/+page.svelte b/src/routes/docs/benchmarks/+page.svelte index 496580a..c9e9d40 100644 --- a/src/routes/docs/benchmarks/+page.svelte +++ b/src/routes/docs/benchmarks/+page.svelte @@ -15,6 +15,7 @@ import { benchmarks_json } from './benchmarks.ts'; import { benchmarks_cross_runtime_json } from './benchmarks_cross_runtime.ts'; import { + benchmarks_cli, cli_scenario_find, cli_ratio_vs_tsv, cli_ratio_vs_tsv_npm, @@ -44,11 +45,12 @@ // the size-chart row names the notes below refer to, from the module that // builds the rows, so prose and chart can't drift apart import { + derive_size_targets, OXC_FULL_LABEL, OXFMT_NATIVE_LABEL, - RSVELTE_INSTALL_LABEL, RSVELTE_LABEL } from './benchmark_sizes.ts'; + import { derive_tool_matrix } from './benchmark_tools.ts'; import { IN_PROCESS_PAIRS } from './benchmarks_prose.ts'; import BenchmarksGroup from './BenchmarksGroup.svelte'; import BenchmarksSizes from './BenchmarksSizes.svelte'; @@ -56,6 +58,7 @@ import BenchmarksCorpus from './BenchmarksCorpus.svelte'; import BenchmarksCrossRuntime from './BenchmarksCrossRuntime.svelte'; import BenchmarksCliSection from './BenchmarksCliSection.svelte'; + import BenchmarksTools from './BenchmarksTools.svelte'; const LIBRARY_ITEM_NAME = 'benchmarks'; @@ -66,6 +69,7 @@ // Section titles referenced by in-page anchors, slugified the same way // `TomeSectionHeader` builds its ids so a rename can't orphan a link. + const LANGUAGE_SECTION_TITLE = 'Language support'; const CLI_SECTION_TITLE = 'End-to-end CLI benchmark'; const DETAILS_SECTION_TITLE = 'Benchmarking details'; const CORPUS_SECTION_TITLE = 'Corpus'; @@ -76,8 +80,11 @@ const node_display = format_runtime_display(benchmarks_json); const groups = derive_benchmark_groups(benchmarks_json); + // what each tool parses and formats, with the cells this page times marked from the reports + const tool_matrix = derive_tool_matrix(benchmarks_json, benchmarks_cli); + const size_targets = derive_size_targets(benchmarks_json.binary_sizes); const corpus = benchmarks_json.corpus; - // Read off the report so the "What's measured" figures can't drift from the + // Read off the report so the Corpus section's figures can't drift from the // copied data; the harvest is disclosed beside the file count rather than netted // out of it, and quoted only when the report distinguishes it. const corpus_counts = derive_corpus_counts(benchmarks_json); @@ -123,7 +130,6 @@ // What tsv's default per-node `loc` costs over its span-only wire, same engine. const parse_ts_loc_cost = speedup('parse_ts_loc_cost'); const parse_ts_yuku_vs_tsv = speedup('parse_ts_yuku_vs_tsv'); - const parse_ts_yuku_vs_tsv_wasm = speedup('parse_ts_yuku_vs_tsv_wasm'); // Svelte and CSS pair tsv's default `loc`-bearing wire with the JS parsers it // is a drop-in for (and rsvelte's, which carries the same payload). CSS runs // against tsv, so those two are quoted in that direction. @@ -183,15 +189,11 @@ coverage on deliberately hard test suites.

      - This page compares tsv to Prettier, and to Oxc and - Biome, similar tools with more features and wider - language support — tsv doesn't support JSX/TSX/SCSS/etc., and it has only one formatting - style. Also compared: rsvelte (Svelte - parser and formatter), Yuku and - SWC (TypeScript/JS parsers), - dprint (TypeScript/JS formatter), - Malva (CSS formatter), and - PostCSS (CSS parser). + This page compares tsv to Prettier, and to Oxc and Biome, similar tools with more features, + configurable styles, and wider language support. It also compares rsvelte, yuku-parser, swc, + dprint, Malva, and PostCSS; + {LANGUAGE_SECTION_TITLE} lays out what + each parses and formats.

      @@ -205,8 +207,8 @@

      Except in the CLI section, every timing here is in-process and one file at a time, isolating engine speed from multi-core parallelism. The corpus is {format_count(corpus_counts.files)} - files of real-world code (see Corpus), - timed under {node_display}; a + files of real-world code, the author's own and Svelte's (see + Corpus), timed under {node_display}; a cross-runtime comparison closes the page.

      @@ -227,12 +229,11 @@ faster than Biome, same pairings.
    • - Parsing TypeScript into JS with a span-only payload matched to Oxc's, native tsv lands - ~{parse_ts_vs_oxc} ahead of Oxc and ~{parse_ts_yuku_vs_tsv} behind yuku-parser - (~{parse_ts_yuku_vs_tsv_wasm} wasm-vs-wasm). tsv's default AST adds per-node line/column - loc for drop-in acorn and Svelte AST compatibility, at ~{parse_ts_loc_cost} - the span-only wire's time, which puts it behind Oxc (and swc, span-only in its own AST - shape). + Parsing TypeScript into JS, native tsv's span-only AST lands ~{parse_ts_vs_oxc} ahead of + Oxc and ~{parse_ts_yuku_vs_tsv} behind yuku-parser. tsv's default AST adds per-node + line/column loc for drop-in acorn and Svelte compatibility, at + ~{parse_ts_loc_cost} the span-only wire's time, which puts it behind Oxc (and swc, + span-only in its own AST shape).
    • Parsing Svelte, that default loc-bearing AST lands in JS @@ -346,8 +347,8 @@ The dprint entry is dprint-plugin-typescript, the engine deno fmt runs for TypeScript and JS, loaded in-process as its wasm - plugin. It rejects CSS and Svelte, and no dprint markup plugin is wired in, so it has no - Svelte row and its CSS slot goes to + plugin. It formats only TypeScript and JS, and no dprint markup plugin is wired in, so + it has no Svelte row and its CSS slot goes to Malva, a third-party CSS plugin for the same host. This times the engine, not the deno fmt CLI.
    • @@ -367,8 +368,6 @@ - -

      @@ -451,83 +450,100 @@ + + + + + + +

      - The size of each tool's artifact, grouped by what it does. Size matters most in the browser. - Bars and ratios are raw on-disk bytes; the gz annotation beside each is the - gzipped size, the better estimate of a download. Each group mixes JS, wasm, and native - builds under one anchor, so compare like with like. + The size of each tool's artifact, split by where it runs and grouped by what it does. Bars + and ratios are raw bytes, which track what a runtime compiles or parses and what sits on + disk; the gz beside each estimates the download. tsv-wasm, + tsv (napi), and tsv (ffi) are tsv's full builds, parser and + formatter for Svelte, TypeScript/JS, and CSS in one artifact, beside format-only and + parse-only subsets.

      - - + + + + + + + + + +
      @@ -607,9 +623,9 @@ {format_count_maybe(corpus_counts.standalone_css)} standalone files.
    • - The corpus is dominated by the author's own code plus Svelte's, the same code tsv is - developed and tested against and mostly tsv-formatted already, so every ratio here is "on - this corpus", not a universal figure. + The corpus is the author's own code plus Svelte's, the same code tsv is developed and + tested against and mostly tsv-formatted already, so every ratio here is "on this corpus", + not a universal figure.
    diff --git a/src/routes/docs/benchmarks/BenchmarksCliSection.svelte b/src/routes/docs/benchmarks/BenchmarksCliSection.svelte index e58c5fd..5a1a221 100644 --- a/src/routes/docs/benchmarks/BenchmarksCliSection.svelte +++ b/src/routes/docs/benchmarks/BenchmarksCliSection.svelte @@ -138,7 +138,8 @@ RSS comes from a separate pass without warmups, as many runs as the timed one, and counts the largest single process in each command's tree, not the sum, so a row that launches a native binary from Node — Biome's, rsvelte-fmt's, and tsv's dispatcher — is understated: the - smaller processes in its tree don't count, which for tsv's dispatcher is the binary itself. + smaller processes in its tree don't count, so the dispatcher row reads Node's peak, not the + binary's.
  • As in-process, every formatter is pinned to tsv's style in its own dialect — outputs still diff --git a/src/routes/docs/benchmarks/BenchmarksSizes.svelte b/src/routes/docs/benchmarks/BenchmarksSizes.svelte index 43b7769..deebc08 100644 --- a/src/routes/docs/benchmarks/BenchmarksSizes.svelte +++ b/src/routes/docs/benchmarks/BenchmarksSizes.svelte @@ -1,20 +1,16 @@ -{#each size_groups as group (group.capability)} +{#each groups as group (group.capability)}
    -

    {group.heading}

    + +

    {group.heading}

    {/each} diff --git a/src/routes/docs/benchmarks/BenchmarksTools.svelte b/src/routes/docs/benchmarks/BenchmarksTools.svelte new file mode 100644 index 0000000..b4b8a1a --- /dev/null +++ b/src/routes/docs/benchmarks/BenchmarksTools.svelte @@ -0,0 +1,113 @@ + + +
    + + + + + {#each TOOL_LANGUAGES as language (language)} + + {/each} + + + + + {#each rows as row (row.name)} + + + {#each TOOL_LANGUAGES as language (language)} + {@const cells = row.cells[language]} + + {/each} + + + {/each} + +
    tool{TOOL_LANGUAGE_LABELS[language]}other
    + {#if row.url} + + {row.name} + {:else} + {row.name} + {/if} + + {#each cells as cell, i (cell.operation)} + + {i > 0 ? '; ' : ''}{to_label(cell)} + + {:else} + none + {/each} + {row.other ?? ''}
    +
    +

    + + P parses to an AST in JS, F formats; bold is timed on this page, faded is + supported but not timed here. + {#each footnotes as footnote, i (footnote)} + {i + 1} {TOOL_FOOTNOTES[footnote]}{i < footnotes.length - 1 ? '; ' : '.'} + {/each} + +

    + + diff --git a/src/routes/docs/benchmarks/benchmark_data.ts b/src/routes/docs/benchmarks/benchmark_data.ts index 415486e..73683f5 100644 --- a/src/routes/docs/benchmarks/benchmark_data.ts +++ b/src/routes/docs/benchmarks/benchmark_data.ts @@ -518,7 +518,7 @@ export const derive_benchmark_groups = (baseline: BenchmarkBaseline): Array e.mean_ns ?? 0)); diff --git a/src/routes/docs/benchmarks/benchmark_sizes.ts b/src/routes/docs/benchmarks/benchmark_sizes.ts index c5f5d9f..59f7af6 100644 --- a/src/routes/docs/benchmarks/benchmark_sizes.ts +++ b/src/routes/docs/benchmarks/benchmark_sizes.ts @@ -1,7 +1,7 @@ -// The binary-size domain of the benchmarks page: category and capability -// grouping, and the synthesized combined builds. The report shapes these read live -// in `benchmark_data.ts`; the ratio color scale is `benchmark_baseline.ts`'s -// shared `baseline_ratio_color`. +// The binary-size domain of the benchmarks page: category, the browser/native +// target split, capability grouping, and the synthesized combined oxc build. The +// report shapes these read live in `benchmark_data.ts`; the ratio color scale is +// `benchmark_baseline.ts`'s shared `baseline_ratio_color`. import type { BinarySize, ImplementationCategory } from './benchmark_data.ts'; @@ -48,10 +48,10 @@ export type SizeCapability = 'full' | 'formatter' | 'parser'; * * - `dprint` and `malva` are the SAME kind of artifact and must land in the same * bucket: both are dprint plugins loaded over the one `@dprint/formatter` host, - * and neither exposes a parser. dprint's covers TypeScript/JS, malva's CSS — - * each a slice of what tsv's format-only build does, so pair both against - * `tsv-format-wasm`: malva's smaller size there is scope, while dprint is larger - * despite it. + * and neither exposes a parser. dprint's covers TypeScript/JS and JSX, malva's + * CSS and its dialects — each one of tsv's three languages plus syntax tsv + * doesn't format, so pair both against `tsv-format-wasm`: malva's smaller size + * there is scope, while dprint is larger despite it. * - `swc` and rsvelte's addon back parse rows and ship no formatter. Both are far * wider than what the rows measure — swc's `.node` is an entire compiler * (transforms, minifier, bundler) and rsvelte's carries the compiler plus @@ -117,6 +117,16 @@ export interface SizeCapabilityGroup { entries: Array; } +/** + * Where a build runs, the size section's first split: a browser loads only wasm + * and JS, so those builds stand apart from the native addons and binaries. A + * browser group still mixes wasm and JS, which compress differently. + */ +export type SizeTarget = 'browser' | 'native'; + +export const to_size_target = (size: Pick): SizeTarget => + size.kind === 'native' ? 'native' : 'browser'; + const SIZE_CAPABILITY_ORDER: ReadonlyArray<{ capability: SizeCapability; heading: string; @@ -126,7 +136,7 @@ const SIZE_CAPABILITY_ORDER: ReadonlyArray<{ { capability: 'parser', heading: 'Parser' } ]; -/** The measured oxfmt native addon — the label the tsv harness emits, half of both synthesized sums. */ +/** The measured oxfmt native addon — the label the tsv harness emits, half of the synthesized oxc sum. */ export const OXFMT_NATIVE_LABEL = 'oxfmt (napi)'; /** The measured oxc-parser native addon — the label the tsv harness emits. */ @@ -135,102 +145,79 @@ const OXC_PARSER_NATIVE_LABEL = 'oxc-parser (napi)'; /** Display label for the synthesized combined oxc full-toolchain build. */ export const OXC_FULL_LABEL = 'oxc-parser + oxfmt (napi)'; -/** Display label for oxfmt's absent wasm build placeholder — see `derive_size_groups`. */ +/** Display label for oxfmt's absent wasm build placeholder — see `derive_size_targets`. */ export const OXFMT_WASM_LABEL = 'oxfmt (wasm)'; -/** - * A synthesized native entry summing two measured builds — `undefined` when - * either is missing (an artifact the report didn't size), gzip summed only when - * both carry it. - */ -const sum_binary_sizes = ( - sizes: Array, - label: string, - label_a: string, - label_b: string -): BinarySize | undefined => { - const a = sizes.find((s) => s.label === label_a); - const b = sizes.find((s) => s.label === label_b); - if (!a || !b) return undefined; - return { - label, - bytes: a.bytes + b.bytes, - kind: 'native', - gzip_bytes: a.gzip_bytes != null && b.gzip_bytes != null ? a.gzip_bytes + b.gzip_bytes : null - }; -}; +/** The rsvelte-fmt binary on its own — the label the tsv harness emits. */ +export const RSVELTE_LABEL = 'rsvelte-fmt (binary)'; /** * Synthesizes oxc's full-toolchain native build by summing its separately-shipped * parser (`oxc-parser (napi)`) and formatter (`oxfmt (napi)`) packages — together * they're the closest equivalent to tsv's single parse+format build, so the entry - * stands beside `tsv (napi)` in the full-toolchain group. Returns `undefined` when - * either half is missing, and sums gzip only when both carry it. + * stands beside `tsv (napi)` in the native full-toolchain group. Returns + * `undefined` when either half is missing, and sums gzip only when both carry it. */ -const synthesize_oxc_full = (sizes: Array): BinarySize | undefined => - sum_binary_sizes(sizes, OXC_FULL_LABEL, OXC_PARSER_NATIVE_LABEL, OXFMT_NATIVE_LABEL); - -/** The rsvelte-fmt binary on its own — the label the tsv harness emits. */ -export const RSVELTE_LABEL = 'rsvelte-fmt (binary)'; - -/** Display label for the rsvelte-fmt + oxfmt install — see `synthesize_rsvelte_install`. */ -export const RSVELTE_INSTALL_LABEL = 'rsvelte-fmt + oxfmt (binary)'; - -/** - * Synthesizes what installing rsvelte-fmt to format a project actually costs, by - * summing its own binary with the `oxfmt` it declares as a peer dependency. - * - * Both figures are shown because which one is honest depends on how you invoke - * it, and the difference is verifiable: pointed at a **single `.svelte` file** (or - * stdin) rsvelte-fmt needs no oxfmt at all — it formats the embedded - * ` diff --git a/src/routes/docs/benchmarks/benchmarks_cli.ts b/src/routes/docs/benchmarks/benchmarks_cli.ts index 3c88a0a..0ce3fe1 100644 --- a/src/routes/docs/benchmarks/benchmarks_cli.ts +++ b/src/routes/docs/benchmarks/benchmarks_cli.ts @@ -63,6 +63,12 @@ export interface CliScenario extends CliScenarioCopy { target: string; /** Which revision of the corpus the numbers came from, as the harness records it. */ corpus: string; + /** + * Every formatter the scenario benched, as displayed, in the harness's order — + * timed or only preflight-checked. An abort before timing empties `results` + * but not this, so it's what says who the scenario is between. + */ + labels: Array; /** * Results ascending by wall-clock time. The component computes each ratio * against its table's anchor row — the dispatcher row facing other tools, native @@ -115,8 +121,8 @@ export const CLI_TSV_LABEL = 'tsv'; /** * The tsv-vs-rsvelte-fmt Svelte scenario's id. The harness publishes it aborted - * whenever rsvelte-fmt's nondeterministic crash hits its preflight, so prose - * quoting its ratios must be conditional on them resolving. + * if rsvelte-fmt crashes, which it has done in preflight, so prose quoting its + * ratios must be conditional on them resolving. */ export const CLI_SVELTE_KEY = 'svelte-tsv-vs-rsvelte-fmt'; @@ -180,7 +186,7 @@ const SCENARIO_COPY: Record = { description: 'Two Rust Svelte-native formatters head-to-head on a third-party .svelte corpus, rsvelte-fmt configured to tsv’s fixed style. Its time includes the Oxfmt it launches for non-.svelte files, which walks the corpus and finds none.', abort_context: - 'rsvelte-fmt’s crash on this corpus is nondeterministic, and the harness doesn’t retry.', + 'rsvelte-fmt 0.7.x can abort when its output and stderr share a pipe, and the harness doesn’t retry.', tsv_only: false }, [CLI_DELIVERY_KEY]: { @@ -200,10 +206,16 @@ const CLI_LABELS: Record = { 'tsv-npm': CLI_TSV_NPM_LABEL }; +const to_label = (name: string): string => CLI_LABELS[name] ?? name; + +const to_labels = (scenario: FormatterScenario): Array => [ + ...new Set([...scenario.preflight, ...scenario.timings].map((entry) => to_label(entry.name))) +]; + const to_results = (scenario: FormatterScenario): Array => scenario.timings .map((timing) => ({ - label: CLI_LABELS[timing.name] ?? timing.name, + label: to_label(timing.name), wall_ms: timing.mean_ms, cpu_ms: timing.user_ms + timing.system_ms, memory_mb: scenario.memory.find((m) => m.name === timing.name)?.mean_mb ?? null @@ -227,7 +239,7 @@ export const CLI_SCENARIO_KEYS = Object.keys(SCENARIO_COPY); export const to_abort_note = (scenario: FormatterScenario): string => { if (scenario.timings.length) return `Timed, but no memory was published: ${scenario.aborted}.`; const faults = scenario.preflight.flatMap((entry) => { - const label = CLI_LABELS[entry.name] ?? entry.name; + const label = to_label(entry.name); if (entry.crashed) return [`${label} crashed partway through its preflight check`]; if (entry.unavailable) return [`${label} could not run`]; if (entry.rejected > 0) return [`${label} rejected ${entry.rejected} files`]; @@ -241,11 +253,20 @@ export const to_abort_note = (scenario: FormatterScenario): string => { * bin shim the other rows pay for. */ export const to_unshimmed_note = (names: Array): string => - `${names.map((name) => CLI_LABELS[name] ?? name).join(' and ')} ran as a bare Node script, skipping the few milliseconds of pnpm bin shim the other tools’ rows go through.`; + `${names.map(to_label).join(' and ')} ran as a bare Node script, skipping the few milliseconds of pnpm bin shim the other tools’ rows go through.`; -const to_scenarios = (): Array => +/** + * A report's scenarios shaped for the tables, in `SCENARIO_COPY`'s order — the + * ones it has copy for, timed or aborted. + * + * @param report - the validated formatter report + * @returns the scenarios the page renders + */ +export const to_cli_scenarios = ( + report: Pick +): Array => Object.entries(SCENARIO_COPY).flatMap(([key, copy]) => { - const scenario = benchmarks_formatters_json.scenarios.find((s) => s.id === key); + const scenario = report.scenarios.find((s) => s.id === key); return scenario ? [ { @@ -253,6 +274,7 @@ const to_scenarios = (): Array => ...copy, target: scenario.target, corpus: scenario.corpus, + labels: to_labels(scenario), results: to_results(scenario), warmup_runs: scenario.warmup_runs, benchmark_runs: scenario.benchmark_runs, @@ -268,7 +290,7 @@ const to_scenarios = (): Array => export const benchmarks_cli: BenchmarksCliReport = { ...benchmarks_formatters_json, - scenarios: to_scenarios() + scenarios: to_cli_scenarios(benchmarks_formatters_json) }; /** diff --git a/src/routes/docs/benchmarks/benchmarks_formatters.json b/src/routes/docs/benchmarks/benchmarks_formatters.json index 1a54428..e3c8cdc 100644 --- a/src/routes/docs/benchmarks/benchmarks_formatters.json +++ b/src/routes/docs/benchmarks/benchmarks_formatters.json @@ -1,7 +1,7 @@ { - "timestamp": "2026-09-20T11:59:28.000Z", - "git_commit": "d9475fd", - "git_dirty": true, + "timestamp": "2026-09-23T19:54:13.835Z", + "git_commit": "4a703e9", + "git_dirty": false, "machine": { "cpu_model": "AMD Ryzen 5 PRO 7530U with Radeon Graphics", "threads": 12, @@ -9,8 +9,8 @@ "arch": "x86_64" }, "node_startup": { - "mean_ms": 18.814, - "stddev_ms": 0.667, + "mean_ms": 18.873, + "stddev_ms": 0.813, "runs": 20 }, "versions": { @@ -76,133 +76,133 @@ "timings": [ { "name": "prettier", - "mean_ms": 1605.852, - "stddev_ms": 32.447, - "user_ms": 1539.744, - "system_ms": 868.999, - "min_ms": 1544.885, - "max_ms": 1665.654 + "mean_ms": 1610.831, + "stddev_ms": 24.323, + "user_ms": 1534.545, + "system_ms": 881.75, + "min_ms": 1558.018, + "max_ms": 1659.518 }, { "name": "prettier+oxc-parser", - "mean_ms": 972.875, - "stddev_ms": 11.401, - "user_ms": 873.584, - "system_ms": 455.419, - "min_ms": 947.438, - "max_ms": 994.034 + "mean_ms": 973.566, + "stddev_ms": 11.126, + "user_ms": 888.053, + "system_ms": 444.455, + "min_ms": 955.33, + "max_ms": 995.418 }, { "name": "biome", - "mean_ms": 107.907, - "stddev_ms": 1.196, - "user_ms": 82.431, - "system_ms": 32.753, - "min_ms": 106.329, - "max_ms": 110.366 + "mean_ms": 107.927, + "stddev_ms": 1.481, + "user_ms": 78.971, + "system_ms": 35.803, + "min_ms": 105.531, + "max_ms": 110.75 }, { "name": "oxfmt", - "mean_ms": 62.224, - "stddev_ms": 1.992, - "user_ms": 42.66, - "system_ms": 52.267, - "min_ms": 59.599, - "max_ms": 65.957 + "mean_ms": 62.194, + "stddev_ms": 1.944, + "user_ms": 43.919, + "system_ms": 50.357, + "min_ms": 59.702, + "max_ms": 65.883 }, { "name": "tsv-npm", - "mean_ms": 46.872, - "stddev_ms": 0.957, - "user_ms": 31.106, - "system_ms": 18.168, - "min_ms": 45.32, - "max_ms": 48.903 + "mean_ms": 46.58, + "stddev_ms": 0.67, + "user_ms": 28.674, + "system_ms": 19.981, + "min_ms": 44.852, + "max_ms": 47.621 }, { "name": "tsv", - "mean_ms": 16.6, - "stddev_ms": 0.348, - "user_ms": 11.11, - "system_ms": 5.471, - "min_ms": 15.963, - "max_ms": 17.197 + "mean_ms": 16.525, + "stddev_ms": 0.419, + "user_ms": 10.96, + "system_ms": 5.539, + "min_ms": 15.822, + "max_ms": 17.222 } ], "fastest": "tsv", "speedups": [ { "name": "tsv-npm", - "ratio": 2.8237, - "ratio_stddev": 0.0826 + "ratio": 2.8187, + "ratio_stddev": 0.0822 }, { "name": "oxfmt", - "ratio": 3.7485, - "ratio_stddev": 0.1434 + "ratio": 3.7635, + "ratio_stddev": 0.1515 }, { "name": "biome", - "ratio": 6.5006, - "ratio_stddev": 0.154 + "ratio": 6.531, + "ratio_stddev": 0.1882 }, { "name": "prettier+oxc-parser", - "ratio": 58.6086, - "ratio_stddev": 1.4064 + "ratio": 58.913, + "ratio_stddev": 1.638 }, { "name": "prettier", - "ratio": 96.7407, - "ratio_stddev": 2.8151 + "ratio": 97.4756, + "ratio_stddev": 2.8759 } ], "memory": [ { "name": "prettier", - "mean_mb": 305.357, - "min_mb": 292.754, - "max_mb": 321.68, - "ratio": 22.7454, - "ratio_stddev": 0.6576 + "mean_mb": 305.035, + "min_mb": 292.613, + "max_mb": 316.934, + "ratio": 22.8284, + "ratio_stddev": 0.5397 }, { "name": "prettier+oxc-parser", - "mean_mb": 196.601, - "min_mb": 193.777, - "max_mb": 199.332, - "ratio": 14.6444, - "ratio_stddev": 0.2302 + "mean_mb": 196.414, + "min_mb": 192.91, + "max_mb": 198.449, + "ratio": 14.6993, + "ratio_stddev": 0.2081 }, { "name": "biome", - "mean_mb": 95.25, - "min_mb": 92.715, - "max_mb": 99.473, - "ratio": 7.095, - "ratio_stddev": 0.1719 + "mean_mb": 95.679, + "min_mb": 93.781, + "max_mb": 99.523, + "ratio": 7.1605, + "ratio_stddev": 0.1693 }, { "name": "oxfmt", - "mean_mb": 114.037, - "min_mb": 113.875, - "max_mb": 114.199, - "ratio": 8.4944, - "ratio_stddev": 0.1147 + "mean_mb": 114.055, + "min_mb": 113.844, + "max_mb": 114.316, + "ratio": 8.5357, + "ratio_stddev": 0.1005 }, { "name": "tsv-npm", - "mean_mb": 49.578, - "min_mb": 49.457, - "max_mb": 49.77, - "ratio": 3.6929, - "ratio_stddev": 0.0502 + "mean_mb": 49.489, + "min_mb": 49.285, + "max_mb": 49.629, + "ratio": 3.7037, + "ratio_stddev": 0.044 }, { "name": "tsv", - "mean_mb": 13.425, - "min_mb": 13.078, - "max_mb": 13.82 + "mean_mb": 13.362, + "min_mb": 13.133, + "max_mb": 13.684 } ] }, @@ -255,133 +255,133 @@ "timings": [ { "name": "prettier", - "mean_ms": 8320.585, - "stddev_ms": 100.078, - "user_ms": 13813.618, - "system_ms": 951.963, - "min_ms": 8188.222, - "max_ms": 8506.132 + "mean_ms": 8321.663, + "stddev_ms": 109.842, + "user_ms": 13853.138, + "system_ms": 927.474, + "min_ms": 8175.041, + "max_ms": 8502.97 }, { "name": "prettier+oxc-parser", - "mean_ms": 6863.006, - "stddev_ms": 79.402, - "user_ms": 8808.885, - "system_ms": 578.887, - "min_ms": 6727.173, - "max_ms": 6993.49 + "mean_ms": 6855.327, + "stddev_ms": 64.924, + "user_ms": 8796.413, + "system_ms": 551.473, + "min_ms": 6741.877, + "max_ms": 6950.061 }, { "name": "biome", - "mean_ms": 300.739, - "stddev_ms": 1.506, - "user_ms": 2182.799, - "system_ms": 218.699, - "min_ms": 298.985, - "max_ms": 303.453 + "mean_ms": 300.191, + "stddev_ms": 1.938, + "user_ms": 2159.353, + "system_ms": 232.543, + "min_ms": 297.5, + "max_ms": 302.535 }, { "name": "oxfmt", - "mean_ms": 116.707, - "stddev_ms": 3.15, - "user_ms": 534.553, - "system_ms": 268.32, - "min_ms": 113.769, - "max_ms": 123.631 + "mean_ms": 116.146, + "stddev_ms": 1.188, + "user_ms": 531.178, + "system_ms": 253.286, + "min_ms": 114.379, + "max_ms": 118.463 }, { "name": "tsv-npm", - "mean_ms": 75.831, - "stddev_ms": 0.538, - "user_ms": 289.156, - "system_ms": 130.72, - "min_ms": 75.215, - "max_ms": 76.649 + "mean_ms": 76.239, + "stddev_ms": 1.387, + "user_ms": 299.22, + "system_ms": 120.432, + "min_ms": 74.166, + "max_ms": 79.353 }, { "name": "tsv", - "mean_ms": 45.284, - "stddev_ms": 0.363, - "user_ms": 272.554, - "system_ms": 114.004, - "min_ms": 44.87, - "max_ms": 46.037 + "mean_ms": 45.356, + "stddev_ms": 0.854, + "user_ms": 262.09, + "system_ms": 122.535, + "min_ms": 44.685, + "max_ms": 47.562 } ], "fastest": "tsv", "speedups": [ { "name": "tsv-npm", - "ratio": 1.6746, - "ratio_stddev": 0.0179 + "ratio": 1.6809, + "ratio_stddev": 0.044 }, { "name": "oxfmt", - "ratio": 2.5772, - "ratio_stddev": 0.0726 + "ratio": 2.5608, + "ratio_stddev": 0.0549 }, { "name": "biome", - "ratio": 6.6412, - "ratio_stddev": 0.0627 + "ratio": 6.6186, + "ratio_stddev": 0.1318 }, { "name": "prettier+oxc-parser", - "ratio": 151.5544, - "ratio_stddev": 2.1326 + "ratio": 151.1453, + "ratio_stddev": 3.1868 }, { "name": "prettier", - "ratio": 183.7419, - "ratio_stddev": 2.6551 + "ratio": 183.4749, + "ratio_stddev": 4.2202 } ], "memory": [ { "name": "prettier", - "mean_mb": 436.411, - "min_mb": 360.496, - "max_mb": 482.93, - "ratio": 20.8993, - "ratio_stddev": 1.9226 + "mean_mb": 451.168, + "min_mb": 398.137, + "max_mb": 479.316, + "ratio": 21.7733, + "ratio_stddev": 1.1482 }, { "name": "prettier+oxc-parser", - "mean_mb": 306.598, - "min_mb": 300.547, - "max_mb": 324.398, - "ratio": 14.6827, - "ratio_stddev": 0.4043 + "mean_mb": 304.773, + "min_mb": 298.586, + "max_mb": 321.84, + "ratio": 14.7083, + "ratio_stddev": 0.4809 }, { "name": "biome", - "mean_mb": 145.582, - "min_mb": 141.539, - "max_mb": 149.473, - "ratio": 6.9718, - "ratio_stddev": 0.1752 + "mean_mb": 146.032, + "min_mb": 141.949, + "max_mb": 147.848, + "ratio": 7.0475, + "ratio_stddev": 0.1871 }, { "name": "oxfmt", - "mean_mb": 227.086, - "min_mb": 214.078, - "max_mb": 235.055, - "ratio": 10.8749, - "ratio_stddev": 0.3853 + "mean_mb": 227.186, + "min_mb": 218.711, + "max_mb": 230.93, + "ratio": 10.964, + "ratio_stddev": 0.3134 }, { "name": "tsv-npm", - "mean_mb": 49.405, - "min_mb": 47.609, - "max_mb": 49.875, - "ratio": 2.366, - "ratio_stddev": 0.0502 + "mean_mb": 49.525, + "min_mb": 49.336, + "max_mb": 49.75, + "ratio": 2.3901, + "ratio_stddev": 0.0567 }, { "name": "tsv", - "mean_mb": 20.882, - "min_mb": 20.418, - "max_mb": 21.535 + "mean_mb": 20.721, + "min_mb": 19.836, + "max_mb": 21.52 } ] }, @@ -416,67 +416,67 @@ "timings": [ { "name": "rsvelte-fmt", - "mean_ms": 190.867, - "stddev_ms": 7.143, - "user_ms": 833.243, - "system_ms": 697.64, - "min_ms": 180.553, - "max_ms": 201.439 + "mean_ms": 195.538, + "stddev_ms": 7.94, + "user_ms": 843.975, + "system_ms": 696.12, + "min_ms": 185.312, + "max_ms": 206.074 }, { "name": "tsv-npm", - "mean_ms": 72.084, - "stddev_ms": 0.557, - "user_ms": 253.354, - "system_ms": 137.164, - "min_ms": 71.136, - "max_ms": 72.674 + "mean_ms": 71.424, + "stddev_ms": 1.036, + "user_ms": 248.09, + "system_ms": 138.878, + "min_ms": 70.17, + "max_ms": 73.229 }, { "name": "tsv", - "mean_ms": 40.834, - "stddev_ms": 0.343, - "user_ms": 227.619, - "system_ms": 125.105, - "min_ms": 40.202, - "max_ms": 41.492 + "mean_ms": 41.019, + "stddev_ms": 0.22, + "user_ms": 220.822, + "system_ms": 134.057, + "min_ms": 40.695, + "max_ms": 41.431 } ], "fastest": "tsv", "speedups": [ { "name": "tsv-npm", - "ratio": 1.7653, - "ratio_stddev": 0.0202 + "ratio": 1.7413, + "ratio_stddev": 0.0269 }, { "name": "rsvelte-fmt", - "ratio": 4.6742, - "ratio_stddev": 0.1793 + "ratio": 4.7671, + "ratio_stddev": 0.1952 } ], "memory": [ { "name": "rsvelte-fmt", - "mean_mb": 137.258, - "min_mb": 121.148, - "max_mb": 153.566, - "ratio": 10.5327, - "ratio_stddev": 0.6845 + "mean_mb": 139.36, + "min_mb": 125.355, + "max_mb": 151.457, + "ratio": 10.8441, + "ratio_stddev": 0.6879 }, { "name": "tsv-npm", - "mean_mb": 49.526, - "min_mb": 49.34, - "max_mb": 49.73, - "ratio": 3.8004, - "ratio_stddev": 0.0666 + "mean_mb": 49.352, + "min_mb": 47.539, + "max_mb": 49.805, + "ratio": 3.8403, + "ratio_stddev": 0.1047 }, { "name": "tsv", - "mean_mb": 13.032, - "min_mb": 12.555, - "max_mb": 13.34 + "mean_mb": 12.851, + "min_mb": 12.363, + "max_mb": 13.285 } ] }, @@ -511,67 +511,67 @@ "timings": [ { "name": "tsv-wasm", - "mean_ms": 150.565, - "stddev_ms": 2.295, - "user_ms": 325.249, - "system_ms": 53.33, - "min_ms": 147.247, - "max_ms": 155.583 + "mean_ms": 152.548, + "stddev_ms": 4.212, + "user_ms": 324.518, + "system_ms": 54.87, + "min_ms": 147.628, + "max_ms": 166.939 }, { "name": "tsv-npm", - "mean_ms": 47.546, - "stddev_ms": 0.914, - "user_ms": 27.621, - "system_ms": 22.226, - "min_ms": 45.807, - "max_ms": 49.54 + "mean_ms": 47.333, + "stddev_ms": 0.894, + "user_ms": 27.483, + "system_ms": 22.191, + "min_ms": 45.822, + "max_ms": 49.649 }, { "name": "tsv", - "mean_ms": 17.071, - "stddev_ms": 0.353, - "user_ms": 10.939, - "system_ms": 6.098, - "min_ms": 16.549, - "max_ms": 18.041 + "mean_ms": 16.623, + "stddev_ms": 0.529, + "user_ms": 10.979, + "system_ms": 5.608, + "min_ms": 15.856, + "max_ms": 18.003 } ], "fastest": "tsv", "speedups": [ { "name": "tsv-npm", - "ratio": 2.7851, - "ratio_stddev": 0.0787 + "ratio": 2.8475, + "ratio_stddev": 0.1054 }, { "name": "tsv-wasm", - "ratio": 8.8197, - "ratio_stddev": 0.2266 + "ratio": 9.1771, + "ratio_stddev": 0.3868 } ], "memory": [ { "name": "tsv-wasm", - "mean_mb": 117.414, - "min_mb": 112.699, - "max_mb": 120.125, - "ratio": 8.775, - "ratio_stddev": 0.1558 + "mean_mb": 116.95, + "min_mb": 111.496, + "max_mb": 121.719, + "ratio": 8.7442, + "ratio_stddev": 0.2139 }, { "name": "tsv-npm", - "mean_mb": 49.447, - "min_mb": 47.574, - "max_mb": 49.684, - "ratio": 3.6954, - "ratio_stddev": 0.0488 + "mean_mb": 49.606, + "min_mb": 49.332, + "max_mb": 49.891, + "ratio": 3.709, + "ratio_stddev": 0.041 }, { "name": "tsv", - "mean_mb": 13.38, - "min_mb": 13.129, - "max_mb": 13.594 + "mean_mb": 13.375, + "min_mb": 13.098, + "max_mb": 13.625 } ] } diff --git a/src/routes/docs/benchmarks/formatter_benchmark_data.ts b/src/routes/docs/benchmarks/formatter_benchmark_data.ts index 479109c..991cf3a 100644 --- a/src/routes/docs/benchmarks/formatter_benchmark_data.ts +++ b/src/routes/docs/benchmarks/formatter_benchmark_data.ts @@ -105,11 +105,11 @@ export const FormatterScenario = z.strictObject({ unshimmed: z.array(z.string().min(1)).min(1).optional(), timings: z.array(FormatterTiming), /** - * The fastest timed formatter, and its margin over each other one; `''` when + * The fastest timed formatter, and its margin over each other one; absent when * nothing was timed. Not the memory rows' anchor, which the harness fixes per * scenario and marks by leaving that row without a `ratio`. */ - fastest: z.string(), + fastest: z.string().min(1).optional(), speedups: z.array(FormatterSpeedup), /** Empty without GNU time, and when an abort kept the memory pass from finishing. */ memory: z.array(FormatterMemory) @@ -188,7 +188,8 @@ const scenario_has_tsv = (scenario: FormatterScenario): boolean => * @param results - the parsed `results.json` * @returns the validated benchmarks, tsv's scenarios only * @throws if the report doesn't match `FormatterBenchmarks`, a scenario carries - * neither timings nor an abort, no scenario timed tsv, or the versions list lacks tsv + * neither timings nor an abort or a `fastest` that disagrees with its timings, no + * scenario timed tsv, or the versions list lacks tsv */ export const parse_formatter_benchmarks = (results: unknown): FormatterBenchmarks => { const parsed = FormatterBenchmarks.safeParse(results); @@ -203,6 +204,12 @@ export const parse_formatter_benchmarks = (results: unknown): FormatterBenchmark if (scenario.timings.length === 0 && scenario.aborted === undefined) { throw new Error(`formatter benchmarks: scenario "${scenario.name}" has no timings`); } + // `fastest` names a timed row, so it is present exactly when rows were timed + if ((scenario.fastest === undefined) !== (scenario.timings.length === 0)) { + throw new Error( + `formatter benchmarks: scenario "${scenario.name}" has ${scenario.timings.length} timings but fastest ${JSON.stringify(scenario.fastest)}` + ); + } } // tsv has no JSX/TSX parser, so it sits out some scenarios by design — but if it diff --git a/src/test/benchmark_test_helpers.ts b/src/test/benchmark_test_helpers.ts index deeb953..7b23ea4 100644 --- a/src/test/benchmark_test_helpers.ts +++ b/src/test/benchmark_test_helpers.ts @@ -126,3 +126,19 @@ export const create_formatter_scenario = ( ], ...overrides }); + +/** + * A scenario that never reached timing — no timings, speedups, or memory, and no + * `fastest` key, as the harness records one. + */ +export const create_untimed_formatter_scenario = ( + overrides: Partial = {} +): FormatterScenario => { + const { fastest: _, ...scenario } = create_formatter_scenario({ + timings: [], + speedups: [], + memory: [], + ...overrides + }); + return scenario; +}; diff --git a/src/test/benchmark_tools.shape.test.ts b/src/test/benchmark_tools.shape.test.ts index 0c7f3b0..f43bbb7 100644 --- a/src/test/benchmark_tools.shape.test.ts +++ b/src/test/benchmark_tools.shape.test.ts @@ -18,9 +18,9 @@ describe('the language-support matrix reads the reports', () => { test('every report row a tool lists is in the report, and every CLI label in a scenario', () => { const names = new Set(benchmarks_json.entries.map((e) => e.name)); - const cli_labels = new Set( - benchmarks_cli.scenarios.flatMap((s) => s.results.map((r) => r.label)) - ); + // a scenario's roster rather than its timed rows: a scenario published + // aborted still names the tools it didn't time + const cli_labels = new Set(benchmarks_cli.scenarios.flatMap((s) => s.labels)); for (const tool of TOOL_SUPPORT) { for (const name of Object.values(tool.rows).flat()) { assert.ok(names.has(name), `${tool.name}: no report row ${name}`); diff --git a/src/test/benchmark_tools.test.ts b/src/test/benchmark_tools.test.ts index 43ada2f..456a3f7 100644 --- a/src/test/benchmark_tools.test.ts +++ b/src/test/benchmark_tools.test.ts @@ -20,6 +20,7 @@ const scenario = (key: string, labels: Array, tsv_only = false): CliScen tsv_only, target: '', corpus: '', + labels, results: labels.map((label) => ({ label, wall_ms: 1, cpu_ms: 1, memory_mb: 1 })), warmup_runs: 3, benchmark_runs: 10 diff --git a/src/test/benchmarks_cli.test.ts b/src/test/benchmarks_cli.test.ts index 732d605..ae28af6 100644 --- a/src/test/benchmarks_cli.test.ts +++ b/src/test/benchmarks_cli.test.ts @@ -12,7 +12,9 @@ import { CLI_TSV_NPM_LABEL, CLI_TSV_WASM_LABEL, to_abort_note, + to_cli_scenarios, to_unshimmed_note, + CLI_SVELTE_KEY, type CliFormatterResult, type CliScenario } from '$routes/docs/benchmarks/benchmarks_cli.ts'; @@ -21,19 +23,16 @@ import type { FormatterScenario } from '$routes/docs/benchmarks/formatter_benchm import { create_formatter_preflight, create_formatter_scenario, - create_formatter_timing + create_formatter_timing, + create_untimed_formatter_scenario } from './benchmark_test_helpers.ts'; describe('to_abort_note', () => { // aborted before timing, until a test gives it rows const scenario = (overrides: Partial): FormatterScenario => - create_formatter_scenario({ + create_untimed_formatter_scenario({ preflight: [], aborted: 'harness said so', - timings: [], - fastest: '', - speedups: [], - memory: [], ...overrides }); const preflight = create_formatter_preflight; @@ -75,6 +74,42 @@ describe('to_abort_note', () => { }); }); +describe('to_cli_scenarios', () => { + test('a scenario aborted before timing keeps its roster and its abort, with no rows', () => { + // the harness publishes the Svelte head-to-head aborted if rsvelte-fmt + // crashes in preflight, the shape it has shipped in before + const aborted = create_untimed_formatter_scenario({ + id: CLI_SVELTE_KEY, + preflight: [ + create_formatter_preflight('rsvelte-fmt', { crashed: true }), + create_formatter_preflight('tsv-npm'), + create_formatter_preflight('tsv') + ], + aborted: 'crashed: rsvelte-fmt' + }); + const [svelte] = to_cli_scenarios({ scenarios: [aborted] }); + assert.ok(svelte); + assert.deepEqual(svelte.labels, ['rsvelte-fmt', CLI_TSV_NPM_LABEL, CLI_TSV_LABEL]); + assert.isEmpty(svelte.results); + assert.strictEqual( + svelte.aborted, + 'Not timed: rsvelte-fmt crashed partway through its preflight check.' + ); + assert.isUndefined(cli_default_anchor_label(svelte)); + }); + + test('a timed scenario lists each formatter once, and skips one without copy', () => { + const timed = create_formatter_scenario(); + const uncopied = create_formatter_scenario({ id: 'no-copy-for-this' }); + const scenarios = to_cli_scenarios({ scenarios: [uncopied, timed] }); + assert.deepEqual( + scenarios.map((s) => s.key), + [timed.id] + ); + assert.deepEqual(scenarios[0]!.labels, ['oxfmt', CLI_TSV_LABEL]); + }); +}); + describe('cli ratios over a scenario with two tsv rows', () => { const result = ( label: string, @@ -176,6 +211,7 @@ describe('cli claims spanning scenarios', () => { tsv_only: false, target: '', corpus: '', + labels: overrides.results?.map((r) => r.label) ?? [], results: [], warmup_runs: 3, benchmark_runs: 20, diff --git a/src/test/formatter_benchmark_data.test.ts b/src/test/formatter_benchmark_data.test.ts index 71c521d..9f5dcbc 100644 --- a/src/test/formatter_benchmark_data.test.ts +++ b/src/test/formatter_benchmark_data.test.ts @@ -10,13 +10,15 @@ import { import { create_formatter_preflight, create_formatter_scenario, - create_formatter_timing + create_formatter_timing, + create_untimed_formatter_scenario } from './benchmark_test_helpers.ts'; // one scenario tsv runs in, one it sits out const timing = create_formatter_timing; const preflight = create_formatter_preflight; const scenario = create_formatter_scenario; +const untimed = create_untimed_formatter_scenario; // an upstream scenario: JSX in the corpus, so no tsv row and no preflight const jsx_scenario = (overrides: Partial = {}): FormatterScenario => @@ -77,21 +79,18 @@ describe('parse_formatter_benchmarks', () => { }); test('keeps a scenario the harness aborted before timing, with its reason and no numbers', () => { - const aborted = scenario({ + const aborted = untimed({ id: 'svelte', name: 'Svelte', // the harness records the counts up front, so an abort keeps them warmup_runs: 3, benchmark_runs: 10, preflight: [preflight('rsvelte-fmt', { crashed: true }), preflight('tsv')], - aborted: 'crashed: rsvelte-fmt', - timings: [], - fastest: '', - speedups: [], - memory: [] + aborted: 'crashed: rsvelte-fmt' }); const parsed = parse_formatter_benchmarks(report({ scenarios: [scenario(), aborted] })); assert.deepEqual(parsed.scenarios[1], aborted); + assert.notProperty(parsed.scenarios[1], 'fastest'); }); test('keeps a scenario aborted in its memory pass, with its timings', () => { @@ -102,10 +101,9 @@ describe('parse_formatter_benchmarks', () => { }); test('drops an aborted scenario tsv was not in', () => { - const aborted = jsx_scenario({ + const { fastest: _, ...aborted } = jsx_scenario({ aborted: 'a timed run failed — Hyperfine failed with code 1', timings: [], - fastest: '', speedups: [] }); const parsed = parse_formatter_benchmarks(report({ scenarios: [scenario(), aborted] })); @@ -127,13 +125,32 @@ describe('parse_formatter_benchmarks', () => { }); test('throws when a scenario carries neither timings nor an abort', () => { - const empty = scenario({ timings: [], fastest: '', speedups: [], memory: [] }); + const empty = untimed(); assert.throws( () => parse_formatter_benchmarks(report({ scenarios: [scenario(), empty] })), /has no timings/ ); }); + test('throws when `fastest` disagrees with whether anything was timed', () => { + const unnamed = { ...scenario(), fastest: undefined }; + assert.throws( + () => parse_formatter_benchmarks(report({ scenarios: [unnamed] })), + /has 2 timings but fastest undefined/ + ); + const named = { ...untimed({ aborted: 'crashed: oxfmt' }), fastest: 'tsv' }; + assert.throws( + () => parse_formatter_benchmarks(report({ scenarios: [scenario(), named] })), + /has 0 timings but fastest "tsv"/ + ); + // the schema, before that check: a named-but-empty row is no row + const blank = { ...untimed({ aborted: 'crashed: oxfmt' }), fastest: '' }; + assert.throws( + () => parse_formatter_benchmarks(report({ scenarios: [scenario(), blank] })), + /fastest/ + ); + }); + test('throws when no scenario timed tsv', () => { assert.throws( () => parse_formatter_benchmarks(report({ scenarios: [jsx_scenario()] })), From 8e31df82e2b5907759d877ef8ff537d506306468 Mon Sep 17 00:00:00 2001 From: Ryan Atkinson Date: Wed, 23 Sep 2026 17:06:44 -0400 Subject: [PATCH 212/218] wip --- CLAUDE.md | 10 +- src/routes/docs/benchmarks/+page.svelte | 136 ++++++++++-------- .../docs/benchmarks/BenchmarksCli.svelte | 4 +- .../benchmarks/BenchmarksCliSection.svelte | 77 +++++----- .../docs/benchmarks/BenchmarksMeta.svelte | 4 +- src/routes/docs/benchmarks/benchmark_data.ts | 9 +- .../docs/benchmarks/benchmark_display.ts | 47 ++++-- src/routes/docs/benchmarks/benchmark_tools.ts | 2 +- src/routes/docs/benchmarks/benchmarks_cli.ts | 18 ++- src/routes/docs/introduction/+page.svelte | 12 +- src/routes/docs/playground/+page.svelte | 2 +- src/routes/docs/playground/Playground.svelte | 6 +- src/test/benchmark_data.prose.test.ts | 6 +- src/test/benchmark_data.test.ts | 2 +- src/test/benchmark_display.test.ts | 58 +++++++- src/test/benchmarks_cli.shape.test.ts | 10 ++ src/test/benchmarks_cli.test.ts | 16 +++ 17 files changed, 280 insertions(+), 139 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 1b3e65d..6a3e82b 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -30,9 +30,9 @@ IMPORTANT for AI agents: Do NOT run `gro dev` - the developer will manage the de - Gro (`@fuzdev/gro`) - build system and task runner - tsv (via Gro) - code formatting - mdz (`@fuzdev/mdz`) - markdown preprocessor wired into `svelte.config.js` -- `@fuzdev/tsv-wasm` - tsv's formatter + parser as WASM; powers the playground, loaded lazily in the browser +- `@fuzdev/tsv-wasm` - tsv's formatter + parser as wasm; powers the playground, loaded lazily in the browser -Note: `@fuzdev/tsv-wasm` is loaded only on `/docs/playground` via a browser-only dynamic `import()`, so the ~1MB-gzipped WASM (~2.5MB decoded) never weighs down `/docs` or the prerendered pages. +Note: `@fuzdev/tsv-wasm` is loaded only on `/docs/playground` via a browser-only dynamic `import()`, so the ~1MB-gzipped wasm (~2.5MB decoded) never weighs down `/docs` or the prerendered pages. Note: several devDependencies — `@webref/css` (CSS spec data), `zimmerframe` (AST traversal), `@sveltejs/acorn-typescript`, `zod`, and `@fuzdev/blake3-wasm` — are *optional peer dependencies* of `@fuzdev/fuz_css`'s `vite_plugin_fuz_css`, declared here so its build-time CSS generation resolves them (e.g. `css_literal.ts` imports `@webref/css`, `css_class_extractor.ts` walks ASTs with `zimmerframe`). Of those only `zod` is imported by this app's own source — `formatter_benchmark_data.ts`'s schemas, read at gen and test time and as erased types by the page, so it never reaches the client bundle — so don't mistake the rest for dead deps. Likewise `esm-env`, `@types/estree`, and `@types/node` are peers of `@fuzdev/fuz_util` (the latter two optional), and `esm-env` and `@types/estree` optional peers of `@fuzdev/mdz` and `esm-env` of `@fuzdev/fuz_ui`, and `tslib` backs `tsconfig.json`'s `importHelpers` — none is imported here directly either. @@ -46,7 +46,7 @@ tsv.fuz.dev is the public face of the tsv tool: - Benchmarks page with bar charts and tables, and a language-support matrix of the tools compared - Docs section (introduction, playground, benchmarks, conformance) - Conformance page with per-corpus-source parse-coverage tables over deliberately hard corpora, and a `Test corpus` section on how each source was chosen -- Interactive playground (`/docs/playground`) — edit a deliberately-unformatted Svelte example in a syntax-highlighted editor (fuz_code's `CodeTextarea`); the formatted output below it updates live and the parsed AST follows on a short idle; runs `@fuzdev/tsv-wasm` as lazily-loaded WASM +- Interactive playground (`/docs/playground`) — edit a deliberately-unformatted Svelte example in a syntax-highlighted editor (fuz_code's `CodeTextarea`); the formatted output below it updates live and the parsed AST follows on a short idle; runs `@fuzdev/tsv-wasm` as lazily-loaded wasm - Theme controls via fuz_ui's `ThemeRoot` in the root layout (no separate about/settings page) - Shows install instructions: the `fuzdev.tsv-format` VS Code extension, then the native `@fuzdev/tsv` (prebuilt N-API addon for Node/Bun, ships the `tsv` CLI), then `@fuzdev/tsv-wasm` (universal, same `tsv` CLI) and the format/parse subsets @@ -185,9 +185,9 @@ the components' scripts hold no untested reductions. - `docs/tomes.ts` defines the doc sections: introduction, playground, benchmarks, conformance - Benchmark data, modules, and the refresh workflow: see [Benchmarks](#benchmarks) - Tests import route modules through the `$routes` alias (`svelte.config.js`), not a `#routes/*` subpath import — this repo has no `package.json` `imports` map; routes import each other relatively -- The `/docs` index renders every tome's component through `DocsContent`, so the playground, benchmarks, and conformance tomes check `at_root` (`page.url.pathname === DOCS_PATH`) and render only a one-line link there, keeping the WASM, the charts, and their section ids off the index +- The `/docs` index renders every tome's component through `DocsContent`, so the playground, benchmarks, and conformance tomes check `at_root` (`page.url.pathname === DOCS_PATH`) and render only a one-line link there, keeping the wasm, the charts, and their section ids off the index - `library.ts` builds component metadata at runtime from the `virtual:svelte-docinfo` module (provided by the `svelte-docinfo` Vite plugin); the docs index passes it to `DocsContent` -- The playground (`/docs/playground`) loads `@fuzdev/tsv-wasm` via a browser-only dynamic `import()` inside `Playground.svelte`, so the WASM code-splits into its own chunk fetched only on that route, keeping `/docs` and the prerendered pages WASM-free. `@fuzdev/tsv-wasm` is in `vite.config.ts` `optimizeDeps.exclude` (like `@fuzdev/blake3-wasm`) +- The playground (`/docs/playground`) loads `@fuzdev/tsv-wasm` via a browser-only dynamic `import()` inside `Playground.svelte`, so the wasm code-splits into its own chunk fetched only on that route, keeping `/docs` and the prerendered pages wasm-free. `@fuzdev/tsv-wasm` is in `vite.config.ts` `optimizeDeps.exclude` (like `@fuzdev/blake3-wasm`) - The playground's formatted pane recomputes on every keystroke (formatting is ~1 ms even on a 9 KB component) while the AST pane trails a ~150 ms idle: the AST is parsed, serialized, and syntax-highlighted — around half a megabyte of it for that same component — and rebuilding that DOM per keystroke is what a large paste feels. The top-level error is the live pane's; the AST pane renders its own, since its debounced source can still be the broken text the editor has moved past - The playground's editor is fuz_code's `CodeTextarea` (live syntax highlighting via the experimental CSS Custom Highlight API). It needs `@fuzdev/fuz_code/theme_highlight.css`, imported inside `Playground.svelte` rather than the root layout so it stays on this route only; `supports_css_highlight_api()` drives a graceful-degradation note where the API is unavailable (the editor still works, unstyled) diff --git a/src/routes/docs/benchmarks/+page.svelte b/src/routes/docs/benchmarks/+page.svelte index 5638d73..e33437a 100644 --- a/src/routes/docs/benchmarks/+page.svelte +++ b/src/routes/docs/benchmarks/+page.svelte @@ -16,6 +16,7 @@ import { benchmarks_cross_runtime_json } from './benchmarks_cross_runtime.ts'; import { benchmarks_cli, + cli_corpora_commit, cli_scenario_find, cli_ratio_vs_tsv, cli_ratio_vs_tsv_npm, @@ -70,6 +71,7 @@ // Section titles referenced by in-page anchors, slugified the same way // `TomeSectionHeader` builds its ids so a rename can't orphan a link. const LANGUAGE_SECTION_TITLE = 'Language support'; + const PARSE_SECTION_TITLE = 'Parse speed'; const CLI_SECTION_TITLE = 'End-to-end CLI benchmark'; const DETAILS_SECTION_TITLE = 'Benchmarking details'; const CORPUS_SECTION_TITLE = 'Corpus'; @@ -172,6 +174,16 @@ const cli_svelte_npm_ratio = cli_ratio_vs_tsv_npm(CLI_SVELTE_KEY, 'rsvelte-fmt', 'wall_ms'); const cli_svelte_timed = cli_svelte_npm_ratio !== undefined; const cli_svelte_npm_wall = format_ratio_approx(cli_svelte_npm_ratio); + // The CLI's Svelte corpus comes from the same fuzdev/corpora repo as this page's, + // possibly at another commit — said only while the two differ (either may be + // abbreviated, so they're compared by prefix). + const cli_svelte_corpora_commit = cli_svelte && cli_corpora_commit(cli_svelte.corpus); + const corpus_snapshot_full_commit = corpus_snapshot?.commit; + const cli_svelte_pin_differs = + !!cli_svelte_corpora_commit && + !!corpus_snapshot_full_commit && + !corpus_snapshot_full_commit.startsWith(cli_svelte_corpora_commit) && + !cli_svelte_corpora_commit.startsWith(corpus_snapshot_full_commit); @@ -194,9 +206,10 @@ coverage on deliberately hard test suites.

    - This page compares tsv to Prettier, and to Oxc and Biome, similar tools with more features, - configurable styles, and wider language support. It also times rsvelte, yuku-parser, swc, - dprint, Malva, and PostCSS; + This page compares tsv to Prettier and the JS parsers it replaces (svelte/compiler and + acorn-typescript), and to Oxc and Biome, similar tools with more features, configurable + styles, and wider language support. It also measures rsvelte, yuku-parser, swc, dprint, + Malva, and PostCSS; {LANGUAGE_SECTION_TITLE} lays out what each parses and formats.

    @@ -205,9 +218,9 @@

    - Compared to Oxc and Biome, tsv builds smaller artifacts for the same capability and formats - its three languages faster in every pairing measured here, while lacking their features and - language breadth. + Compared to Oxc and Biome, tsv ships smaller artifacts, capability for capability, and + formats its three languages faster in every pairing measured here, while lacking their + features and language breadth.

    Except in the CLI section, every timing here is in-process and one file at a time, isolating @@ -225,7 +238,7 @@ Formatting Svelte, tsv is ~{format_svelte_vs_prettier} faster than Prettier and ~{format_svelte_vs_biome} faster than Biome, same pairings. Neither Oxc nor Biome ships a dedicated Svelte formatter: Oxfmt delegates Svelte to Prettier, and Biome's row is its - experimental HTML path. + experimental HTML path, which leaves template expressions as written.

  • Formatting CSS, it's ~{format_css_vs_oxfmt} faster than Oxfmt, ~{format_css_vs_prettier} @@ -237,15 +250,19 @@ line/column loc for drop-in acorn and Svelte compatibility, at ~{parse_ts_loc_cost} the span-only time: ~{parse_ts_vs_acorn} faster than acorn-typescript, the parser it replaces, but behind Oxc and swc. That AST is checked - against acorn's and Svelte's at corpus scale, but Svelte's compiler hasn't yet been run on - it. + against acorn's and Svelte's at corpus scale, but hasn't yet been fed through Svelte's + compiler end to end.
  • Parsing Svelte, that default AST is ~{parse_svelte_vs_compiler} faster than svelte/compiler (JS) and ~{parse_svelte_vs_rsvelte} faster than rsvelte - (native-vs-native). CSS runs the other way: Svelte's own parseCss is - ~{parse_css_compiler_vs_tsv} faster than tsv's JSON wire and PostCSS - ~{parse_css_postcss_vs_tsv}. + (native-vs-native). +
  • +
  • + Parsing CSS runs the other way: Svelte's own parseCss is + ~{parse_css_compiler_vs_tsv} faster than tsv's default AST and PostCSS + ~{parse_css_postcss_vs_tsv} faster, since JS parsers skip the serialization tsv pays for + (see {PARSE_SECTION_TITLE}).
  • End to end as a CLI, in a @@ -261,9 +278,9 @@
  • {#if cli_svelte_timed}
  • - On a third-party Svelte corpus, tsv's CLI is ~{cli_svelte_npm_wall} faster than - rsvelte-fmt, another Rust Svelte formatter, though rsvelte-fmt's time includes an Oxfmt - pass that finds nothing to format. + On a third-party Svelte corpus, tsv's CLI, again through its Node bin, is + ~{cli_svelte_npm_wall} faster than rsvelte-fmt, another Rust Svelte formatter, though + rsvelte-fmt's time includes an Oxfmt pass that finds nothing to format.
  • {:else if cli_svelte?.aborted}
  • @@ -310,7 +327,7 @@
    • Each format row times the tool's own parse too: source in, formatted text out. - wasm-vs-wasm and native-vs-native (N-API here) are the like-for-like pairings, and the + Wasm-vs-wasm and native-vs-native (N-API here) are the like-for-like pairings, and the tsv-wasm rows run the full parse+format build, not the smaller format-only or parse-only ones.
    • @@ -334,7 +351,7 @@
    • Oxfmt formats TypeScript, JS, and CSS with its own native engine but delegates Svelte to - a Prettier it bundles, with a bundled + its bundled Prettier and prettier-plugin-svelte: only the embedded <script> reaches its native engine, while the markup, its expressions, and the <style> are that Prettier's. @@ -342,31 +359,33 @@
    • Biome has no dedicated Svelte formatter: its Svelte row runs with html.experimentalFullSupportEnabled, the experimental HTML-superset - pipeline that lets it format .svelte at all (without the flag it returns - only the script), and formats the embedded script and style too, so the work is - comparable. Its only in-process format entry point, formatContent, also + pipeline that formats the markup, script, and style (without the flag it returns only + the formatted script). It parses the template's expressions but leaves them as written, + where Prettier and tsv reprint them, so its Svelte row does somewhat less work than + theirs. Its in-process API's only format entry point, formatContent, also opens the file in its workspace, pulls syntax diagnostics, and closes it on every call, so its rows carry that wrapper. The harness also swaps in a fresh wasm instance once its - memory has grown past a threshold — before every sweep on the larger groups — and that - instance's slower first sweep costs a few percent. There's no native Biome entry: its - in-process API, @biomejs/js-api, runs only on its wasm builds, and the - native engine ships only as the biome CLI, a separate process rather than a - library. + memory has grown past a threshold — before every sweep in the Svelte and TypeScript + groups, every few in CSS — and that instance's slower first sweep adds about 1–4% to + Biome's rows. There's no native Biome entry: its in-process API, + @biomejs/js-api, runs only on its wasm builds, and the native engine ships + only as the biome CLI, a separate process rather than a library, which the + CLI section times.
    • The dprint entry is dprint-plugin-typescript, the engine deno fmt runs for TypeScript and JS, loaded in-process as its wasm - plugin. It formats only TypeScript and JS, and no dprint markup plugin is wired in, so - it has no Svelte row and its CSS slot goes to + plugin. It formats only TypeScript and JS (JSX included), and no dprint markup plugin is + wired in, so it has no Svelte row and its CSS slot goes to Malva, a third-party CSS plugin for the same host. This times the engine, not the deno fmt CLI.
    • rsvelte-fmt, the - other Rust-native Svelte formatter here, is grayed out in the Svelte group: it ran over - every Svelte file but isn't timed, since it ships no in-process API and a process per - file would measure spawn rather than formatting. + other Rust-native Svelte formatter here, is grayed out in the Svelte group: the harness + runs it over every Svelte file to check coverage but doesn't time it, since it ships no + in-process API and a process per file would measure spawn rather than formatting. {#if cli_svelte_timed} The CLI section times it. {:else if cli_svelte?.aborted} @@ -379,7 +398,7 @@ - +

      tsv and oxc-parser share a mechanism: both serialize the AST to JSON in Rust and hand it to the JS engine's @@ -439,9 +458,10 @@ with per-node loc that the caller JSON.parses — so rsvelte-parse compares against tsv json, not the no-locs entries. Its second entry passes rsvelte's own - skipExpressionLoc, which drops loc from every JS node but - keeps name_loc on elements and attributes, so it sits near tsv's span-only - wire without matching it. + skipExpressionLoc, which drops loc from every JS node, the + <script> program included, but keeps name_loc on + elements, attributes, and directives, so it sits near tsv's span-only wire without + matching it. {#if rsvelte_svelte_target && rsvelte_svelte_target !== svelte_version} Its addon targets its own upstream Svelte, {rsvelte_svelte_target}, a release apart from the {svelte_version} the svelte/compiler row runs (both are listed under @@ -470,7 +490,8 @@ disk; the gz beside each estimates the download. tsv-wasm, tsv (napi), and tsv (ffi) are tsv's full builds, parser and formatter for Svelte, TypeScript/JS, and CSS in one artifact, beside format-only and - parse-only subsets. + parse-only subsets. Each group's ratios are against its smallest build, highlighted; hover + another row to re-anchor them.

      @@ -483,12 +504,12 @@ prettier-plugin-svelte, and the parsers tsv replaces (Svelte's, plus acorn with acorn-typescript) — and aren't files a package ships. Neither publishes a single artifact, and installed size counts every language Prettier supports in two module - formats, so each entry is instead a minified, tree-shaken bundle of the least one job - needs for tsv's three languages: what you would deploy to a browser, not what Node + formats, so each entry is instead a minified, tree-shaken bundle of just what its job + needs across tsv's three languages: what you would deploy to a browser, not what Node loads. The full entry is barely larger than the formatter, which already contains the whole parse bundle: prettier-plugin-svelte needs Svelte's parser, which pulls in acorn - and acorn-typescript. Minified JS compresses much better than tsv's wasm, so next to - it they look smaller by gz than by raw bytes. + and acorn-typescript. Minified JS compresses much better than tsv's wasm, so beside it + these entries look smaller by gz than by raw bytes.
    • dprint (wasm) and Malva (wasm) expose no parser, so both sit @@ -498,9 +519,9 @@
    • Biome's build carries a parser, formatter, and linter for every language it supports. - yuku-parser parses TypeScript, JS, and JSX only, where tsv's parse-only build beside - it carries Svelte and CSS parsers too. Oxfmt ships no wasm build, hence its grayed-out - slot under Formatter. + yuku-parser parses TypeScript, JS, JSX, and TSX only, where tsv's parse-only build + beside it carries Svelte and CSS parsers too. Oxfmt ships no wasm build, hence its + grayed-out slot under Formatter.
    @@ -518,7 +539,7 @@ Svelte path. tsv (napi) is likewise its .node alone: @fuzdev/tsv is a JS dispatcher over prebuilt per-platform packages, and each also carries the - tsv CLI binary. Each leaves out nearly its own size again. + tsv CLI binary. Either package is close to twice its entry here.
  • The (ffi) entries are tsv's C-ABI build, which isn't published — what the @@ -576,11 +597,11 @@

    Rows run in a fixed order, not interleaved or shuffled: the reference row, then tsv's rows, then the alternatives. A forced garbage collection before each row limits what one row - leaves for the next, but nothing pins the process to a core or holds the clock steady (an - unpinned laptop CPU), so whatever remains, thermal drift included, falls on the later rows. - Against every alternative that bias counts for tsv; against the reference row, which runs - first, it counts against tsv — Prettier in the format charts, and svelte/compiler, - acorn-typescript, and parseCss in the parse ones. + leaves for the next, but nothing pins the process to a core or holds the laptop CPU's clock + steady, so whatever remains, thermal drift included, falls on the later rows. Against every + alternative that bias counts for tsv; against the reference row, which runs first, it counts + against tsv — Prettier in the format charts, and svelte/compiler, acorn-typescript, and + parseCss in the parse ones.

    One asymmetry isn't isolated: Oxfmt's programmatic format is async-only (as is @@ -595,21 +616,22 @@

    - Every in-process timing on this page comes from {format_count(corpus_counts.files)} files of - .svelte, .ts/.js, and .css — real-world - code only, vendored at one pinned commit in the + Every in-process timing on this page comes from {format_count(corpus_counts.files)} + .svelte, .ts/.js, and .css files of + real-world code, vendored in the fuzdev/corpora{corpus_snapshot_commit ? `@${corpus_snapshot_commit}` : ''} - snapshot so one clone reproduces it: the author's libraries, apps, and sites (the - fuz.dev ecosystem plus personal SvelteKit projects), and upstream framework source (Svelte, - SvelteKit, and the svelte.dev site). + snapshot so one clone reproduces it. They're the author's libraries, apps, and sites + (the fuz.dev ecosystem plus personal SvelteKit projects), and upstream framework source + (Svelte, SvelteKit, and the svelte.dev site).

    • The snapshot's third-party component libraries are left out: they would dominate the Svelte set. The CLI section's Svelte corpus draws on them, and shares only its kit and - svelte.dev trees with this one. + svelte.dev trees with this + one{cli_svelte_pin_differs ? ', vendored at a different corpora commit' : ''}.
    • Test files count as real code and stay in. Fixture files (formatter test suites, and @@ -628,7 +650,9 @@
    • The corpus is the author's own code plus Svelte's, the same code tsv is developed and - tested against and mostly tsv-formatted already, so every ratio here is "on this corpus", + tested against and mostly tsv-formatted already. Input already in a tool's own style may + format faster, which would favor tsv; pinning the other formatters to that style narrows + it, since the input then sits near their output too. Every ratio here is "on this corpus", not a universal figure.
    diff --git a/src/routes/docs/benchmarks/BenchmarksCli.svelte b/src/routes/docs/benchmarks/BenchmarksCli.svelte index e18fcb3..c13bc17 100644 --- a/src/routes/docs/benchmarks/BenchmarksCli.svelte +++ b/src/routes/docs/benchmarks/BenchmarksCli.svelte @@ -1,6 +1,6 @@ diff --git a/src/routes/docs/playground/Playground.svelte b/src/routes/docs/playground/Playground.svelte index bef41de..b39ec62 100644 --- a/src/routes/docs/playground/Playground.svelte +++ b/src/routes/docs/playground/Playground.svelte @@ -12,7 +12,7 @@ import { playground_example } from './playground_example.ts'; // `@fuzdev/tsv-wasm` is loaded lazily, in the browser only — a dynamic import - // so the ~1MB-gzipped WASM lands in its own chunk, fetched the first time this + // so the ~1MB-gzipped wasm lands in its own chunk, fetched the first time this // component mounts and never pulled into `/docs` or the prerendered HTML. let tsv: typeof import('@fuzdev/tsv-wasm') | null = $state(null); let load_error: string | null = $state(null); @@ -26,7 +26,7 @@ // A tsv call's outcome: its string result, or the thrown error's message. type Outcome = { value: string; error: null } | { value: null; error: string }; - // Run a tsv call, capturing a thrown error as a message; `null` until the WASM + // Run a tsv call, capturing a thrown error as a message; `null` until the wasm // loads. Lets `formatted` and `ast` share one shape and recompute as `source` changes // — no blur or button. const run = (fn: (t: NonNullable) => string): Outcome | null => { @@ -96,7 +96,7 @@ }; // format the editable source in place — writes the formatted result back into - // the editor; no-op while the WASM is loading or the input doesn't parse + // the editor; no-op while the wasm is loading or the input doesn't parse const format = (): void => { if (!formatted || formatted.error !== null) return; source = formatted.value; diff --git a/src/test/benchmark_data.prose.test.ts b/src/test/benchmark_data.prose.test.ts index 2632e28..67adcf2 100644 --- a/src/test/benchmark_data.prose.test.ts +++ b/src/test/benchmark_data.prose.test.ts @@ -360,12 +360,12 @@ describe('prose ratios resolve', () => { }); test('the scenario descriptions state facts the report carries', () => { - // the delivery copy: "the WASM row's CPU ratio runs well past its time ratio" + // the delivery copy: "the wasm row's CPU ratio runs well past its time ratio" const cpu = cli_ratio_vs_tsv(CLI_DELIVERY_KEY, CLI_TSV_WASM_LABEL, 'cpu_ms'); const wall = cli_ratio_vs_tsv(CLI_DELIVERY_KEY, CLI_TSV_WASM_LABEL, 'wall_ms'); assert.isDefined(cpu, 'delivery scenario has no tsv-wasm row'); assert.isDefined(wall); - assert.isAbove(cpu, wall * 1.5, 'the WASM CPU ratio no longer runs well past its time ratio'); + assert.isAbove(cpu, wall * 1.5, 'the wasm CPU ratio no longer runs well past its time ratio'); // the Svelte copy: "rsvelte-fmt 0.7.x crashes nondeterministically in the harness's preflight" const rsvelte_version = benchmarks_cli.versions['rsvelte-fmt']; assert.isDefined(rsvelte_version); @@ -410,7 +410,7 @@ describe('prose ratios resolve', () => { assert.isDefined(cli_memory_ratio_range({ scenario_key: CLI_DELIVERY_KEY })); }); - test('the WASM delivery row is "ahead of both Prettier rows … and behind Oxfmt and Biome"', () => { + test('the wasm delivery row is "ahead of both Prettier rows … and behind Oxfmt and Biome"', () => { // the delivery and large-single-file scenarios time the same parser.ts, so // the note's ordering claim is checkable across them const delivery = benchmarks_cli.scenarios.find((s) => s.key === CLI_DELIVERY_KEY); diff --git a/src/test/benchmark_data.test.ts b/src/test/benchmark_data.test.ts index f962fec..b77b55e 100644 --- a/src/test/benchmark_data.test.ts +++ b/src/test/benchmark_data.test.ts @@ -53,7 +53,7 @@ describe('derive_corpus_source_table', () => { label: 'fuzdev/zzz', subpath: undefined, url: 'https://github.com/fuzdev/zzz/tree/0123456789abcdef0123456789abcdef01234567/src', - commit: '012345678', + commit: '0123456', files: 5, by_language: [3, 2, 0] }, diff --git a/src/test/benchmark_display.test.ts b/src/test/benchmark_display.test.ts index c198cdd..91c6156 100644 --- a/src/test/benchmark_display.test.ts +++ b/src/test/benchmark_display.test.ts @@ -2,6 +2,8 @@ import { assert, describe, test } from 'vitest'; import { format_bytes, + format_cli_corpus, + format_commit, format_gzip_size, format_count, format_coverage_percent, @@ -272,21 +274,31 @@ describe('format_group_omissions', () => { ] }; - test('several files by several rows flags the overlap', () => { + test('several files by several rows lists each row, flagging the overlap', () => { assert.strictEqual( format_group_omissions(omissions), - "2 of 951 files (11.2% of this group's bytes) left out of every row's timed set, because a row here fails them in this harness — files failed, by row (rows can overlap): biome (wasm) 2, oxfmt (node napi) 1" + "2 of 951 files (11.2% of the group's bytes) are left out of every row, because rows here fail them in this harness — by row, overlapping: biome (wasm) 2, oxfmt (node napi) 1." ); }); - test('one file by one row takes a singular pronoun, with no overlap flag', () => { + test('one row is named outright, without a count', () => { + assert.strictEqual( + format_group_omissions({ + ...omissions, + by_tool: [{ name: 'biome-wasm', files: 2, bytes: 112, categories: {} }] + }), + "2 of 951 files (11.2% of the group's bytes) are left out of every row, because biome (wasm) fails them in this harness." + ); + }); + + test('one file takes a singular pronoun', () => { assert.strictEqual( format_group_omissions({ ...omissions, omitted_files: 1, by_tool: [{ name: 'oxfmt', files: 1, bytes: 112, categories: {} }] }), - "1 of 951 files (11.2% of this group's bytes) left out of every row's timed set, because a row here fails it in this harness — files failed, by row: oxfmt (node napi) 1" + "1 of 951 files (11.2% of the group's bytes) are left out of every row, because oxfmt (node napi) fails it in this harness." ); }); }); @@ -297,3 +309,41 @@ describe('format_report_date', () => { assert.strictEqual(format_report_date('2026-09-23T01:44:33.674Z'), 'September 23, 2026'); }); }); + +describe('format_commit', () => { + test('abbreviates a full or longer-abbreviated SHA to one length', () => { + assert.strictEqual(format_commit('b4c8d2862dc13b0e04512dc2c5dd5f79a6c74c1b'), 'b4c8d28'); + assert.strictEqual(format_commit('23392a6e'), '23392a6'); + assert.strictEqual(format_commit('abc1234'), 'abc1234'); + }); +}); + +describe('format_cli_corpus', () => { + test('a git corpus reads as a commit with its date', () => { + assert.strictEqual(format_cli_corpus('8cf997c 2026-07-14'), 'commit 8cf997c (2026-07-14)'); + }); + + test('a single file gets byte separators and keeps its content hash', () => { + assert.strictEqual( + format_cli_corpus('539588 bytes, sha256:dcddb577aa14'), + '539,588 bytes, sha256:dcddb577aa14' + ); + }); + + test('a corpora snapshot abbreviates its commit and tree ids', () => { + assert.strictEqual( + format_cli_corpus( + 'fuzdev/corpora@1117b4829309 (collections tree 5f40c547c3ed), snapshot 6214069 2026-09-04' + ), + 'fuzdev/corpora@1117b48 (collections tree 5f40c54), snapshot 6214069 (2026-09-04)' + ); + }); + + test('an all-digit run is a number, not an id', () => { + assert.strictEqual(format_cli_corpus('12345678 bytes'), '12,345,678 bytes'); + }); + + test('an unrecognized line passes through', () => { + assert.strictEqual(format_cli_corpus('unknown (ENOENT)'), 'unknown (ENOENT)'); + }); +}); diff --git a/src/test/benchmarks_cli.shape.test.ts b/src/test/benchmarks_cli.shape.test.ts index 5e5768b..6fc8b09 100644 --- a/src/test/benchmarks_cli.shape.test.ts +++ b/src/test/benchmarks_cli.shape.test.ts @@ -4,11 +4,13 @@ import { benchmarks_json } from '$routes/docs/benchmarks/benchmarks.ts'; import { benchmarks_formatters_json } from '$routes/docs/benchmarks/benchmarks_formatters.ts'; import { benchmarks_cli, + cli_corpora_commit, cli_default_anchor_label, cli_settle_seconds, CLI_DELIVERY_KEY, CLI_SCENARIO_KEYS, CLI_SINGLE_FILE_KEY, + CLI_SVELTE_KEY, CLI_TSV_LABEL, CLI_TSV_NPM_LABEL } from '$routes/docs/benchmarks/benchmarks_cli.ts'; @@ -149,6 +151,14 @@ describe('benchmarks_cli shape', () => { } }); + test('the Svelte corpus names the corpora commit the Corpus section compares its pin to', () => { + // "vendored at a different corpora commit" is said only while the pins differ, + // so a corpus line this can't read would drop the note silently + const svelte = benchmarks_cli.scenarios.find((s) => s.key === CLI_SVELTE_KEY); + assert.isDefined(svelte); + assert.isDefined(cli_corpora_commit(svelte.corpus), svelte.corpus); + }); + test('every formatter accepts the whole corpus in every timed scenario, as the page claims', () => { // The page's notes say the preflight asserts every formatter parses every file, so // no formatter is credited for skipping files. That's a claim about the data — diff --git a/src/test/benchmarks_cli.test.ts b/src/test/benchmarks_cli.test.ts index ae28af6..600552a 100644 --- a/src/test/benchmarks_cli.test.ts +++ b/src/test/benchmarks_cli.test.ts @@ -2,6 +2,7 @@ import { assert, describe, test } from 'vitest'; import { cli_comparison_results, + cli_corpora_commit, cli_default_anchor_label, cli_label_is_tsv, cli_memory_ratio_range, @@ -283,3 +284,18 @@ describe('to_unshimmed_note', () => { ); }); }); + +describe('cli_corpora_commit', () => { + test('reads the commit off a corpora snapshot line', () => { + assert.strictEqual( + cli_corpora_commit( + 'fuzdev/corpora@1117b4829309 (collections tree 5f40c547c3ed), snapshot 6214069 2026-09-04' + ), + '1117b4829309' + ); + }); + + test('a corpus from elsewhere has none', () => { + assert.isUndefined(cli_corpora_commit('8cf997c 2026-07-14')); + }); +}); From 6f1c07f226e750ea931a78543c16cd1cfd5e7592 Mon Sep 17 00:00:00 2001 From: Ryan Atkinson Date: Wed, 23 Sep 2026 17:56:05 -0400 Subject: [PATCH 213/218] wip --- .../benchmarks/benchmarks_formatters.json | 444 +++++++++--------- src/test/benchmark_data.prose.test.ts | 30 +- 2 files changed, 251 insertions(+), 223 deletions(-) diff --git a/src/routes/docs/benchmarks/benchmarks_formatters.json b/src/routes/docs/benchmarks/benchmarks_formatters.json index e3c8cdc..4217d85 100644 --- a/src/routes/docs/benchmarks/benchmarks_formatters.json +++ b/src/routes/docs/benchmarks/benchmarks_formatters.json @@ -1,6 +1,6 @@ { - "timestamp": "2026-09-23T19:54:13.835Z", - "git_commit": "4a703e9", + "timestamp": "2026-09-23T21:18:37.149Z", + "git_commit": "a02708c", "git_dirty": false, "machine": { "cpu_model": "AMD Ryzen 5 PRO 7530U with Radeon Graphics", @@ -9,8 +9,8 @@ "arch": "x86_64" }, "node_startup": { - "mean_ms": 18.873, - "stddev_ms": 0.813, + "mean_ms": 18.509, + "stddev_ms": 0.618, "runs": 20 }, "versions": { @@ -76,133 +76,133 @@ "timings": [ { "name": "prettier", - "mean_ms": 1610.831, - "stddev_ms": 24.323, - "user_ms": 1534.545, - "system_ms": 881.75, - "min_ms": 1558.018, - "max_ms": 1659.518 + "mean_ms": 1620.432, + "stddev_ms": 26.219, + "user_ms": 1555.45, + "system_ms": 865.342, + "min_ms": 1557.27, + "max_ms": 1660.41 }, { "name": "prettier+oxc-parser", - "mean_ms": 973.566, - "stddev_ms": 11.126, - "user_ms": 888.053, - "system_ms": 444.455, - "min_ms": 955.33, - "max_ms": 995.418 + "mean_ms": 976.694, + "stddev_ms": 8.69, + "user_ms": 887.228, + "system_ms": 445.983, + "min_ms": 962.295, + "max_ms": 1003.355 }, { "name": "biome", - "mean_ms": 107.927, - "stddev_ms": 1.481, - "user_ms": 78.971, - "system_ms": 35.803, - "min_ms": 105.531, - "max_ms": 110.75 + "mean_ms": 107.881, + "stddev_ms": 1.265, + "user_ms": 81.098, + "system_ms": 34.199, + "min_ms": 105.631, + "max_ms": 110.254 }, { "name": "oxfmt", - "mean_ms": 62.194, - "stddev_ms": 1.944, - "user_ms": 43.919, - "system_ms": 50.357, - "min_ms": 59.702, - "max_ms": 65.883 + "mean_ms": 61.679, + "stddev_ms": 1.717, + "user_ms": 46.105, + "system_ms": 48.393, + "min_ms": 60.125, + "max_ms": 66.591 }, { "name": "tsv-npm", - "mean_ms": 46.58, - "stddev_ms": 0.67, - "user_ms": 28.674, - "system_ms": 19.981, - "min_ms": 44.852, - "max_ms": 47.621 + "mean_ms": 46.564, + "stddev_ms": 0.602, + "user_ms": 30.037, + "system_ms": 18.991, + "min_ms": 45.665, + "max_ms": 47.863 }, { "name": "tsv", - "mean_ms": 16.525, - "stddev_ms": 0.419, - "user_ms": 10.96, - "system_ms": 5.539, - "min_ms": 15.822, - "max_ms": 17.222 + "mean_ms": 16.764, + "stddev_ms": 0.548, + "user_ms": 10.016, + "system_ms": 6.754, + "min_ms": 16.017, + "max_ms": 18.74 } ], "fastest": "tsv", "speedups": [ { "name": "tsv-npm", - "ratio": 2.8187, - "ratio_stddev": 0.0822 + "ratio": 2.7776, + "ratio_stddev": 0.0977 }, { "name": "oxfmt", - "ratio": 3.7635, - "ratio_stddev": 0.1515 + "ratio": 3.6793, + "ratio_stddev": 0.158 }, { "name": "biome", - "ratio": 6.531, - "ratio_stddev": 0.1882 + "ratio": 6.4353, + "ratio_stddev": 0.2236 }, { "name": "prettier+oxc-parser", - "ratio": 58.913, - "ratio_stddev": 1.638 + "ratio": 58.2616, + "ratio_stddev": 1.9749 }, { "name": "prettier", - "ratio": 97.4756, - "ratio_stddev": 2.8759 + "ratio": 96.6618, + "ratio_stddev": 3.5273 } ], "memory": [ { "name": "prettier", - "mean_mb": 305.035, - "min_mb": 292.613, - "max_mb": 316.934, - "ratio": 22.8284, - "ratio_stddev": 0.5397 + "mean_mb": 306.063, + "min_mb": 292.738, + "max_mb": 327.07, + "ratio": 22.7871, + "ratio_stddev": 0.6138 }, { "name": "prettier+oxc-parser", - "mean_mb": 196.414, - "min_mb": 192.91, - "max_mb": 198.449, - "ratio": 14.6993, - "ratio_stddev": 0.2081 + "mean_mb": 196.77, + "min_mb": 193.41, + "max_mb": 198.375, + "ratio": 14.6499, + "ratio_stddev": 0.1557 }, { "name": "biome", - "mean_mb": 95.679, - "min_mb": 93.781, - "max_mb": 99.523, - "ratio": 7.1605, - "ratio_stddev": 0.1693 + "mean_mb": 94.521, + "min_mb": 92.934, + "max_mb": 97.176, + "ratio": 7.0373, + "ratio_stddev": 0.1016 }, { "name": "oxfmt", - "mean_mb": 114.055, - "min_mb": 113.844, - "max_mb": 114.316, - "ratio": 8.5357, - "ratio_stddev": 0.1005 + "mean_mb": 114.015, + "min_mb": 113.82, + "max_mb": 114.352, + "ratio": 8.4887, + "ratio_stddev": 0.0703 }, { "name": "tsv-npm", - "mean_mb": 49.489, - "min_mb": 49.285, - "max_mb": 49.629, - "ratio": 3.7037, - "ratio_stddev": 0.044 + "mean_mb": 49.34, + "min_mb": 47.309, + "max_mb": 49.648, + "ratio": 3.6735, + "ratio_stddev": 0.0473 }, { "name": "tsv", - "mean_mb": 13.362, - "min_mb": 13.133, - "max_mb": 13.684 + "mean_mb": 13.431, + "min_mb": 13.219, + "max_mb": 13.609 } ] }, @@ -255,133 +255,133 @@ "timings": [ { "name": "prettier", - "mean_ms": 8321.663, - "stddev_ms": 109.842, - "user_ms": 13853.138, - "system_ms": 927.474, - "min_ms": 8175.041, - "max_ms": 8502.97 + "mean_ms": 8325.389, + "stddev_ms": 72.367, + "user_ms": 13874.069, + "system_ms": 907.009, + "min_ms": 8228.237, + "max_ms": 8430.571 }, { "name": "prettier+oxc-parser", - "mean_ms": 6855.327, - "stddev_ms": 64.924, - "user_ms": 8796.413, - "system_ms": 551.473, - "min_ms": 6741.877, - "max_ms": 6950.061 + "mean_ms": 6864.058, + "stddev_ms": 87.471, + "user_ms": 8825.068, + "system_ms": 540.436, + "min_ms": 6712.083, + "max_ms": 6985.163 }, { "name": "biome", - "mean_ms": 300.191, - "stddev_ms": 1.938, - "user_ms": 2159.353, - "system_ms": 232.543, - "min_ms": 297.5, - "max_ms": 302.535 + "mean_ms": 299.878, + "stddev_ms": 1.428, + "user_ms": 2173.453, + "system_ms": 226.363, + "min_ms": 298.187, + "max_ms": 302.519 }, { "name": "oxfmt", - "mean_ms": 116.146, - "stddev_ms": 1.188, - "user_ms": 531.178, - "system_ms": 253.286, - "min_ms": 114.379, - "max_ms": 118.463 + "mean_ms": 115.961, + "stddev_ms": 2.532, + "user_ms": 530.074, + "system_ms": 273.978, + "min_ms": 112.624, + "max_ms": 119.823 }, { "name": "tsv-npm", - "mean_ms": 76.239, - "stddev_ms": 1.387, - "user_ms": 299.22, - "system_ms": 120.432, - "min_ms": 74.166, - "max_ms": 79.353 + "mean_ms": 76.022, + "stddev_ms": 0.68, + "user_ms": 289.677, + "system_ms": 130.209, + "min_ms": 75.266, + "max_ms": 77.573 }, { "name": "tsv", - "mean_ms": 45.356, - "stddev_ms": 0.854, - "user_ms": 262.09, - "system_ms": 122.535, - "min_ms": 44.685, - "max_ms": 47.562 + "mean_ms": 45.185, + "stddev_ms": 0.285, + "user_ms": 269.243, + "system_ms": 115.521, + "min_ms": 44.8, + "max_ms": 45.765 } ], "fastest": "tsv", "speedups": [ { "name": "tsv-npm", - "ratio": 1.6809, - "ratio_stddev": 0.044 + "ratio": 1.6825, + "ratio_stddev": 0.0184 }, { "name": "oxfmt", - "ratio": 2.5608, - "ratio_stddev": 0.0549 + "ratio": 2.5664, + "ratio_stddev": 0.0583 }, { "name": "biome", - "ratio": 6.6186, - "ratio_stddev": 0.1318 + "ratio": 6.6367, + "ratio_stddev": 0.0525 }, { "name": "prettier+oxc-parser", - "ratio": 151.1453, - "ratio_stddev": 3.1868 + "ratio": 151.9108, + "ratio_stddev": 2.1605 }, { "name": "prettier", - "ratio": 183.4749, - "ratio_stddev": 4.2202 + "ratio": 184.252, + "ratio_stddev": 1.9796 } ], "memory": [ { "name": "prettier", - "mean_mb": 451.168, - "min_mb": 398.137, - "max_mb": 479.316, - "ratio": 21.7733, - "ratio_stddev": 1.1482 + "mean_mb": 478.305, + "min_mb": 397.051, + "max_mb": 535.211, + "ratio": 23.1253, + "ratio_stddev": 2.2024 }, { "name": "prettier+oxc-parser", - "mean_mb": 304.773, - "min_mb": 298.586, - "max_mb": 321.84, - "ratio": 14.7083, - "ratio_stddev": 0.4809 + "mean_mb": 303.916, + "min_mb": 299.164, + "max_mb": 308.375, + "ratio": 14.6939, + "ratio_stddev": 0.4863 }, { "name": "biome", - "mean_mb": 146.032, - "min_mb": 141.949, - "max_mb": 147.848, - "ratio": 7.0475, - "ratio_stddev": 0.1871 + "mean_mb": 144.821, + "min_mb": 141.664, + "max_mb": 146.641, + "ratio": 7.0019, + "ratio_stddev": 0.236 }, { "name": "oxfmt", - "mean_mb": 227.186, - "min_mb": 218.711, - "max_mb": 230.93, - "ratio": 10.964, - "ratio_stddev": 0.3134 + "mean_mb": 225.951, + "min_mb": 219.461, + "max_mb": 232.301, + "ratio": 10.9244, + "ratio_stddev": 0.3905 }, { "name": "tsv-npm", - "mean_mb": 49.525, - "min_mb": 49.336, - "max_mb": 49.75, - "ratio": 2.3901, - "ratio_stddev": 0.0567 + "mean_mb": 49.573, + "min_mb": 49.289, + "max_mb": 49.867, + "ratio": 2.3968, + "ratio_stddev": 0.076 }, { "name": "tsv", - "mean_mb": 20.721, - "min_mb": 19.836, - "max_mb": 21.52 + "mean_mb": 20.683, + "min_mb": 19.691, + "max_mb": 21.73 } ] }, @@ -416,67 +416,67 @@ "timings": [ { "name": "rsvelte-fmt", - "mean_ms": 195.538, - "stddev_ms": 7.94, - "user_ms": 843.975, - "system_ms": 696.12, - "min_ms": 185.312, - "max_ms": 206.074 + "mean_ms": 189.076, + "stddev_ms": 11.624, + "user_ms": 833.735, + "system_ms": 705.772, + "min_ms": 176.002, + "max_ms": 212.932 }, { "name": "tsv-npm", - "mean_ms": 71.424, - "stddev_ms": 1.036, - "user_ms": 248.09, - "system_ms": 138.878, - "min_ms": 70.17, - "max_ms": 73.229 + "mean_ms": 71.689, + "stddev_ms": 1.235, + "user_ms": 244.257, + "system_ms": 143.421, + "min_ms": 70.487, + "max_ms": 74.196 }, { "name": "tsv", - "mean_ms": 41.019, - "stddev_ms": 0.22, - "user_ms": 220.822, - "system_ms": 134.057, - "min_ms": 40.695, - "max_ms": 41.431 + "mean_ms": 41.051, + "stddev_ms": 0.447, + "user_ms": 226.574, + "system_ms": 126.821, + "min_ms": 40.591, + "max_ms": 42.211 } ], "fastest": "tsv", "speedups": [ { "name": "tsv-npm", - "ratio": 1.7413, - "ratio_stddev": 0.0269 + "ratio": 1.7463, + "ratio_stddev": 0.0356 }, { "name": "rsvelte-fmt", - "ratio": 4.7671, - "ratio_stddev": 0.1952 + "ratio": 4.6059, + "ratio_stddev": 0.2876 } ], "memory": [ { "name": "rsvelte-fmt", - "mean_mb": 139.36, - "min_mb": 125.355, - "max_mb": 151.457, - "ratio": 10.8441, - "ratio_stddev": 0.6879 + "mean_mb": 134.023, + "min_mb": 121.297, + "max_mb": 147.301, + "ratio": 10.2783, + "ratio_stddev": 0.672 }, { "name": "tsv-npm", - "mean_mb": 49.352, - "min_mb": 47.539, - "max_mb": 49.805, - "ratio": 3.8403, - "ratio_stddev": 0.1047 + "mean_mb": 49.579, + "min_mb": 49.348, + "max_mb": 49.809, + "ratio": 3.8023, + "ratio_stddev": 0.107 }, { "name": "tsv", - "mean_mb": 12.851, - "min_mb": 12.363, - "max_mb": 13.285 + "mean_mb": 13.039, + "min_mb": 12.547, + "max_mb": 13.672 } ] }, @@ -511,67 +511,67 @@ "timings": [ { "name": "tsv-wasm", - "mean_ms": 152.548, - "stddev_ms": 4.212, - "user_ms": 324.518, - "system_ms": 54.87, - "min_ms": 147.628, - "max_ms": 166.939 + "mean_ms": 151.999, + "stddev_ms": 3.33, + "user_ms": 321.777, + "system_ms": 56.413, + "min_ms": 146.922, + "max_ms": 160.339 }, { "name": "tsv-npm", - "mean_ms": 47.333, - "stddev_ms": 0.894, - "user_ms": 27.483, - "system_ms": 22.191, - "min_ms": 45.822, - "max_ms": 49.649 + "mean_ms": 47.522, + "stddev_ms": 1.094, + "user_ms": 32.828, + "system_ms": 17.021, + "min_ms": 45.923, + "max_ms": 50.085 }, { "name": "tsv", - "mean_ms": 16.623, - "stddev_ms": 0.529, - "user_ms": 10.979, - "system_ms": 5.608, - "min_ms": 15.856, - "max_ms": 18.003 + "mean_ms": 16.908, + "stddev_ms": 0.249, + "user_ms": 11.173, + "system_ms": 5.688, + "min_ms": 16.524, + "max_ms": 17.465 } ], "fastest": "tsv", "speedups": [ { "name": "tsv-npm", - "ratio": 2.8475, - "ratio_stddev": 0.1054 + "ratio": 2.8107, + "ratio_stddev": 0.0768 }, { "name": "tsv-wasm", - "ratio": 9.1771, - "ratio_stddev": 0.3868 + "ratio": 8.99, + "ratio_stddev": 0.2372 } ], "memory": [ { "name": "tsv-wasm", - "mean_mb": 116.95, - "min_mb": 111.496, - "max_mb": 121.719, - "ratio": 8.7442, - "ratio_stddev": 0.2139 + "mean_mb": 116.519, + "min_mb": 112.676, + "max_mb": 119.781, + "ratio": 8.7196, + "ratio_stddev": 0.1775 }, { "name": "tsv-npm", - "mean_mb": 49.606, - "min_mb": 49.332, - "max_mb": 49.891, - "ratio": 3.709, - "ratio_stddev": 0.041 + "mean_mb": 49.596, + "min_mb": 49.289, + "max_mb": 49.777, + "ratio": 3.7115, + "ratio_stddev": 0.034 }, { "name": "tsv", - "mean_mb": 13.375, - "min_mb": 13.098, - "max_mb": 13.625 + "mean_mb": 13.363, + "min_mb": 13.105, + "max_mb": 13.566 } ] } diff --git a/src/test/benchmark_data.prose.test.ts b/src/test/benchmark_data.prose.test.ts index 67adcf2..38a5064 100644 --- a/src/test/benchmark_data.prose.test.ts +++ b/src/test/benchmark_data.prose.test.ts @@ -366,12 +366,40 @@ describe('prose ratios resolve', () => { assert.isDefined(cpu, 'delivery scenario has no tsv-wasm row'); assert.isDefined(wall); assert.isAbove(cpu, wall * 1.5, 'the wasm CPU ratio no longer runs well past its time ratio'); - // the Svelte copy: "rsvelte-fmt 0.7.x crashes nondeterministically in the harness's preflight" + // the Svelte abort context: "rsvelte-fmt 0.7.x can abort when its output and stderr share a pipe" const rsvelte_version = benchmarks_cli.versions['rsvelte-fmt']; assert.isDefined(rsvelte_version); assert.match(rsvelte_version, /^0\.7\./, 'the Svelte copy names rsvelte-fmt 0.7.x'); }); + test('the delivery note places the wasm row among the single-file tools', () => { + // "still well ahead of both Prettier rows there, but behind Oxfmt and Biome" — + // the delivery and single-file scenarios time the same file (the shape test + // holds them to one corpus revision), so the wasm row reads against the other + // tools' single-file times across the two tables + const wasm = cli_scenario_find(CLI_DELIVERY_KEY)?.results.find( + (r) => r.label === CLI_TSV_WASM_LABEL + ); + assert(wasm, `${CLI_DELIVERY_KEY} has no ${CLI_TSV_WASM_LABEL} row`); + const single = cli_scenario_find(CLI_SINGLE_FILE_KEY); + assert(single, `no generated scenario has id "${CLI_SINGLE_FILE_KEY}"`); + const wall = (label: string): number => { + const row = single.results.find((r) => r.label === label); + assert(row, `${CLI_SINGLE_FILE_KEY} has no ${label} row`); + return row.wall_ms; + }; + for (const label of ['prettier', 'prettier + oxc-parser']) { + assert.isAbove( + wall(label), + wasm.wall_ms * 2, + `${label}: the wasm row is no longer well ahead` + ); + } + for (const label of ['oxfmt', 'biome']) { + assert.isBelow(wall(label), wasm.wall_ms, `${label}: the wasm row is no longer behind`); + } + }); + test('the CPU-work column counts system time, as the note says', () => { // "hyperfine's user plus system time" — a refresh that drops either half // would relabel a different metric under the same heading From 75c310124e0e0d1df0f6578d0f5bd93395c00489 Mon Sep 17 00:00:00 2001 From: Ryan Atkinson Date: Wed, 23 Sep 2026 18:11:28 -0400 Subject: [PATCH 214/218] wip --- src/routes/docs/benchmarks/+page.svelte | 22 +++++----- .../benchmarks/BenchmarksCliSection.svelte | 42 +++++++++---------- src/routes/docs/benchmarks/benchmark_tools.ts | 2 +- src/test/benchmark_data.prose.test.ts | 4 +- 4 files changed, 35 insertions(+), 35 deletions(-) diff --git a/src/routes/docs/benchmarks/+page.svelte b/src/routes/docs/benchmarks/+page.svelte index e33437a..9c2f07c 100644 --- a/src/routes/docs/benchmarks/+page.svelte +++ b/src/routes/docs/benchmarks/+page.svelte @@ -219,8 +219,7 @@

    Compared to Oxc and Biome, tsv ships smaller artifacts, capability for capability, and - formats its three languages faster in every pairing measured here, while lacking their - features and language breadth. + formats its three languages faster in every pairing measured here.

    Except in the CLI section, every timing here is in-process and one file at a time, isolating @@ -238,7 +237,7 @@ Formatting Svelte, tsv is ~{format_svelte_vs_prettier} faster than Prettier and ~{format_svelte_vs_biome} faster than Biome, same pairings. Neither Oxc nor Biome ships a dedicated Svelte formatter: Oxfmt delegates Svelte to Prettier, and Biome's row is its - experimental HTML path, which leaves template expressions as written. + experimental HTML path.

  • Formatting CSS, it's ~{format_css_vs_oxfmt} faster than Oxfmt, ~{format_css_vs_prettier} @@ -280,7 +279,8 @@
  • On a third-party Svelte corpus, tsv's CLI, again through its Node bin, is ~{cli_svelte_npm_wall} faster than rsvelte-fmt, another Rust Svelte formatter, though - rsvelte-fmt's time includes an Oxfmt pass that finds nothing to format. + rsvelte-fmt's time includes a second Node launch, the Oxfmt it runs for + non-.svelte files, which finds none.
  • {:else if cli_svelte?.aborted}
  • @@ -364,14 +364,16 @@ where Prettier and tsv reprint them, so its Svelte row does somewhat less work than theirs. Its in-process API's only format entry point, formatContent, also opens the file in its workspace, pulls syntax diagnostics, and closes it on every call, - so its rows carry that wrapper. The harness also swaps in a fresh wasm instance once its - memory has grown past a threshold — before every sweep in the Svelte and TypeScript - groups, every few in CSS — and that instance's slower first sweep adds about 1–4% to - Biome's rows. There's no native Biome entry: its in-process API, + so its rows carry that wrapper. There's no native Biome entry: its in-process API, @biomejs/js-api, runs only on its wasm builds, and the native engine ships only as the biome CLI, a separate process rather than a library, which the CLI section times.
  • +
  • + The harness swaps in a fresh Biome wasm instance once its memory has grown past a + threshold — before every sweep in the Svelte and TypeScript groups, every few in CSS — + and that instance's slower first sweep adds about 3–4% to Biome's rows. +
  • The dprint entry is dprint-plugin-typescript, the @@ -628,8 +630,8 @@

    • - The snapshot's third-party component libraries are left out: they would dominate the - Svelte set. The CLI section's Svelte corpus draws on them, and shares only its kit and + The snapshot's third-party Svelte libraries and tooling are left out: they would dominate + the Svelte set. The CLI section's Svelte corpus draws on them, and shares only its kit and svelte.dev trees with this one{cli_svelte_pin_differs ? ', vendored at a different corpora commit' : ''}.
    • diff --git a/src/routes/docs/benchmarks/BenchmarksCliSection.svelte b/src/routes/docs/benchmarks/BenchmarksCliSection.svelte index 186f0a5..999a734 100644 --- a/src/routes/docs/benchmarks/BenchmarksCliSection.svelte +++ b/src/routes/docs/benchmarks/BenchmarksCliSection.svelte @@ -90,14 +90,14 @@ that adds tsv. It times the whole CLI end to end — process spawn, file discovery, I/O, each tool's default multi-file parallelism — plus peak memory: what you experience typing the command, on real code. - Upstream's JSX scenarios are left out, since tsv has no JSX/TSX parser. Every formatter is - installed from npm, pinned by the fork's lockfile, and the other tools are timed through their - packages' Node bins. Against them, tsv has two rows. {CLI_TSV_NPM_LABEL} is the - like-for-like one: the Node bin of + Upstream's other three scenarios are left out, since their corpora include JSX and tsv has no + JSX/TSX parser. Every formatter is installed from npm, pinned by the fork's lockfile, and the + other tools are timed through their packages' Node bins. Against them, tsv has two rows. + {CLI_TSV_NPM_LABEL} is the like-for-like one: the Node bin of @fuzdev/tsv, what - npx tsv runs, launching the native binary as Biome's and rsvelte-fmt's bins do. The - plain tsv row runs the binary directly from the platform package, skipping Node: - what the binary costs on its own. + npx tsv runs once it's installed, launching the native binary as Biome's and + rsvelte-fmt's bins do. The plain tsv row runs the binary directly from the platform + package, skipping Node: what the binary costs on its own.

      Each table's ratios are against its highlighted row — {CLI_TSV_NPM_LABEL} where tsv @@ -114,29 +114,27 @@

    • tsv, Oxfmt, Biome, and rsvelte-fmt parallelize across files; Prettier's stable CLI formats - them one at a time (its worker pool needs --experimental-cli plus that CLI's - --parallel, which the harness leaves off). No tool's thread count is pinned, so - the wall-clock ratios bake in each tool's parallelism, scale with core count, and mean - little apart from this machine. The CPU ratio column — - hyperfine's user plus system time, summed - across threads and child processes — is the parallelism-neutral view, but only a rough - engine proxy: it also counts work beside the formatting, enough that even Prettier's CPU - time runs above its wall-clock. + them one at a time (its worker pool comes with --experimental-cli, which the + harness leaves off). No tool's thread count is pinned, so the wall-clock ratios bake in each + tool's parallelism, scale with core count, and mean little apart from this machine.
    • - On the multi-file scenarios, CPU ratios barely move between tsv's two rows, since the - dispatcher's fixed launch cost is small beside the CPU a repo takes: on the TypeScript repo - tsv leads Oxfmt ~{npm_ts_cpu_vs_oxfmt} in CPU through the dispatcher and ~{ts_cpu_vs_oxfmt} - as the bare binary, where wall-clock swings from ~{npm_ts_vs_oxfmt} to ~{ts_wall_vs_oxfmt}. + The CPU ratio column — hyperfine's user + plus system time, summed across threads and child processes — is the parallelism-neutral + view, but only a rough engine proxy: it also counts work beside the formatting, enough that + even Prettier's CPU time runs above its wall-clock.
    • tsv's dispatcher adds a fixed ~{npm_overhead} over the bare binary, most of it Node's own startup (a bare node -e "" takes ~{format_ms(node_startup_ms)} on this machine), which every other npm-bin row pays too. That makes it ~{delivery_npm_wall} the - binary's time on the delivery table's one file, but ~{npm_ts_cost} on the TypeScript repo. + binary's time on the delivery table's one file but ~{npm_ts_cost} on the TypeScript repo, + where CPU ratios move far less than wall-clock: tsv leads Oxfmt ~{npm_ts_cpu_vs_oxfmt} in + CPU through the dispatcher and ~{ts_cpu_vs_oxfmt} as the bare binary, against + ~{npm_ts_vs_oxfmt} and ~{ts_wall_vs_oxfmt} wall-clock. @fuzdev/tsv-wasm - takes ~{wasm_wall} the binary's time and ~{wasm_memory} its memory on that one file — still - well ahead of both Prettier rows there, but behind Oxfmt and Biome. + takes ~{wasm_wall} the binary's time and ~{wasm_memory} its memory on that one file, still + well ahead of both Prettier rows in the single-file table but behind Oxfmt and Biome.
    • Through its dispatcher tsv uses {format_ratio_range(npm_memory)} less peak memory than every diff --git a/src/routes/docs/benchmarks/benchmark_tools.ts b/src/routes/docs/benchmarks/benchmark_tools.ts index 954f600..758ea6c 100644 --- a/src/routes/docs/benchmarks/benchmark_tools.ts +++ b/src/routes/docs/benchmarks/benchmark_tools.ts @@ -122,7 +122,7 @@ export const TOOL_SUPPORT: ReadonlyArray = [ css: { format: true }, svelte: { format: 'experimental' } }, - other: 'JSON, GraphQL, and experimental HTML, Vue, Astro', + other: 'JSON, GraphQL, HTML (opt-in), and experimental Vue, Astro', rows: { format: ['biome-wasm'] }, cli_labels: ['biome'] }, diff --git a/src/test/benchmark_data.prose.test.ts b/src/test/benchmark_data.prose.test.ts index 38a5064..f3d38ce 100644 --- a/src/test/benchmark_data.prose.test.ts +++ b/src/test/benchmark_data.prose.test.ts @@ -292,8 +292,8 @@ describe('prose ratios resolve', () => { }); test('the CLI CPU-work note reads the way the numbers run', () => { - // "CPU ratios barely move between tsv's two rows ... where wall-clock swings from - // ~A to ~B" — the two CPU leads must sit inside the wall-clock span: dispatcher + // "CPU ratios move far less than wall-clock: tsv leads Oxfmt ~C ... and ~D ..., + // against ~A and ~B wall-clock" — the two CPU leads must sit inside the wall-clock span: dispatcher // wall < dispatcher CPU <= bare CPU < bare wall. Any one flipping on a refresh // leaves the note explaining the opposite of what the table shows. const defined = (value: number | undefined, name: string): number => { From 66729e7a891b3982982bf084c59dd8cfffcceb45 Mon Sep 17 00:00:00 2001 From: Ryan Atkinson Date: Wed, 23 Sep 2026 18:19:03 -0400 Subject: [PATCH 215/218] wip --- src/routes/docs/benchmarks/+page.svelte | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/routes/docs/benchmarks/+page.svelte b/src/routes/docs/benchmarks/+page.svelte index 9c2f07c..1dc4b9f 100644 --- a/src/routes/docs/benchmarks/+page.svelte +++ b/src/routes/docs/benchmarks/+page.svelte @@ -372,7 +372,7 @@
    • The harness swaps in a fresh Biome wasm instance once its memory has grown past a threshold — before every sweep in the Svelte and TypeScript groups, every few in CSS — - and that instance's slower first sweep adds about 3–4% to Biome's rows. + and that instance's slower first sweep adds a few percent to Biome's rows.
    • The dprint entry is From 5ecf8bf6316dc27a772459b0ca4e3ed9050ee662 Mon Sep 17 00:00:00 2001 From: Ryan Atkinson Date: Wed, 23 Sep 2026 19:03:58 -0400 Subject: [PATCH 216/218] wip --- src/routes/docs/benchmarks/+page.svelte | 140 ++++++++++-------- .../docs/benchmarks/BenchmarksCli.svelte | 15 +- .../benchmarks/BenchmarksCliSection.svelte | 30 ++-- src/routes/docs/benchmarks/benchmark_data.ts | 9 +- src/routes/docs/benchmarks/benchmark_tools.ts | 2 +- src/routes/docs/benchmarks/benchmarks_cli.ts | 5 +- .../docs/benchmarks/benchmarks_prose.ts | 3 + .../benchmarks/formatter_benchmark_data.ts | 6 + src/test/benchmark_data.prose.test.ts | 12 +- src/test/benchmark_data.test.ts | 14 +- 10 files changed, 149 insertions(+), 87 deletions(-) diff --git a/src/routes/docs/benchmarks/+page.svelte b/src/routes/docs/benchmarks/+page.svelte index 1dc4b9f..7abd0ce 100644 --- a/src/routes/docs/benchmarks/+page.svelte +++ b/src/routes/docs/benchmarks/+page.svelte @@ -123,11 +123,14 @@ }; const format_ts_vs_oxfmt = speedup('format_ts_vs_oxfmt'); const format_ts_vs_prettier = speedup('format_ts_vs_prettier'); + const format_ts_wasm_vs_prettier = speedup('format_ts_wasm_vs_prettier'); const format_ts_vs_biome = speedup('format_ts_vs_biome'); const format_svelte_vs_prettier = speedup('format_svelte_vs_prettier'); + const format_svelte_wasm_vs_prettier = speedup('format_svelte_wasm_vs_prettier'); const format_svelte_vs_biome = speedup('format_svelte_vs_biome'); const format_css_vs_oxfmt = speedup('format_css_vs_oxfmt'); const format_css_vs_prettier = speedup('format_css_vs_prettier'); + const format_css_wasm_vs_prettier = speedup('format_css_wasm_vs_prettier'); const format_css_vs_biome = speedup('format_css_vs_biome'); const parse_ts_vs_oxc = speedup('parse_ts_vs_oxc'); // tsv's default `loc`-bearing wire against the reference parser it's a drop-in for @@ -218,8 +221,9 @@

      - Compared to Oxc and Biome, tsv ships smaller artifacts, capability for capability, and - formats its three languages faster in every pairing measured here. + Compared to Oxc and Biome, tsv formats its three languages faster in every pairing measured + here, and ships smaller artifacts capability for capability, except a native parser alone, + where tsv publishes only its full build.

      Except in the CLI section, every timing here is in-process and one file at a time, isolating @@ -230,27 +234,29 @@

      • Formatting TypeScript, tsv is ~{format_ts_vs_oxfmt} faster than Oxfmt (native-vs-native), - ~{format_ts_vs_prettier} faster than Prettier (native Rust vs Prettier's JS), and - ~{format_ts_vs_biome} faster than Biome (wasm-vs-wasm). + ~{format_ts_vs_prettier} faster than Prettier (native Rust vs Prettier's JS; + ~{format_ts_wasm_vs_prettier} as wasm), and ~{format_ts_vs_biome} faster than Biome + (wasm-vs-wasm).
      • - Formatting Svelte, tsv is ~{format_svelte_vs_prettier} faster than Prettier and - ~{format_svelte_vs_biome} faster than Biome, same pairings. Neither Oxc nor Biome ships a - dedicated Svelte formatter: Oxfmt delegates Svelte to Prettier, and Biome's row is its - experimental HTML path. + Formatting Svelte, tsv is ~{format_svelte_vs_prettier} (~{format_svelte_wasm_vs_prettier} + as wasm) faster than Prettier and ~{format_svelte_vs_biome} faster than Biome, same + pairings. Neither Oxc nor Biome ships a dedicated Svelte formatter: Oxfmt delegates Svelte + to Prettier, and Biome's row is its experimental HTML path.
      • Formatting CSS, it's ~{format_css_vs_oxfmt} faster than Oxfmt, ~{format_css_vs_prettier} - faster than Prettier, and ~{format_css_vs_biome} faster than Biome, same pairings. + (~{format_css_wasm_vs_prettier} as wasm) faster than Prettier, and ~{format_css_vs_biome} + faster than Biome, same pairings.
      • - Parsing TypeScript, native tsv's span-only AST is ~{parse_ts_vs_oxc} faster than Oxc's and + Parsing TypeScript, native tsv's span-only AST is ~{parse_ts_vs_oxc} faster than Oxc's, + largely because Oxc's carries more (see + {PARSE_SECTION_TITLE}), and ~{parse_ts_yuku_vs_tsv} slower than yuku-parser's. Its default AST adds per-node line/column loc for drop-in acorn and Svelte compatibility, at ~{parse_ts_loc_cost} the span-only time: ~{parse_ts_vs_acorn} faster than - acorn-typescript, the parser it replaces, but behind Oxc and swc. That AST is checked - against acorn's and Svelte's at corpus scale, but hasn't yet been fed through Svelte's - compiler end to end. + acorn-typescript, the parser it replaces, but behind Oxc and swc.
      • Parsing Svelte, that default AST is ~{parse_svelte_vs_compiler} faster than @@ -362,12 +368,15 @@ pipeline that formats the markup, script, and style (without the flag it returns only the formatted script). It parses the template's expressions but leaves them as written, where Prettier and tsv reprint them, so its Svelte row does somewhat less work than - theirs. Its in-process API's only format entry point, formatContent, also - opens the file in its workspace, pulls syntax diagnostics, and closes it on every call, - so its rows carry that wrapper. There's no native Biome entry: its in-process API, - @biomejs/js-api, runs only on its wasm builds, and the native engine ships - only as the biome CLI, a separate process rather than a library, which the - CLI section times. + theirs. +
      • +
      • + Biome's in-process API's only format entry point, formatContent, also opens + the file in its workspace, pulls syntax diagnostics, and closes it on every call, so its + rows carry that wrapper, roughly 5–10% of their time. There's no native Biome entry: its + in-process API, @biomejs/js-api, runs only on its wasm builds, and the + native engine ships only as the biome CLI, a separate process rather than a + library, which the CLI section times.
      • The harness swaps in a fresh Biome wasm instance once its memory has grown past a @@ -408,11 +417,14 @@ (tsv json / tsv-wasm json) carries a per-node loc (line/column) object that oxc-parser's span-only AST omits, at ~{parse_ts_loc_cost} the time without it on the TypeScript corpus. The no-locs entries drop it for a - span-only wire of Oxc's kind, so they are the payload-matched comparison with oxc-parser, - though the shapes still differ in detail. The internal entries build tsv's - in-Rust AST and stop — no serialization, nothing materialized in JS — so they show raw - engine speed, and their gap to the json entries is what serializing and handing - off costs tsv, not a cross-tool comparison. + span-only wire of Oxc's kind, the closest comparison with oxc-parser but not an equal one: + Oxc's AST also writes out default-valued fields tsv omits (optional: false, + decorators: [], typeAnnotation: null), about a third more bytes, + and its call also returns comments and module records, so much of the gap between them is + payload. The internal entries build tsv's in-Rust AST and stop — no + serialization, nothing materialized in JS — so they show raw engine speed, and their gap to + the json entries is what serializing and handing off costs tsv, not a + cross-tool comparison.

        yuku-parser, a JS/TS parser written in Zig, emits the same span-only AST as Oxc, so it too @@ -437,9 +449,9 @@ most noise.

      • - Biome is grayed out across all three parse groups: its in-process API exposes formatting - and linting only, so the AST it parses never reaches JS to be measured. oxc-parser is - grayed out in the CSS group: Oxc formats CSS (in Oxfmt) but ships no CSS parse binding. + Biome is grayed out across all three parse groups: its API hands JS its syntax tree only + as a debug-printed string, not an AST to materialize and time. oxc-parser is grayed out + in the CSS group: Oxc formats CSS (in Oxfmt) but ships no CSS parse binding.
      • oxc-parser's wasm row runs an older release than its native row — the newest whose wasi @@ -447,10 +459,14 @@ (both listed under {DETAILS_SECTION_TITLE}).
      • +
      • + tsv's default AST is checked against acorn's and Svelte's at corpus scale, but hasn't + yet been fed through Svelte's compiler end to end. +
      • When line/column is needed, the span-only wire plus JS-side reconstruct_locations beats tsv's default loc-bearing wire on - TypeScript — see the + TypeScript (on Svelte the two roughly tie) — see the 's span-only section.
      • @@ -476,7 +492,7 @@ the base of Prettier's CSS parse, so it's the parse-side counterpart of the Prettier format entry. It isn't payload-matched to tsv: it keeps selectors as strings where parseCss and tsv parse them, but stores positions and raw whitespace on - every node — fewer nodes, about as many objects. + every node — fewer nodes, though not proportionally fewer objects.
      @@ -520,10 +536,11 @@ smaller on scope, while dprint (TypeScript/JS and JSX only) is larger regardless.
    • - Biome's build carries a parser, formatter, and linter for every language it supports. - yuku-parser parses TypeScript, JS, JSX, and TSX only, where tsv's parse-only build - beside it carries Svelte and CSS parsers too. Oxfmt ships no wasm build, hence its - grayed-out slot under Formatter. + Biome's build carries its whole toolchain: a parser, formatter, and linter for every + language it supports, plus assists like import sorting, GritQL search and plugins, and + a module graph. yuku-parser parses TypeScript, JS, JSX, and TSX only, where tsv's + parse-only build beside it carries Svelte and CSS parsers too. Oxfmt ships no wasm + build, hence its grayed-out slot under Formatter.
    @@ -544,9 +561,10 @@ tsv CLI binary. Either package is close to twice its entry here.
  • - The (ffi) entries are tsv's C-ABI build, which isn't published — what the - engine costs in that configuration, not something you can install; the cross-runtime - section's Deno run loads the full one. + The (ffi) entries are tsv's C-ABI build, which isn't published (natively, + tsv ships only its full N-API addon) — what the engine costs in that configuration, + not something you can install; the cross-runtime section's Deno run loads the full + one.
  • The {OXC_FULL_LABEL} entry under Full toolchain sums Oxc's separate @@ -573,6 +591,27 @@ + + +

    + The same harness runs under three JS runtimes — Node, Deno, and Bun; the in-process charts + above are the Node run, chosen as the default N-API host, not for speed. The native entry + differs by runtime: Node and Bun load tsv's N-API addon, Deno its C-FFI library, which + shares its code but crosses a different binding boundary and aborts on panic where the addon + unwinds. So a per-runtime delta on the same row comes from the JS engine, the host's N-API + implementation, or that binding and build, not from tsv's algorithms. +

    + + +
    +

    @@ -603,7 +642,9 @@ steady, so whatever remains, thermal drift included, falls on the later rows. Against every alternative that bias counts for tsv; against the reference row, which runs first, it counts against tsv — Prettier in the format charts, and svelte/compiler, acorn-typescript, and - parseCss in the parse ones. + parseCss in the parse ones. The size of that bias hasn't been measured; no + row's timings shift more than ~{format_share_approx(sweeps.drift_max)} from its first half + to its second.

    One asymmetry isn't isolated: Oxfmt's programmatic format is async-only (as is @@ -630,7 +671,7 @@

    • - The snapshot's third-party Svelte libraries and tooling are left out: they would dominate + The snapshot's community Svelte libraries and tooling are left out: they would dominate the Svelte set. The CLI section's Svelte corpus draws on them, and shares only its kit and svelte.dev trees with this one{cli_svelte_pin_differs ? ', vendored at a different corpora commit' : ''}. @@ -658,31 +699,10 @@ not a universal figure.
    -
    +

    Each source links its upstream at the commit the snapshot vendored.

    - - - -

    - The same harness runs under three JS runtimes — Node, Deno, and Bun; the in-process charts - above are the Node run, chosen as the default N-API host, not for speed. The native entry - differs by runtime: Node and Bun load tsv's N-API addon, Deno its C-FFI library, which - shares its code but crosses a different binding boundary and aborts on panic where the addon - unwinds. So a per-runtime delta on the same row comes from the JS engine, the host's N-API - implementation, or that binding and build, not from tsv's algorithms. -

    - - -
    {/if} diff --git a/src/routes/docs/benchmarks/BenchmarksCli.svelte b/src/routes/docs/benchmarks/BenchmarksCli.svelte index c13bc17..d872128 100644 --- a/src/routes/docs/benchmarks/BenchmarksCli.svelte +++ b/src/routes/docs/benchmarks/BenchmarksCli.svelte @@ -1,6 +1,12 @@ @@ -90,9 +92,10 @@ that adds tsv. It times the whole CLI end to end — process spawn, file discovery, I/O, each tool's default multi-file parallelism — plus peak memory: what you experience typing the command, on real code. - Upstream's other three scenarios are left out, since their corpora include JSX and tsv has no - JSX/TSX parser. Every formatter is installed from npm, pinned by the fork's lockfile, and the - other tools are timed through their packages' Node bins. Against them, tsv has two rows. + Upstream's other three scenarios are left out: their corpora include JSX, which tsv doesn't + parse, and two also sort imports and Tailwind classes or format languages beyond tsv's three. + Every formatter is installed from npm, pinned by the fork's lockfile, and the other tools are + timed through their packages' Node bins. Against them, tsv has two rows. {CLI_TSV_NPM_LABEL} is the like-for-like one: the Node bin of @fuzdev/tsv, what npx tsv runs once it's installed, launching the native binary as Biome's and @@ -128,13 +131,16 @@ tsv's dispatcher adds a fixed ~{npm_overhead} over the bare binary, most of it Node's own startup (a bare node -e "" takes ~{format_ms(node_startup_ms)} on this machine), which every other npm-bin row pays too. That makes it ~{delivery_npm_wall} the - binary's time on the delivery table's one file but ~{npm_ts_cost} on the TypeScript repo, - where CPU ratios move far less than wall-clock: tsv leads Oxfmt ~{npm_ts_cpu_vs_oxfmt} in - CPU through the dispatcher and ~{ts_cpu_vs_oxfmt} as the bare binary, against - ~{npm_ts_vs_oxfmt} and ~{ts_wall_vs_oxfmt} wall-clock. + binary's time on the delivery table's one file but ~{npm_ts_cost} on the TypeScript repo. + Against the repo's multi-threaded work it adds little CPU: tsv leads Oxfmt + ~{npm_ts_cpu_vs_oxfmt} in CPU through the dispatcher and ~{ts_cpu_vs_oxfmt} as the bare + binary, against ~{npm_ts_vs_oxfmt} and ~{ts_wall_vs_oxfmt} wall-clock. +
  • +
  • @fuzdev/tsv-wasm - takes ~{wasm_wall} the binary's time and ~{wasm_memory} its memory on that one file, still - well ahead of both Prettier rows in the single-file table but behind Oxfmt and Biome. + takes ~{wasm_wall} the binary's time and ~{wasm_memory} its memory on the delivery table's + one file, still well ahead of both Prettier rows in the single-file table but behind Oxfmt + and Biome.
  • Through its dispatcher tsv uses {format_ratio_range(npm_memory)} less peak memory than every @@ -187,5 +193,9 @@ build{cli_tsv_binary.built ? ` from ${cli_tsv_binary.built}` : ''}, {/if} and its wasm row @fuzdev/tsv-wasm {cli_tsv_wasm_version}. + {#if cli_plugin_oxc_version} + Its prettier + oxc-parser row runs @prettier/plugin-oxc + {cli_plugin_oxc_version}, with its own oxc-parser, not the release listed there. + {/if}

    diff --git a/src/routes/docs/benchmarks/benchmark_data.ts b/src/routes/docs/benchmarks/benchmark_data.ts index 04bcece..9ec27f6 100644 --- a/src/routes/docs/benchmarks/benchmark_data.ts +++ b/src/routes/docs/benchmarks/benchmark_data.ts @@ -777,6 +777,11 @@ export interface SweepStats { /** The span of cleaned timing counts the report kept per row. */ sample_size_min: number | undefined; sample_size_max: number | undefined; + /** + * The largest level shift any row showed while it was measured (`|drift|`, a + * fraction) — what bounds, loosely, how far a row's timings moved in place. + */ + drift_max: number | undefined; } export const derive_sweep_stats = (baseline: BenchmarkBaseline): SweepStats => { @@ -787,12 +792,14 @@ export const derive_sweep_stats = (baseline: BenchmarkBaseline): SweepStats => { categorize_name(e.name) === 'canonical' ? (e.min_iterations ?? []) : [] ); const sample_sizes = baseline.entries.flatMap((e) => e.sample_size ?? []); + const drifts = baseline.entries.flatMap((e) => (e.drift == null ? [] : Math.abs(e.drift))); const floor = min_of(floors); return { floor, canonical_floor: min_of(canonical_floors) ?? floor, sample_size_min: min_of(sample_sizes), - sample_size_max: sample_sizes.length ? Math.max(...sample_sizes) : undefined + sample_size_max: sample_sizes.length ? Math.max(...sample_sizes) : undefined, + drift_max: drifts.length ? Math.max(...drifts) : undefined }; }; diff --git a/src/routes/docs/benchmarks/benchmark_tools.ts b/src/routes/docs/benchmarks/benchmark_tools.ts index 758ea6c..268721f 100644 --- a/src/routes/docs/benchmarks/benchmark_tools.ts +++ b/src/routes/docs/benchmarks/benchmark_tools.ts @@ -122,7 +122,7 @@ export const TOOL_SUPPORT: ReadonlyArray = [ css: { format: true }, svelte: { format: 'experimental' } }, - other: 'JSON, GraphQL, HTML (opt-in), and experimental Vue, Astro', + other: 'JSON, GraphQL, GritQL, HTML (opt-in), and experimental Vue, Astro', rows: { format: ['biome-wasm'] }, cli_labels: ['biome'] }, diff --git a/src/routes/docs/benchmarks/benchmarks_cli.ts b/src/routes/docs/benchmarks/benchmarks_cli.ts index a9592c7..6278c61 100644 --- a/src/routes/docs/benchmarks/benchmarks_cli.ts +++ b/src/routes/docs/benchmarks/benchmarks_cli.ts @@ -63,6 +63,8 @@ export interface CliScenario extends CliScenarioCopy { target: string; /** Which revision of the corpus the numbers came from, as the harness records it. */ corpus: string; + /** How many files the scenario formatted, when the harness recorded it. */ + files?: number; /** * Every formatter the scenario benched, as displayed, in the harness's order — * timed or only preflight-checked. An abort before timing empties `results` @@ -184,7 +186,7 @@ const SCENARIO_COPY: Record = { [CLI_SVELTE_KEY]: { heading: 'Svelte corpus', description: - 'Two Rust Svelte-native formatters head-to-head on a third-party .svelte corpus, rsvelte-fmt configured to tsv’s fixed style. rsvelte-fmt’s time includes the Oxfmt it launches for non-.svelte files, which walks the corpus and finds none.', + 'Two Rust Svelte-native formatters head-to-head on a third-party .svelte corpus (over half of it flowbite-svelte), rsvelte-fmt configured to tsv’s fixed style. rsvelte-fmt’s time includes the Oxfmt it launches for non-.svelte files, which walks the corpus and finds none.', abort_context: 'rsvelte-fmt 0.7.x can abort when its output and stderr share a pipe, and the harness doesn’t retry.', tsv_only: false @@ -284,6 +286,7 @@ export const to_cli_scenarios = ( ...copy, target: scenario.target, corpus: scenario.corpus, + ...(scenario.files === undefined ? null : { files: scenario.files }), labels: to_labels(scenario), results: to_results(scenario), warmup_runs: scenario.warmup_runs, diff --git a/src/routes/docs/benchmarks/benchmarks_prose.ts b/src/routes/docs/benchmarks/benchmarks_prose.ts index 022b357..909dac6 100644 --- a/src/routes/docs/benchmarks/benchmarks_prose.ts +++ b/src/routes/docs/benchmarks/benchmarks_prose.ts @@ -16,11 +16,14 @@ export type InProcessPair = readonly [group: string, slower: string, faster: str export const IN_PROCESS_PAIRS = { format_ts_vs_oxfmt: ['format/typescript', 'oxfmt', 'tsv'], format_ts_vs_prettier: ['format/typescript', 'prettier', 'tsv'], + format_ts_wasm_vs_prettier: ['format/typescript', 'prettier', 'tsv-wasm'], format_ts_vs_biome: ['format/typescript', 'biome-wasm', 'tsv-wasm'], format_svelte_vs_prettier: ['format/svelte', 'prettier', 'tsv'], + format_svelte_wasm_vs_prettier: ['format/svelte', 'prettier', 'tsv-wasm'], format_svelte_vs_biome: ['format/svelte', 'biome-wasm', 'tsv-wasm'], format_css_vs_oxfmt: ['format/css', 'oxfmt', 'tsv'], format_css_vs_prettier: ['format/css', 'prettier', 'tsv'], + format_css_wasm_vs_prettier: ['format/css', 'prettier', 'tsv-wasm'], format_css_vs_biome: ['format/css', 'biome-wasm', 'tsv-wasm'], parse_ts_vs_oxc: ['parse/typescript', 'oxc-parser', 'tsv-json-no-locations'], // the drop-in comparison: tsv's default `loc`-bearing wire against the reference it replaces diff --git a/src/routes/docs/benchmarks/formatter_benchmark_data.ts b/src/routes/docs/benchmarks/formatter_benchmark_data.ts index 991cf3a..d5249d8 100644 --- a/src/routes/docs/benchmarks/formatter_benchmark_data.ts +++ b/src/routes/docs/benchmarks/formatter_benchmark_data.ts @@ -90,6 +90,12 @@ export const FormatterScenario = z.strictObject({ settle_seconds: z.number().nonnegative().optional(), /** Empty in the harness's upstream scenarios, which run no preflight. */ preflight: z.array(FormatterPreflight), + /** + * How many files the scenario formatted: the count every formatter that reports + * one agreed on in preflight. Absent where none reports one, and from reports + * that predate the field. + */ + files: z.number().int().positive().optional(), /** * Why the harness stopped early. Before timing (preflight failed) there are no * timings, speedups, or memory rows and the `preflight` entries say which diff --git a/src/test/benchmark_data.prose.test.ts b/src/test/benchmark_data.prose.test.ts index f3d38ce..3c53197 100644 --- a/src/test/benchmark_data.prose.test.ts +++ b/src/test/benchmark_data.prose.test.ts @@ -160,11 +160,13 @@ describe('prose ratios resolve', () => { } }); - test('the pairings the copy calls payload-matched are, and the ones it excludes are not', () => { - // The page names four pairings as comparing the same PRODUCT and rules three out - // ("swc's AST ... matches neither tsv wire", and the `no-locs` entries, not the - // default wire, "are the payload-matched comparison with oxc-parser"). Those are claims about - // the report's `payload` tiers, so read them off it rather than trusting prose. + test('the pairings the copy compares by payload tier share one, and the ones it excludes do not', () => { + // The page names four pairings as comparing the same kind of PRODUCT and rules three + // out ("swc's AST ... matches neither tsv wire", and the `no-locs` entries, not the + // default wire, are "the closest comparison with oxc-parser"). Those are claims about + // the report's `payload` tiers, so read them off it rather than trusting prose. A + // shared tier is a shape, not a byte count: the copy says Oxc's span-only AST runs + // larger than tsv's. const entry = (group: string, name: string) => { const found = benchmarks_json.entries.find((e) => e.group === group && e.name === name); assert(found, `${group}/${name} is missing`); diff --git a/src/test/benchmark_data.test.ts b/src/test/benchmark_data.test.ts index b77b55e..9082d51 100644 --- a/src/test/benchmark_data.test.ts +++ b/src/test/benchmark_data.test.ts @@ -316,9 +316,9 @@ describe('derive_sweep_stats', () => { const stats = derive_sweep_stats( create_baseline({ entries: [ - entry({ name: 'prettier', min_iterations: 16, sample_size: 16 }), - entry({ name: 'tsv', min_iterations: 8, sample_size: 900 }), - entry({ name: 'biome-wasm', min_iterations: 8, sample_size: 6 }) + entry({ name: 'prettier', min_iterations: 16, sample_size: 16, drift: 0.004 }), + entry({ name: 'tsv', min_iterations: 8, sample_size: 900, drift: -0.012 }), + entry({ name: 'biome-wasm', min_iterations: 8, sample_size: 6, drift: null }) ] }) ); @@ -326,21 +326,23 @@ describe('derive_sweep_stats', () => { floor: 8, canonical_floor: 16, sample_size_min: 6, - sample_size_max: 900 + sample_size_max: 900, + drift_max: 0.012 }); }); test('a report with only untimed rows reads as undefined, never Infinity', () => { const stats = derive_sweep_stats( create_baseline({ - entries: [entry({ sample_size: null, min_iterations: null })] + entries: [entry({ sample_size: null, min_iterations: null, drift: null })] }) ); assert.deepEqual(stats, { floor: undefined, canonical_floor: undefined, sample_size_min: undefined, - sample_size_max: undefined + sample_size_max: undefined, + drift_max: undefined }); }); }); From cdf6028fb41411d02b3055a3d1c24cc3809f59ad Mon Sep 17 00:00:00 2001 From: Ryan Atkinson Date: Sun, 27 Sep 2026 21:21:26 -0400 Subject: [PATCH 217/218] fix: match the color-scheme loader to fuz_ui's CSP hash --- src/app.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app.html b/src/app.html index e3061bc..06d95cd 100644 --- a/src/app.html +++ b/src/app.html @@ -11,7 +11,7 @@ ((c) => c === 'dark' || (c !== 'light' && matchMedia('(prefers-color-scheme:dark)').matches) ? 'dark' - : 'light')(localStorage.getItem('fuz:color-scheme')), + : 'light')(localStorage.getItem('fuz:color-scheme')) ); From 773647534079e503aa8985525fcb9a969a415f57 Mon Sep 17 00:00:00 2001 From: Ryan Atkinson Date: Tue, 29 Sep 2026 13:24:04 -0400 Subject: [PATCH 218/218] docs: drop the never-run-the-dev-server rule --- CLAUDE.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index fee48c3..e44b93e 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -17,8 +17,6 @@ gro deploy # build, commit, and push to deploy branch gro sync # regenerate files and run svelte-kit sync ``` -IMPORTANT for AI agents: Do NOT run `gro dev` - the developer will manage the dev server. - ## Key dependencies - Svelte 5 - component framework with runes