benchforge 0.1.11 → 0.2.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +20 -0
- package/README.md +99 -294
- package/bin/benchforge +1 -2
- package/dist/AnalyzeArchive-8NCJhmhS.mjs +145 -0
- package/dist/AnalyzeArchive-8NCJhmhS.mjs.map +1 -0
- package/dist/BenchMatrix-BZVrBB_h.mjs +1050 -0
- package/dist/BenchMatrix-BZVrBB_h.mjs.map +1 -0
- package/dist/{BenchRunner-BzyUfiyB.d.mts → BenchRunner-DglX1NOn.d.mts} +119 -66
- package/dist/CoverageSampler-D5T9DRqe.mjs +27 -0
- package/dist/CoverageSampler-D5T9DRqe.mjs.map +1 -0
- package/dist/Formatters-BWj3d4sv.mjs +95 -0
- package/dist/Formatters-BWj3d4sv.mjs.map +1 -0
- package/dist/{HeapSampler-B8dtKHn1.mjs → HeapSampler-Dq-hpXem.mjs} +4 -4
- package/dist/HeapSampler-Dq-hpXem.mjs.map +1 -0
- package/dist/RunBenchCLI-C17DrJz8.mjs +3075 -0
- package/dist/RunBenchCLI-C17DrJz8.mjs.map +1 -0
- package/dist/StatisticalUtils-BD92crgM.mjs +255 -0
- package/dist/StatisticalUtils-BD92crgM.mjs.map +1 -0
- package/dist/TimeSampler-Ds8n7l2B.mjs +29 -0
- package/dist/TimeSampler-Ds8n7l2B.mjs.map +1 -0
- package/dist/ViewerServer-BJhdnxlN.mjs +639 -0
- package/dist/ViewerServer-BJhdnxlN.mjs.map +1 -0
- package/dist/ViewerServer-CuMNdNBz.mjs +2 -0
- package/dist/bin/benchforge.mjs +4 -5
- package/dist/bin/benchforge.mjs.map +1 -1
- package/dist/index.d.mts +711 -558
- package/dist/index.mjs +98 -3
- package/dist/index.mjs.map +1 -0
- package/dist/runners/WorkerScript.d.mts +12 -4
- package/dist/runners/WorkerScript.mjs +77 -105
- package/dist/runners/WorkerScript.mjs.map +1 -1
- package/dist/viewer/assets/CIPlot-BkOvMoMa.js +1 -0
- package/dist/viewer/assets/HistogramKde-CmSyUFY0.js +1 -0
- package/dist/viewer/assets/LegendUtils-BJpbn_jr.js +55 -0
- package/dist/viewer/assets/SampleTimeSeries-C4VBhXr3.js +1 -0
- package/dist/viewer/assets/index-Br9bp_cX.js +153 -0
- package/dist/viewer/assets/index-NzXXe_CC.css +1 -0
- package/dist/viewer/index.html +19 -0
- package/dist/viewer/speedscope/LICENSE +21 -0
- package/dist/viewer/speedscope/SourceCodePro-Regular.ttf-ILST5JV6.woff2 +0 -0
- package/dist/viewer/speedscope/favicon-16x16-V2DMIAZS.js +2 -0
- package/dist/viewer/speedscope/favicon-16x16-V2DMIAZS.js.map +7 -0
- package/dist/viewer/speedscope/favicon-16x16-VSI62OPJ.png +0 -0
- package/dist/viewer/speedscope/favicon-32x32-3EB2YCUY.png +0 -0
- package/dist/viewer/speedscope/favicon-32x32-THY3JDJL.js +2 -0
- package/dist/viewer/speedscope/favicon-32x32-THY3JDJL.js.map +7 -0
- package/dist/viewer/speedscope/favicon-FOKUP5Y5.ico +0 -0
- package/dist/viewer/speedscope/favicon-M34RF7BI.js +2 -0
- package/dist/viewer/speedscope/favicon-M34RF7BI.js.map +7 -0
- package/dist/viewer/speedscope/file-format-schema.json +274 -0
- package/dist/viewer/speedscope/index.html +19 -0
- package/dist/viewer/speedscope/jfrview_bg-BLJXNNQB.wasm +0 -0
- package/dist/viewer/speedscope/perf-vertx-stacks-01-collapsed-all-ZNUIGAJL.txt +199 -0
- package/dist/viewer/speedscope/release.txt +3 -0
- package/dist/viewer/speedscope/source-code-pro.LICENSE.md +93 -0
- package/dist/viewer/speedscope/speedscope-GHPHNKXC.css +2 -0
- package/dist/viewer/speedscope/speedscope-GHPHNKXC.css.map +7 -0
- package/dist/viewer/speedscope/speedscope-QZFMJ7VP.js +212 -0
- package/dist/viewer/speedscope/speedscope-QZFMJ7VP.js.map +7 -0
- package/package.json +52 -27
- package/src/bin/benchforge.ts +2 -2
- package/src/cli/AnalyzeArchive.ts +232 -0
- package/src/cli/BrowserBench.ts +322 -0
- package/src/cli/CliArgs.ts +164 -51
- package/src/cli/CliExport.ts +179 -0
- package/src/cli/CliOptions.ts +147 -0
- package/src/cli/CliReport.ts +197 -0
- package/src/cli/FilterBenchmarks.ts +18 -30
- package/src/cli/RunBenchCLI.ts +132 -866
- package/src/cli/SuiteRunner.ts +160 -0
- package/src/cli/ViewerServer.ts +282 -0
- package/src/export/AllocExport.ts +121 -0
- package/src/export/ArchiveExport.ts +146 -0
- package/src/export/ArchiveFormat.ts +50 -0
- package/src/export/CoverageExport.ts +148 -0
- package/src/export/EditorUri.ts +10 -0
- package/src/export/PerfettoExport.ts +64 -99
- package/src/export/SpeedscopeTypes.ts +98 -0
- package/src/export/TimeExport.ts +115 -0
- package/src/index.ts +86 -67
- package/src/matrix/BenchMatrix.ts +230 -0
- package/src/matrix/CaseLoader.ts +8 -6
- package/src/matrix/MatrixDirRunner.ts +153 -0
- package/src/matrix/MatrixFilter.ts +49 -47
- package/src/matrix/MatrixInlineRunner.ts +50 -0
- package/src/matrix/MatrixReport.ts +90 -250
- package/src/matrix/VariantLoader.ts +5 -5
- package/src/profiling/browser/BenchLoop.ts +51 -0
- package/src/profiling/browser/BrowserCDP.ts +133 -0
- package/src/profiling/browser/BrowserGcStats.ts +33 -0
- package/src/profiling/browser/BrowserProfiler.ts +160 -0
- package/src/profiling/browser/CdpClient.ts +82 -0
- package/src/profiling/browser/CdpPage.ts +138 -0
- package/src/profiling/browser/ChromeLauncher.ts +158 -0
- package/src/profiling/browser/ChromeTraceEvent.ts +28 -0
- package/src/profiling/browser/PageLoadMode.ts +61 -0
- package/src/profiling/node/CoverageSampler.ts +27 -0
- package/src/profiling/node/CoverageTypes.ts +23 -0
- package/src/profiling/node/HeapSampleReport.ts +261 -0
- package/src/{heap-sample → profiling/node}/HeapSampler.ts +1 -2
- package/src/{heap-sample → profiling/node}/ResolvedProfile.ts +18 -9
- package/src/profiling/node/TimeSampler.ts +57 -0
- package/src/report/BenchmarkReport.ts +146 -0
- package/src/report/Colors.ts +9 -0
- package/src/report/Formatters.ts +110 -0
- package/src/report/GcSections.ts +151 -0
- package/src/{GitUtils.ts → report/GitUtils.ts} +18 -19
- package/src/report/HtmlReport.ts +223 -0
- package/src/report/ParseStats.ts +73 -0
- package/src/report/StandardSections.ts +147 -0
- package/src/report/ViewerSections.ts +286 -0
- package/src/report/text/TableReport.ts +253 -0
- package/src/report/text/TextReport.ts +123 -0
- package/src/runners/AdaptiveWrapper.ts +116 -236
- package/src/runners/BenchRunner.ts +20 -15
- package/src/{Benchmark.ts → runners/BenchmarkSpec.ts} +5 -6
- package/src/runners/CreateRunner.ts +5 -7
- package/src/runners/GcStats.ts +47 -50
- package/src/{MeasuredResults.ts → runners/MeasuredResults.ts} +43 -37
- package/src/runners/MergeBatches.ts +123 -0
- package/src/{NodeGC.ts → runners/NodeGC.ts} +2 -3
- package/src/runners/RunnerOrchestrator.ts +127 -243
- package/src/runners/RunnerUtils.ts +75 -1
- package/src/runners/SampleStats.ts +100 -0
- package/src/runners/TimingRunner.ts +244 -0
- package/src/runners/TimingUtils.ts +3 -2
- package/src/runners/WorkerScript.ts +135 -151
- package/src/stats/BootstrapDifference.ts +282 -0
- package/src/{PermutationTest.ts → stats/PermutationTest.ts} +8 -17
- package/src/stats/StatisticalUtils.ts +445 -0
- package/src/{tests → test}/AdaptiveConvergence.test.ts +10 -10
- package/src/test/AdaptiveRunner.test.ts +39 -41
- package/src/{tests → test}/AdaptiveSampling.test.ts +9 -9
- package/src/test/AdaptiveStatistics.integration.ts +2 -2
- package/src/{tests → test}/BenchMatrix.test.ts +19 -16
- package/src/test/BenchmarkReport.test.ts +63 -13
- package/src/test/BrowserBench.e2e.test.ts +186 -17
- package/src/test/BrowserBench.test.ts +10 -5
- package/src/test/BuildTimeSection.test.ts +130 -0
- package/src/test/CapSamples.test.ts +82 -0
- package/src/test/CoverageExport.test.ts +115 -0
- package/src/test/CoverageSampler.test.ts +33 -0
- package/src/test/HeapAttribution.test.ts +14 -14
- package/src/{tests → test}/MatrixFilter.test.ts +1 -1
- package/src/{tests → test}/MatrixReport.test.ts +1 -1
- package/src/test/PermutationTest.test.ts +1 -1
- package/src/{tests → test}/RealDataValidation.test.ts +6 -6
- package/src/test/RunBenchCLI.test.ts +39 -38
- package/src/test/RunnerOrchestrator.test.ts +12 -12
- package/src/test/StatisticalUtils.test.ts +48 -12
- package/src/{table-util/test → test}/TableReport.test.ts +2 -2
- package/src/test/TestUtils.ts +12 -7
- package/src/test/TimeExport.test.ts +139 -0
- package/src/test/TimeSampler.test.ts +37 -0
- package/src/test/ViewerLive.e2e.test.ts +159 -0
- package/src/test/ViewerStatic.static.e2e.test.ts +137 -0
- package/src/{tests → test}/fixtures/baseline/impl.ts +1 -1
- package/src/{tests → test}/fixtures/bevy30-samples.ts +3 -1
- package/src/test/fixtures/cases/asyncCases.ts +9 -0
- package/src/{tests → test}/fixtures/cases/cases.ts +5 -2
- package/src/test/fixtures/cases/variants/product.ts +2 -0
- package/src/test/fixtures/cases/variants/sum.ts +2 -0
- package/src/test/fixtures/discover/fast.ts +1 -0
- package/src/{tests → test}/fixtures/discover/slow.ts +1 -1
- package/src/test/fixtures/invalid/bad.ts +1 -0
- package/src/test/fixtures/loader/fast.ts +1 -0
- package/src/{tests → test}/fixtures/loader/slow.ts +1 -1
- package/src/test/fixtures/loader/stateful.ts +2 -0
- package/src/test/fixtures/stateful/stateful.ts +2 -0
- package/src/test/fixtures/variants/extra.ts +1 -0
- package/src/test/fixtures/variants/impl.ts +1 -0
- package/src/test/fixtures/worker/fast.ts +1 -0
- package/src/{tests → test}/fixtures/worker/slow.ts +1 -1
- package/src/viewer/DateFormat.ts +30 -0
- package/src/viewer/Helpers.ts +23 -0
- package/src/viewer/LineData.ts +120 -0
- package/src/viewer/Providers.ts +191 -0
- package/src/viewer/ReportData.ts +123 -0
- package/src/viewer/State.ts +49 -0
- package/src/viewer/Theme.ts +15 -0
- package/src/viewer/components/App.tsx +73 -0
- package/src/viewer/components/DropZone.tsx +71 -0
- package/src/viewer/components/LazyPlot.ts +33 -0
- package/src/viewer/components/SamplesPanel.tsx +214 -0
- package/src/viewer/components/Shell.tsx +26 -0
- package/src/viewer/components/SourcePanel.tsx +216 -0
- package/src/viewer/components/SummaryPanel.tsx +332 -0
- package/src/viewer/components/TabBar.tsx +131 -0
- package/src/viewer/components/TabContent.tsx +46 -0
- package/src/viewer/components/ThemeToggle.tsx +50 -0
- package/src/viewer/index.html +20 -0
- package/src/viewer/main.tsx +4 -0
- package/src/viewer/plots/CIPlot.ts +313 -0
- package/src/{html/browser → viewer/plots}/HistogramKde.ts +33 -38
- package/src/viewer/plots/LegendUtils.ts +134 -0
- package/src/viewer/plots/PlotTypes.ts +85 -0
- package/src/viewer/plots/RenderPlots.ts +230 -0
- package/src/viewer/plots/SampleTimeSeries.ts +306 -0
- package/src/viewer/plots/SvgHelpers.ts +136 -0
- package/src/viewer/plots/TimeSeriesMarks.ts +319 -0
- package/src/viewer/report.css +427 -0
- package/src/viewer/shell.css +357 -0
- package/src/viewer/tsconfig.json +11 -0
- package/dist/BrowserHeapSampler-B6asLKWQ.mjs +0 -202
- package/dist/BrowserHeapSampler-B6asLKWQ.mjs.map +0 -1
- package/dist/GcStats-wX7Xyblu.mjs +0 -77
- package/dist/GcStats-wX7Xyblu.mjs.map +0 -1
- package/dist/HeapSampler-B8dtKHn1.mjs.map +0 -1
- package/dist/TimingUtils-DwOwkc8G.mjs +0 -597
- package/dist/TimingUtils-DwOwkc8G.mjs.map +0 -1
- package/dist/browser/index.js +0 -914
- package/dist/src-B-DDaCa9.mjs +0 -3108
- package/dist/src-B-DDaCa9.mjs.map +0 -1
- package/src/BenchMatrix.ts +0 -380
- package/src/BenchmarkReport.ts +0 -161
- package/src/HtmlDataPrep.ts +0 -148
- package/src/StandardSections.ts +0 -261
- package/src/StatisticalUtils.ts +0 -175
- package/src/TypeUtil.ts +0 -8
- package/src/browser/BrowserGcStats.ts +0 -44
- package/src/browser/BrowserHeapSampler.ts +0 -271
- package/src/export/JsonExport.ts +0 -103
- package/src/export/JsonFormat.ts +0 -91
- package/src/export/SpeedscopeExport.ts +0 -202
- package/src/heap-sample/HeapSampleReport.ts +0 -269
- package/src/html/HtmlReport.ts +0 -131
- package/src/html/HtmlTemplate.ts +0 -284
- package/src/html/Types.ts +0 -88
- package/src/html/browser/CIPlot.ts +0 -287
- package/src/html/browser/LegendUtils.ts +0 -163
- package/src/html/browser/RenderPlots.ts +0 -263
- package/src/html/browser/SampleTimeSeries.ts +0 -389
- package/src/html/browser/Types.ts +0 -96
- package/src/html/browser/index.ts +0 -1
- package/src/html/index.ts +0 -17
- package/src/runners/BasicRunner.ts +0 -364
- package/src/table-util/ConvergenceFormatters.ts +0 -19
- package/src/table-util/Formatters.ts +0 -157
- package/src/table-util/README.md +0 -70
- package/src/table-util/TableReport.ts +0 -293
- package/src/tests/fixtures/cases/asyncCases.ts +0 -7
- package/src/tests/fixtures/cases/variants/product.ts +0 -2
- package/src/tests/fixtures/cases/variants/sum.ts +0 -2
- package/src/tests/fixtures/discover/fast.ts +0 -1
- package/src/tests/fixtures/invalid/bad.ts +0 -1
- package/src/tests/fixtures/loader/fast.ts +0 -1
- package/src/tests/fixtures/loader/stateful.ts +0 -2
- package/src/tests/fixtures/stateful/stateful.ts +0 -2
- package/src/tests/fixtures/variants/extra.ts +0 -1
- package/src/tests/fixtures/variants/impl.ts +0 -1
- package/src/tests/fixtures/worker/fast.ts +0 -1
- /package/src/{table-util/test → test}/TableValueExtractor.test.ts +0 -0
- /package/src/{table-util/test → test}/TableValueExtractor.ts +0 -0
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"src-B-DDaCa9.mjs","names":["red","pc"],"sources":["../src/matrix/CaseLoader.ts","../src/runners/RunnerOrchestrator.ts","../src/BenchMatrix.ts","../src/table-util/Formatters.ts","../src/table-util/TableReport.ts","../src/BenchmarkReport.ts","../src/cli/CliArgs.ts","../src/export/JsonExport.ts","../src/export/PerfettoExport.ts","../src/heap-sample/ResolvedProfile.ts","../src/export/SpeedscopeExport.ts","../src/HtmlDataPrep.ts","../src/heap-sample/HeapSampleReport.ts","../src/html/HtmlTemplate.ts","../src/html/HtmlReport.ts","../src/matrix/MatrixFilter.ts","../src/table-util/ConvergenceFormatters.ts","../src/StandardSections.ts","../src/matrix/MatrixReport.ts","../src/cli/FilterBenchmarks.ts","../src/cli/RunBenchCLI.ts","../src/GitUtils.ts"],"sourcesContent":["import type { LoadedCase } from \"../BenchMatrix.ts\";\n\n/** Module that exports case definitions */\nexport interface CasesModule<T = unknown> {\n cases: string[];\n defaultCases?: string[]; // subset for quick runs\n defaultVariants?: string[]; // subset for quick runs\n loadCase?: (id: string) => LoadedCase<T> | Promise<LoadedCase<T>>;\n}\n\n/** Load a cases module by URL */\nexport async function loadCasesModule<T = unknown>(\n moduleUrl: string,\n): Promise<CasesModule<T>> {\n const module = await import(moduleUrl);\n if (!Array.isArray(module.cases)) {\n throw new Error(`Cases module at ${moduleUrl} must export 'cases' array`);\n }\n return {\n cases: module.cases,\n defaultCases: module.defaultCases,\n defaultVariants: module.defaultVariants,\n loadCase: module.loadCase,\n };\n}\n\n/** Load case data from a CasesModule or pass through the caseId */\nexport async function loadCaseData<T>(\n casesModule: CasesModule<T> | undefined,\n caseId: string,\n): Promise<LoadedCase<T>> {\n if (casesModule?.loadCase) {\n return casesModule.loadCase(caseId);\n }\n return { data: caseId as T };\n}\n","import { type ChildProcess, fork } from \"node:child_process\";\nimport { existsSync } from \"node:fs\";\nimport path from \"node:path\";\nimport type { BenchmarkSpec } from \"../Benchmark.ts\";\nimport type { HeapProfile } from \"../heap-sample/HeapSampler.ts\";\nimport type { MeasuredResults } from \"../MeasuredResults.ts\";\nimport {\n type AdaptiveOptions,\n createAdaptiveWrapper,\n} from \"./AdaptiveWrapper.ts\";\nimport type { RunnerOptions } from \"./BenchRunner.ts\";\nimport { createRunner, type KnownRunner } from \"./CreateRunner.ts\";\nimport { aggregateGcStats, type GcEvent, parseGcLine } from \"./GcStats.ts\";\nimport { debugWorkerTiming, getElapsed, getPerfNow } from \"./TimingUtils.ts\";\nimport type {\n ErrorMessage,\n ResultMessage,\n RunMessage,\n} from \"./WorkerScript.ts\";\n\n/** Parameters for running a matrix variant in worker */\nexport interface RunMatrixVariantParams {\n variantDir: string;\n variantId: string;\n caseId: string;\n caseData?: unknown;\n casesModule?: string;\n runner: KnownRunner;\n options: RunnerOptions;\n}\n\ntype WorkerParams<T = unknown> = {\n spec: BenchmarkSpec<T>;\n runner: KnownRunner;\n options: RunnerOptions;\n params?: T;\n};\n\ntype WorkerHandlers = {\n resolve: (results: MeasuredResults[], heapProfile?: HeapProfile) => void;\n reject: (error: Error) => void;\n};\n\ninterface RunBenchmarkParams<T = unknown> {\n spec: BenchmarkSpec<T>;\n runner: KnownRunner;\n options: RunnerOptions;\n useWorker?: boolean;\n params?: T;\n}\n\nconst logTiming = debugWorkerTiming\n ? (message: string) => console.log(`[RunnerOrchestrator] ${message}`)\n : () => {};\n\n/** Execute benchmarks directly or in worker process */\nexport async function runBenchmark<T = unknown>({\n spec,\n runner,\n options,\n useWorker = false,\n params,\n}: RunBenchmarkParams<T>): Promise<MeasuredResults[]> {\n if (!useWorker) {\n const resolvedSpec = spec.modulePath\n ? await resolveModuleSpec(spec, params)\n : { spec, params };\n\n const base = await createRunner(runner);\n const benchRunner = (options as any).adaptive\n ? createAdaptiveWrapper(base, options as AdaptiveOptions)\n : base;\n return benchRunner.runBench(\n resolvedSpec.spec,\n options,\n resolvedSpec.params,\n );\n }\n\n return runInWorker({ spec, runner, options, params });\n}\n\n/** Run a matrix variant benchmark in isolated worker process */\nexport async function runMatrixVariant(\n params: RunMatrixVariantParams,\n): Promise<MeasuredResults[]> {\n const {\n variantDir,\n variantId,\n caseId,\n caseData,\n casesModule,\n runner,\n options,\n } = params;\n const name = `${variantId}/${caseId}`;\n const message: RunMessage = {\n type: \"run\",\n spec: { name, fn: () => {} },\n runnerName: runner,\n options,\n variantDir,\n variantId,\n caseId,\n caseData,\n casesModule,\n };\n return runWorkerWithMessage(name, options, message);\n}\n\n/** Resolve modulePath/exportName to a real function for non-worker mode */\nasync function resolveModuleSpec<T>(\n spec: BenchmarkSpec<T>,\n params: T | undefined,\n): Promise<{ spec: BenchmarkSpec<T>; params: T | undefined }> {\n const module = await import(spec.modulePath!);\n\n const fn = spec.exportName\n ? module[spec.exportName]\n : module.default || module;\n\n if (typeof fn !== \"function\") {\n const name = spec.exportName || \"default\";\n throw new Error(\n `Export '${name}' from ${spec.modulePath} is not a function`,\n );\n }\n\n let resolvedParams = params;\n if (spec.setupExportName) {\n const setupFn = module[spec.setupExportName];\n if (typeof setupFn !== \"function\") {\n const msg = `Setup export '${spec.setupExportName}' from ${spec.modulePath} is not a function`;\n throw new Error(msg);\n }\n resolvedParams = await setupFn(params);\n }\n\n return { spec: { ...spec, fn }, params: resolvedParams };\n}\n\n/** Run benchmark in isolated worker process */\nasync function runInWorker<T>(\n workerParams: WorkerParams<T>,\n): Promise<MeasuredResults[]> {\n const { spec, runner, options, params } = workerParams;\n const msg = createRunMessage(spec, runner, options, params);\n return runWorkerWithMessage(spec.name, options, msg);\n}\n\n/** Spawn worker, wire handlers, send message, return results */\nfunction runWorkerWithMessage(\n name: string,\n options: RunnerOptions,\n message: RunMessage,\n): Promise<MeasuredResults[]> {\n const startTime = getPerfNow();\n const collectGcStats = options.gcStats ?? false;\n logTiming(`Starting worker for ${name}`);\n\n return new Promise((resolve, reject) => {\n const { worker, createTime, gcEvents } =\n createWorkerWithTiming(collectGcStats);\n const handlers = createWorkerHandlers(\n name,\n startTime,\n gcEvents,\n resolve,\n reject,\n );\n setupWorkerHandlers(worker, name, handlers);\n sendWorkerMessage(worker, message, createTime);\n });\n}\n\n/** Create message for worker execution */\nfunction createRunMessage<T>(\n spec: BenchmarkSpec<T>,\n runnerName: KnownRunner,\n options: RunnerOptions,\n params?: T,\n): RunMessage {\n const { fn, ...rest } = spec;\n const message: RunMessage = {\n type: \"run\",\n spec: rest as BenchmarkSpec,\n runnerName,\n options,\n params,\n };\n if (spec.modulePath) {\n message.modulePath = spec.modulePath;\n message.exportName = spec.exportName;\n if (spec.setupExportName) message.setupExportName = spec.setupExportName;\n } else {\n message.fnCode = fn.toString();\n }\n return message;\n}\n\n/** Create worker process with timing logs */\nfunction createWorkerWithTiming(gcStats: boolean) {\n const workerStart = getPerfNow();\n const gcEvents: GcEvent[] = [];\n const worker = createWorkerProcess(gcStats);\n const createTime = getPerfNow();\n if (gcStats && worker.stdout) setupGcCapture(worker, gcEvents);\n logTiming(\n `Worker process created in ${getElapsed(workerStart, createTime).toFixed(1)}ms`,\n );\n return { worker, createTime, gcEvents };\n}\n\n// Consider: --no-compilation-cache, --max-old-space-size=512, --no-lazy\n// for consistency (less realistic)\n\n/** @return handlers that attach GC stats and heap profile to results */\nfunction createWorkerHandlers(\n specName: string,\n startTime: number,\n gcEvents: GcEvent[] | undefined,\n resolve: (results: MeasuredResults[]) => void,\n reject: (error: Error) => void,\n): WorkerHandlers {\n return {\n resolve: (results: MeasuredResults[], heapProfile?: HeapProfile) => {\n logTiming(\n `Total worker time for ${specName}: ${getElapsed(startTime).toFixed(1)}ms`,\n );\n if (gcEvents?.length) {\n const gcStats = aggregateGcStats(gcEvents);\n for (const r of results) r.gcStats = gcStats;\n }\n if (heapProfile) for (const r of results) r.heapProfile = heapProfile;\n resolve(results);\n },\n reject,\n };\n}\n\n/** Setup worker event handlers with cleanup */\nfunction setupWorkerHandlers(\n worker: ReturnType<typeof createWorkerProcess>,\n specName: string,\n handlers: WorkerHandlers,\n) {\n const { resolve, reject } = handlers;\n const cleanup = createCleanup(worker, specName, reject);\n worker.on(\n \"message\",\n createMessageHandler(specName, cleanup, resolve, reject),\n );\n worker.on(\"error\", createErrorHandler(specName, cleanup, reject));\n worker.on(\"exit\", createExitHandler(specName, cleanup, reject));\n}\n\n/** Send message to worker with timing log */\nfunction sendWorkerMessage(\n worker: ReturnType<typeof createWorkerProcess>,\n message: RunMessage,\n createTime: number,\n): void {\n const messageTime = getPerfNow();\n worker.send(message);\n logTiming(\n `Message sent to worker in ${getElapsed(createTime, messageTime).toFixed(1)}ms`,\n );\n}\n\n/** Create worker process with configuration */\nfunction createWorkerProcess(gcStats: boolean) {\n const workerPath = resolveWorkerPath();\n const execArgv = [\"--expose-gc\", \"--allow-natives-syntax\"];\n if (gcStats) execArgv.push(\"--trace-gc-nvp\");\n\n return fork(workerPath, [], {\n execArgv,\n silent: gcStats, // Capture stdout/stderr when collecting GC stats\n env: {\n ...process.env,\n NODE_OPTIONS: \"\",\n },\n });\n}\n\n/** Capture and parse GC lines from stdout (V8's --trace-gc-nvp outputs to stdout) */\nfunction setupGcCapture(worker: ChildProcess, gcEvents: GcEvent[]): void {\n let buffer = \"\";\n worker.stdout!.on(\"data\", (data: Buffer) => {\n buffer += data.toString();\n const lines = buffer.split(\"\\n\");\n buffer = lines.pop() || \"\"; // Keep incomplete line in buffer\n for (const line of lines) {\n const event = parseGcLine(line);\n if (event) {\n gcEvents.push(event);\n } else if (line.trim()) {\n // Forward non-GC stdout to console (worker status messages)\n process.stdout.write(line + \"\\n\");\n }\n }\n });\n}\n\n/** Create cleanup for timeout and termination */\nfunction createCleanup(\n worker: ReturnType<typeof createWorkerProcess>,\n specName: string,\n reject: (error: Error) => void,\n) {\n const timeoutId = setTimeout(() => {\n cleanup();\n reject(new Error(`Benchmark \"${specName}\" timed out after 60 seconds`));\n }, 60000);\n const cleanup = () => {\n clearTimeout(timeoutId);\n if (!worker.killed) worker.kill(\"SIGTERM\");\n };\n return cleanup;\n}\n\n/** Handle worker messages (results or errors) */\nfunction createMessageHandler(\n specName: string,\n cleanup: () => void,\n resolve: (results: MeasuredResults[], heapProfile?: HeapProfile) => void,\n reject: (error: Error) => void,\n) {\n return (msg: ResultMessage | ErrorMessage) => {\n cleanup();\n if (msg.type === \"result\") {\n resolve(msg.results, msg.heapProfile);\n } else if (msg.type === \"error\") {\n const error = new Error(`Benchmark \"${specName}\" failed: ${msg.error}`);\n if (msg.stack) error.stack = msg.stack;\n reject(error);\n }\n };\n}\n\n/** Handle worker process errors */\nfunction createErrorHandler(\n specName: string,\n cleanup: () => void,\n reject: (error: Error) => void,\n) {\n return (error: Error) => {\n cleanup();\n reject(\n new Error(\n `Worker process failed for benchmark \"${specName}\": ${error.message}`,\n ),\n );\n };\n}\n\n/** Handle worker process exit */\nfunction createExitHandler(\n specName: string,\n cleanup: () => void,\n reject: (error: Error) => void,\n) {\n return (code: number | null, _signal: NodeJS.Signals | null) => {\n if (code !== 0 && code !== null) {\n cleanup();\n const msg = `Worker exited with code ${code} for benchmark \"${specName}\"`;\n reject(new Error(msg));\n }\n };\n}\n\n/** Resolve WorkerScript path for dev (.ts) or dist (.mjs) */\nfunction resolveWorkerPath(): string {\n const dir = import.meta.dirname!;\n const tsPath = path.join(dir, \"WorkerScript.ts\");\n if (existsSync(tsPath)) return tsPath;\n return path.join(dir, \"runners\", \"WorkerScript.mjs\");\n}\n","import type { MeasuredResults } from \"./MeasuredResults.ts\";\nimport { loadCaseData, loadCasesModule } from \"./matrix/CaseLoader.ts\";\nimport { discoverVariants } from \"./matrix/VariantLoader.ts\";\nimport { BasicRunner } from \"./runners/BasicRunner.ts\";\nimport type { RunnerOptions } from \"./runners/BenchRunner.ts\";\nimport { runMatrixVariant } from \"./runners/RunnerOrchestrator.ts\";\nimport { average } from \"./StatisticalUtils.ts\";\n\n/** Stateless variant - called each iteration with case data */\nexport type VariantFn<T = unknown> = (caseData: T) => void;\n\n/** Stateful variant - setup once, run many */\nexport interface StatefulVariant<T = unknown, S = unknown> {\n setup: (caseData: T) => S | Promise<S>;\n run: (state: S) => void;\n}\n\n/** A variant is either a plain function or a stateful setup+run pair */\nexport type Variant<T = unknown, S = unknown> =\n | VariantFn<T>\n | StatefulVariant<T, S>;\n\n/** Variant with any state type - used in BenchMatrix to allow mixed variants */\nexport type AnyVariant<T = unknown> = VariantFn<T> | StatefulVariant<T, any>;\n\n/** Result from casesModule.loadCase() */\nexport interface LoadedCase<T = unknown> {\n data: T;\n metadata?: Record<string, unknown>;\n}\n\nexport interface MatrixDefaults {\n warmup?: number;\n maxTime?: number;\n iterations?: number;\n}\n\n/** Bench matrix configuration */\nexport interface BenchMatrix<T = unknown> {\n name: string;\n variantDir?: string;\n variants?: Record<string, AnyVariant<T>>;\n cases?: string[];\n casesModule?: string;\n baselineDir?: string;\n baselineVariant?: string;\n defaults?: MatrixDefaults;\n}\n\n/** Collection of matrices */\nexport interface MatrixSuite {\n name: string;\n matrices: BenchMatrix<any>[];\n}\n\n/** Results for a single variant across all cases */\nexport interface VariantResult {\n id: string;\n cases: CaseResult[];\n}\n\n/** Results for a single (variant, case) pair */\nexport interface CaseResult {\n caseId: string;\n measured: MeasuredResults;\n metadata?: Record<string, unknown>;\n baseline?: MeasuredResults;\n deltaPercent?: number;\n}\n\n/** Results from running a matrix */\nexport interface MatrixResults {\n name: string;\n variants: VariantResult[];\n}\n\n/** Options for runMatrix */\nexport interface RunMatrixOptions {\n iterations?: number;\n maxTime?: number;\n warmup?: number;\n useWorker?: boolean; // use worker process isolation (default: true for variantDir)\n filteredCases?: string[]; // run only these cases (from filter)\n filteredVariants?: string[]; // run only these variants (from filter)\n // Runner options passthrough\n collect?: boolean;\n cpuCounters?: boolean;\n traceOpt?: boolean;\n noSettle?: boolean;\n pauseFirst?: number;\n pauseInterval?: number;\n pauseDuration?: number;\n gcStats?: boolean;\n heapSample?: boolean;\n heapInterval?: number;\n heapDepth?: number;\n}\n\n/** Context for running matrix benchmarks in worker mode */\ninterface DirMatrixContext<T> {\n matrix: BenchMatrix<T>;\n casesModule?: import(\"./matrix/CaseLoader.ts\").CasesModule<T>;\n baselineIds: string[];\n caseIds: string[];\n runnerOpts: RunnerOptions;\n}\n\n/** @return true if variant is a StatefulVariant (has setup + run) */\nexport function isStatefulVariant<T, S>(\n v: Variant<T, S>,\n): v is StatefulVariant<T, S> {\n return typeof v === \"object\" && \"setup\" in v && \"run\" in v;\n}\n\n/** Run a BenchMatrix with inline variants or variantDir */\nexport async function runMatrix<T>(\n matrix: BenchMatrix<T>,\n options: RunMatrixOptions = {},\n): Promise<MatrixResults> {\n validateBaseline(matrix);\n const effectiveOptions = { ...matrix.defaults, ...options };\n\n if (matrix.variantDir) {\n return runMatrixWithDir(matrix, effectiveOptions);\n }\n if (matrix.variants) {\n return runMatrixInline(matrix, effectiveOptions);\n }\n throw new Error(\"BenchMatrix requires either 'variants' or 'variantDir'\");\n}\n\n/** @throws if both baselineDir and baselineVariant are set */\nfunction validateBaseline<T>(matrix: BenchMatrix<T>): void {\n const msg =\n \"BenchMatrix cannot have both 'baselineDir' and 'baselineVariant'\";\n if (matrix.baselineDir && matrix.baselineVariant) throw new Error(msg);\n}\n\n/** Run matrix with variantDir (worker mode for memory isolation) */\nasync function runMatrixWithDir<T>(\n matrix: BenchMatrix<T>,\n options: RunMatrixOptions,\n): Promise<MatrixResults> {\n const allVariantIds = await discoverVariants(matrix.variantDir!);\n if (allVariantIds.length === 0) {\n throw new Error(`No variants found in ${matrix.variantDir}`);\n }\n const variantIds = options.filteredVariants ?? allVariantIds;\n\n const ctx = await createDirContext(matrix, options);\n const variants = await runDirVariants(variantIds, ctx);\n\n if (matrix.baselineVariant) {\n applyBaselineVariant(variants, matrix.baselineVariant);\n }\n return { name: matrix.name, variants };\n}\n\n/** Run matrix with inline variants (non-worker mode) */\nasync function runMatrixInline<T>(\n matrix: BenchMatrix<T>,\n options: RunMatrixOptions,\n): Promise<MatrixResults> {\n // baselineDir is only valid with variantDir\n const msg =\n \"BenchMatrix with inline 'variants' cannot use 'baselineDir'. Use 'variantDir' instead.\";\n if (matrix.baselineDir) throw new Error(msg);\n\n const { casesModule, caseIds } = await resolveCases(matrix, options);\n const runner = new BasicRunner();\n const runnerOpts = buildRunnerOptions(options);\n\n const variantEntries = options.filteredVariants\n ? Object.entries(matrix.variants!).filter(([id]) =>\n options.filteredVariants!.includes(id),\n )\n : Object.entries(matrix.variants!);\n\n const variants: VariantResult[] = [];\n for (const [variantId, variant] of variantEntries) {\n const cases: CaseResult[] = [];\n for (const caseId of caseIds) {\n const loaded = await loadCaseData(casesModule, caseId);\n const caseData =\n casesModule || matrix.cases ? loaded.data : (undefined as T);\n const measured = await runVariant(\n variant,\n caseData,\n variantId,\n runner,\n runnerOpts,\n );\n cases.push({ caseId, measured, metadata: loaded.metadata });\n }\n variants.push({ id: variantId, cases });\n }\n\n if (matrix.baselineVariant) {\n applyBaselineVariant(variants, matrix.baselineVariant);\n }\n\n return { name: matrix.name, variants };\n}\n\n/** Create context for directory-based matrix execution */\nasync function createDirContext<T>(\n matrix: BenchMatrix<T>,\n options: RunMatrixOptions,\n): Promise<DirMatrixContext<T>> {\n const baselineIds = matrix.baselineDir\n ? await discoverVariants(matrix.baselineDir)\n : [];\n const { casesModule, caseIds } = await resolveCases(matrix, options);\n const runnerOpts = buildRunnerOptions(options);\n return { matrix, casesModule, baselineIds, caseIds, runnerOpts };\n}\n\n/** Run all variants using worker processes */\nasync function runDirVariants<T>(\n variantIds: string[],\n ctx: DirMatrixContext<T>,\n): Promise<VariantResult[]> {\n const variants: VariantResult[] = [];\n for (const variantId of variantIds) {\n const cases = await runDirVariantCases(variantId, ctx);\n variants.push({ id: variantId, cases });\n }\n return variants;\n}\n\n/** Apply baselineVariant comparison - one variant is the reference for all others */\nfunction applyBaselineVariant(\n variants: VariantResult[],\n baselineVariantId: string,\n): void {\n const baselineVariant = variants.find(v => v.id === baselineVariantId);\n if (!baselineVariant) return;\n\n const baselineByCase = new Map<string, MeasuredResults>();\n for (const c of baselineVariant.cases) {\n baselineByCase.set(c.caseId, c.measured);\n }\n\n for (const variant of variants) {\n if (variant.id === baselineVariantId) continue;\n for (const caseResult of variant.cases) {\n const baseline = baselineByCase.get(caseResult.caseId);\n if (baseline) {\n caseResult.baseline = baseline;\n caseResult.deltaPercent = computeDeltaPercent(\n baseline,\n caseResult.measured,\n );\n }\n }\n }\n}\n\n/** Load cases module and resolve filtered case IDs */\nasync function resolveCases<T>(\n matrix: BenchMatrix<T>,\n options: RunMatrixOptions,\n) {\n const casesModule = matrix.casesModule\n ? await loadCasesModule<T>(matrix.casesModule)\n : undefined;\n const allCaseIds = casesModule?.cases ?? matrix.cases ?? [\"default\"];\n const caseIds = options.filteredCases ?? allCaseIds;\n return { casesModule, caseIds };\n}\n\nfunction buildRunnerOptions(options: RunMatrixOptions): RunnerOptions {\n return {\n maxIterations: options.iterations,\n maxTime: options.maxTime ?? 1000,\n warmup: options.warmup ?? 0,\n collect: options.collect,\n cpuCounters: options.cpuCounters,\n traceOpt: options.traceOpt,\n noSettle: options.noSettle,\n pauseFirst: options.pauseFirst,\n pauseInterval: options.pauseInterval,\n pauseDuration: options.pauseDuration,\n gcStats: options.gcStats,\n heapSample: options.heapSample,\n heapInterval: options.heapInterval,\n heapDepth: options.heapDepth,\n };\n}\n\n/** Run a single variant with case data */\nasync function runVariant<T>(\n variant: AnyVariant<T>,\n caseData: T,\n name: string,\n runner: BasicRunner,\n options: RunnerOptions,\n): Promise<MeasuredResults> {\n if (isStatefulVariant(variant)) {\n const state = await variant.setup(caseData);\n const [result] = await runner.runBench(\n { name, fn: () => variant.run(state) },\n options,\n );\n return result;\n }\n const [result] = await runner.runBench(\n { name, fn: () => variant(caseData) },\n options,\n );\n return result;\n}\n\n/** Run all cases for a single variant */\nasync function runDirVariantCases<T>(\n variantId: string,\n ctx: DirMatrixContext<T>,\n): Promise<CaseResult[]> {\n const { matrix, casesModule, caseIds, runnerOpts } = ctx;\n const cases: CaseResult[] = [];\n\n for (const caseId of caseIds) {\n const caseData = !matrix.casesModule && matrix.cases ? caseId : undefined;\n const [measured] = await runMatrixVariant({\n variantDir: matrix.variantDir!,\n variantId,\n caseId,\n caseData,\n casesModule: matrix.casesModule,\n runner: \"basic\",\n options: runnerOpts,\n });\n\n const loaded = await loadCaseData(casesModule, caseId);\n const baseline = await runBaselineIfExists(\n variantId,\n caseId,\n caseData,\n ctx,\n );\n const deltaPercent = baseline\n ? computeDeltaPercent(baseline, measured)\n : undefined;\n const metadata = loaded.metadata;\n cases.push({ caseId, measured, metadata, baseline, deltaPercent });\n }\n return cases;\n}\n\n/** Compute delta percentage: (current - baseline) / baseline * 100 */\nfunction computeDeltaPercent(\n baseline: MeasuredResults,\n current: MeasuredResults,\n): number {\n const baseAvg = average(baseline.samples);\n if (baseAvg === 0) return 0;\n return ((average(current.samples) - baseAvg) / baseAvg) * 100;\n}\n\n/** Run baseline variant if it exists in baselineDir */\nasync function runBaselineIfExists<T>(\n variantId: string,\n caseId: string,\n caseData: unknown,\n ctx: DirMatrixContext<T>,\n): Promise<MeasuredResults | undefined> {\n const { matrix, baselineIds, runnerOpts } = ctx;\n if (!matrix.baselineDir || !baselineIds.includes(variantId)) return undefined;\n\n const [measured] = await runMatrixVariant({\n variantDir: matrix.baselineDir,\n variantId,\n caseId,\n caseData,\n casesModule: matrix.casesModule,\n runner: \"basic\",\n options: runnerOpts,\n });\n return measured;\n}\n","import pico from \"picocolors\";\nimport type { CIDirection, DifferenceCI } from \"../StatisticalUtils.ts\";\n\nconst isTest = process.env.NODE_ENV === \"test\" || process.env.VITEST === \"true\";\nconst { red, green } = isTest\n ? { red: (str: string) => str, green: (str: string) => str }\n : pico;\n\n/** Format floats with custom precision */\nexport function floatPrecision(precision: number) {\n return (x: unknown): string | null => {\n if (typeof x !== \"number\") return null;\n return x.toFixed(precision).replace(/\\.?0+$/, \"\");\n };\n}\n\n/** Format percentages with custom precision */\nexport function percentPrecision(precision: number) {\n return (x: unknown): string | null => {\n if (typeof x !== \"number\") return null;\n return percent(x, precision);\n };\n}\n\n/** Format duration in milliseconds with appropriate units */\nexport function duration(ms: unknown): string | null {\n if (typeof ms !== \"number\") return null;\n if (ms < 0.001) return `${(ms * 1000000).toFixed(0)}ns`;\n if (ms < 1) return `${(ms * 1000).toFixed(1)}μs`;\n if (ms < 1000) return `${ms.toFixed(2)}ms`;\n return `${(ms / 1000).toFixed(2)}s`;\n}\n\n/** Format time in milliseconds, showing very small values with units */\nexport function timeMs(ms: unknown): string | null {\n if (typeof ms !== \"number\") return null;\n if (ms < 0.001) return `${(ms * 1000000).toFixed(0)}ns`;\n if (ms < 0.01) return `${(ms * 1000).toFixed(1)}μs`;\n if (ms >= 10) return ms.toFixed(0);\n return ms.toFixed(2);\n}\n\n/** Format as rate (value per unit) */\nexport function rate(unit: string): (value: unknown) => string | null {\n return (value: unknown) => {\n if (typeof value !== \"number\") return null;\n return `${integer(value)}/${unit}`;\n };\n}\n\n/** Format integer with thousand separators */\nexport function integer(x: unknown): string | null {\n if (typeof x !== \"number\") return null;\n return new Intl.NumberFormat(\"en-US\").format(Math.round(x));\n}\n\n/** Format fraction as percentage (0.473 → 47.3%) */\nexport function percent(fraction: unknown, precision = 1): string | null {\n if (typeof fraction !== \"number\") return null;\n return `${Math.abs(fraction * 100).toFixed(precision)}%`;\n}\n\n/** Format percentage difference between two values */\nexport function diffPercent(main: unknown, base: unknown): string {\n if (typeof main !== \"number\" || typeof base !== \"number\") return \" \";\n const diff = main - base;\n return coloredPercent(diff, base);\n}\n\n/** Format percentage difference for benchmarks (lower is better) */\nexport function diffPercentBenchmark(main: unknown, base: unknown): string {\n if (typeof main !== \"number\" || typeof base !== \"number\") return \" \";\n const diff = main - base;\n return coloredPercent(diff, base, false); // negative is good for benchmarks\n}\n\n/** Format memory size in KB with appropriate units */\nexport function memoryKB(kb: unknown): string | null {\n if (typeof kb !== \"number\") return null;\n if (kb < 1024) return `${kb.toFixed(0)}KB`;\n return `${(kb / 1024).toFixed(1)}MB`;\n}\n\n/** Format bytes with appropriate units (B, KB, MB, GB).\n * Use `space: true` for human-readable console output (`1.5 KB`). */\nexport function formatBytes(\n bytes: unknown,\n opts?: { space?: boolean },\n): string | null {\n if (typeof bytes !== \"number\") return null;\n const s = opts?.space ? \" \" : \"\";\n if (bytes < 1024) return `${bytes.toFixed(0)}${s}B`;\n if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)}${s}KB`;\n if (bytes < 1024 * 1024 * 1024)\n return `${(bytes / 1024 / 1024).toFixed(1)}${s}MB`;\n return `${(bytes / 1024 / 1024 / 1024).toFixed(1)}${s}GB`;\n}\n\n/** Format percentage difference with confidence interval */\nexport function formatDiffWithCI(value: unknown): string | null {\n if (!isDifferenceCI(value)) return null;\n const { percent, ci, direction } = value;\n return colorByDirection(diffCIText(percent, ci), direction);\n}\n\n/** Format percentage difference with CI for throughput metrics (higher is better) */\nexport function formatDiffWithCIHigherIsBetter(value: unknown): string | null {\n if (!isDifferenceCI(value)) return null;\n const { percent, ci, direction } = value;\n // Flip percent sign for \"higher is better\" metrics (direction stays same)\n return colorByDirection(diffCIText(-percent, [-ci[1], -ci[0]]), direction);\n}\n\n/** @return truncated string with ellipsis if over maxLen */\nexport function truncate(str: string, maxLen = 30): string {\n return str.length > maxLen ? str.slice(0, maxLen - 3) + \"...\" : str;\n}\n\n/** Format fraction as colored +/- percentage */\nfunction coloredPercent(\n numerator: number,\n denominator: number,\n positiveIsGreen = true,\n): string {\n const fraction = numerator / denominator;\n if (Number.isNaN(fraction) || !Number.isFinite(fraction)) {\n return \" \";\n }\n const positive = fraction >= 0;\n const sign = positive ? \"+\" : \"-\";\n const percentStr = `${sign}${percent(fraction)}`;\n const isGood = positive === positiveIsGreen;\n return isGood ? green(percentStr) : red(percentStr);\n}\n\n/** @return true if value is a DifferenceCI object */\nfunction isDifferenceCI(x: unknown): x is DifferenceCI {\n return typeof x === \"object\" && x !== null && \"ci\" in x && \"direction\" in x;\n}\n\n/** @return text colored green for faster, red for slower */\nfunction colorByDirection(text: string, direction: CIDirection): string {\n if (direction === \"faster\") return green(text);\n if (direction === \"slower\") return red(text);\n return text;\n}\n\n/** @return formatted \"pct [lo, hi]\" text for a diff with CI */\nfunction diffCIText(pct: number, ci: [number, number]): string {\n return `${formatBound(pct)} [${formatBound(ci[0])}, ${formatBound(ci[1])}]`;\n}\n\n/** @return signed percentage string (e.g. \"+1.2%\", \"-3.4%\") */\nfunction formatBound(v: number): string {\n const sign = v >= 0 ? \"+\" : \"\";\n return `${sign}${v.toFixed(1)}%`;\n}\n","import pico from \"picocolors\";\nimport type { Alignment, SpanningCellConfig, TableUserConfig } from \"table\";\nimport { table } from \"table\";\nimport { diffPercent } from \"./Formatters.ts\";\n\n/** Related table columns */\nexport interface ColumnGroup<T> {\n groupTitle?: string;\n columns: AnyColumn<T>[];\n}\n\nexport type AnyColumn<T> = Column<T> | DiffColumn<T>;\n\n/** Column with optional formatter */\nexport interface Column<T> extends ColumnFormat<T> {\n formatter?: (value: unknown) => string | null;\n diffKey?: undefined;\n}\n\n/** Table headers and configuration */\nexport interface TableSetup {\n headerRows: string[][];\n config: TableUserConfig;\n}\n\n/** Data rows with optional baseline */\nexport interface ResultGroup<T extends Record<string, any>> {\n results: T[];\n\n baseline?: T;\n}\n\n/** Comparison column against baseline */\ninterface DiffColumn<T> extends ColumnFormat<T> {\n diffFormatter?: (value: unknown, baseline: unknown) => string | null;\n formatter?: undefined;\n\n /** Key for comparison value against baseline */\n diffKey: keyof T;\n}\n\ninterface ColumnFormat<T> {\n key: keyof T;\n title: string;\n\n alignment?: Alignment;\n\n width?: number;\n}\n\ninterface Lines {\n drawHorizontalLine: (index: number, size: number) => boolean;\n drawVerticalLine: (index: number, size: number) => boolean;\n}\n\nconst isTest = process.env.NODE_ENV === \"test\" || process.env.VITEST === \"true\";\nconst { bold } = isTest ? { bold: (str: string) => str } : pico;\n\n// Regex to strip ANSI escape codes (ESC [ ... m sequences)\nconst ansiEscapeRegex = new RegExp(\n String.fromCharCode(27) + \"\\\\[[0-9;]*m\",\n \"g\",\n);\n\n/** Build formatted table with column groups and baselines */\nexport function buildTable<T extends Record<string, any>>(\n columnGroups: ColumnGroup<T>[],\n resultGroups: ResultGroup<T>[],\n nameKey: keyof T = \"name\" as keyof T,\n): string {\n const allRecords = flattenGroups(columnGroups, resultGroups, nameKey);\n return createTable(columnGroups, allRecords);\n}\n\n/** Convert records to string arrays for table */\nexport function toRows<T extends Record<string, any>>(\n records: T[],\n groups: ColumnGroup<T>[],\n): string[][] {\n const allColumns = groups.flatMap(group => group.columns);\n\n const rawRows = records.map(record =>\n allColumns.map(col => {\n const value = record[col.key];\n return col.formatter ? col.formatter(value) : value;\n }),\n );\n\n return rawRows.map(row => row.map(cell => cell ?? \" \"));\n}\n\n/** Flatten groups with spacing */\nfunction flattenGroups<T extends Record<string, any>>(\n columnGroups: ColumnGroup<T>[],\n resultGroups: ResultGroup<T>[],\n nameKey: keyof T,\n): T[] {\n return resultGroups.flatMap((group, i) => {\n const groupRecords = addBaseline(columnGroups, group, nameKey);\n\n const isLast = i === resultGroups.length - 1;\n return isLast ? groupRecords : [...groupRecords, {} as T];\n });\n}\n\n/** Convert columns and records to formatted table */\nfunction createTable<T extends Record<string, any>>(\n groups: ColumnGroup<T>[],\n records: T[],\n): string {\n const dataRows = toRows(records, groups);\n const { headerRows, config } = setup(groups, dataRows);\n const allRows = [...headerRows, ...dataRows];\n return table(allRows, config);\n}\n\n/** Process results with baseline comparisons */\nfunction addBaseline<T extends Record<string, any>>(\n columnGroups: ColumnGroup<T>[],\n group: ResultGroup<T>,\n nameKey: keyof T,\n): T[] {\n const { results, baseline } = group;\n\n if (!baseline) return results;\n\n const diffResults = results.map(result =>\n addComparisons(columnGroups, result, baseline),\n );\n\n const markedBaseline = {\n ...baseline,\n [nameKey]: `--> ${baseline[nameKey]}`,\n };\n\n return [...diffResults, markedBaseline];\n}\n\n/** Create headers and table configuration */\nfunction setup<T>(groups: ColumnGroup<T>[], dataRows: string[][]): TableSetup {\n const titles = getTitles(groups);\n const numColumns = titles.length;\n\n const sectionRows = createGroupHeaders(groups, numColumns);\n const headerRows = [...sectionRows, titles];\n const spanningCells = createSectionSpans(groups);\n const columnWidths = calcColumnWidths(groups, titles, dataRows);\n const config: TableUserConfig = {\n spanningCells,\n columns: columnWidths,\n ...createLines(groups),\n };\n\n return { headerRows, config };\n}\n\n/** Add comparison values for diff columns */\nfunction addComparisons<T extends Record<string, any>>(\n groups: ColumnGroup<T>[],\n mainRecord: T,\n baselineRecord: T,\n): T {\n const diffColumns = groups.flatMap(g => g.columns).filter(col => col.diffKey);\n const updatedMain = { ...mainRecord };\n\n for (const col of diffColumns) {\n const dcol = col as DiffColumn<T>;\n const diffKey = dcol.diffKey;\n const mainValue = mainRecord[diffKey];\n const baselineValue = baselineRecord[diffKey];\n const diffFormat = dcol.diffFormatter ?? diffPercent;\n const diffStr = diffFormat(mainValue, baselineValue);\n (updatedMain as any)[col.key] = diffStr;\n }\n\n return updatedMain;\n}\n\n/** @return bolded column title strings */\nfunction getTitles<T>(groups: ColumnGroup<T>[]): string[] {\n return groups.flatMap(g => g.columns.map(c => bold(c.title || \" \")));\n}\n\n/** Create header rows with group titles */\nfunction createGroupHeaders<T>(\n groups: ColumnGroup<T>[],\n numColumns: number,\n): string[][] {\n if (!groups.some(g => g.groupTitle)) return [];\n\n const sectionRow = groups.flatMap(g => {\n const title = g.groupTitle ? [bold(g.groupTitle)] : [];\n return padWithBlanks(title, g.columns.length);\n });\n const blankRow = padWithBlanks([], numColumns);\n return [sectionRow, blankRow];\n}\n\n/** @return spanning cell configs for group title headers */\nfunction createSectionSpans<T>(groups: ColumnGroup<T>[]): SpanningCellConfig[] {\n let col = 0;\n const alignment: Alignment = \"center\";\n return groups.map(g => {\n const colSpan = g.columns.length;\n const span = { row: 0, col, colSpan, alignment };\n col += colSpan;\n return span;\n });\n}\n\n/** Calculate column widths based on content, including group titles */\nfunction calcColumnWidths<T>(\n groups: ColumnGroup<T>[],\n titles: string[],\n dataRows: unknown[][],\n): Record<number, { width: number; wrapWord: boolean }> {\n // First pass: calculate base widths from titles and data\n const widths: number[] = [];\n for (let i = 0; i < titles.length; i++) {\n const titleW = cellWidth(titles[i]);\n const maxDataW = dataRows.reduce(\n (max, row) => Math.max(max, cellWidth(row[i])),\n 0,\n );\n widths.push(Math.max(titleW, maxDataW));\n }\n\n // Second pass: ensure group titles fit (accounting for column separators)\n let colIndex = 0;\n for (const group of groups) {\n const groupW = cellWidth(group.groupTitle);\n if (groupW > 0) {\n const numCols = group.columns.length;\n const separatorWidth = (numCols - 1) * 3; // \" | \" between columns\n const currentWidth = widths\n .slice(colIndex, colIndex + numCols)\n .reduce((a, b) => a + b, 0);\n const needed = groupW - currentWidth - separatorWidth;\n if (needed > 0) {\n // Distribute extra width to last column in group\n widths[colIndex + numCols - 1] += needed;\n }\n }\n colIndex += group.columns.length;\n }\n\n // Convert to table config format\n return Object.fromEntries(\n widths.map((w, i) => [i, { width: w, wrapWord: false }]),\n );\n}\n\n/** @return draw functions for horizontal/vertical table borders */\nfunction createLines<T>(groups: ColumnGroup<T>[]): Lines {\n const { sectionBorders, headerBottom } = calcBorders(groups);\n\n function drawVerticalLine(index: number, size: number): boolean {\n return index === 0 || index === size || sectionBorders.includes(index);\n }\n function drawHorizontalLine(index: number, size: number): boolean {\n return index === 0 || index === size || index === headerBottom;\n }\n return { drawHorizontalLine, drawVerticalLine };\n}\n\n/** @return array padded with blank strings to the given length */\nfunction padWithBlanks(arr: string[], length: number): string[] {\n if (arr.length >= length) return arr;\n return [...arr, ...Array(length - arr.length).fill(\" \")];\n}\n\n/** Get visible length of a cell value (strips ANSI escape codes) */\nfunction cellWidth(value: unknown): number {\n if (value == null) return 0;\n const str = String(value);\n return str.replace(ansiEscapeRegex, \"\").length;\n}\n\n/** Calculate vertical lines between sections and header bottom position */\nfunction calcBorders<T>(groups: ColumnGroup<T>[]): {\n sectionBorders: number[];\n headerBottom: number;\n} {\n if (groups.length === 0) return { sectionBorders: [], headerBottom: 1 };\n\n const sectionBorders: number[] = [];\n let border = 0;\n for (const g of groups) {\n border += g.columns.length;\n sectionBorders.push(border);\n }\n return { sectionBorders, headerBottom: 3 };\n}\n","import type { MeasuredResults } from \"./MeasuredResults.ts\";\nimport { bootstrapDifferenceCI } from \"./StatisticalUtils.ts\";\nimport type { UnionToIntersection } from \"./TypeUtil.ts\";\nimport {\n formatDiffWithCI,\n formatDiffWithCIHigherIsBetter,\n truncate,\n} from \"./table-util/Formatters.ts\";\nimport {\n type AnyColumn,\n buildTable,\n type ColumnGroup,\n type ResultGroup,\n} from \"./table-util/TableReport.ts\";\n\n/** Benchmark results with optional baseline for comparison */\nexport interface ReportGroup {\n name: string;\n reports: BenchmarkReport[];\n baseline?: BenchmarkReport;\n}\n\n/** Results from a single benchmark run */\nexport interface BenchmarkReport {\n name: string;\n measuredResults: MeasuredResults;\n metadata?: UnknownRecord;\n}\n\nexport interface ReportColumnGroup<T> {\n groupTitle?: string;\n columns: ReportColumn<T>[];\n}\n\nexport type ReportColumn<T> = AnyColumn<T> & {\n /** Add diff column after this column when baseline exists */\n comparable?: boolean;\n /** Set true for throughput metrics where higher values are better (e.g., lines/sec) */\n higherIsBetter?: boolean;\n};\n\n/** Maps benchmark results to table columns */\nexport interface ResultsMapper<\n T extends Record<string, any> = Record<string, any>,\n> {\n extract(results: MeasuredResults, metadata?: UnknownRecord): T;\n columns(): ReportColumnGroup<T>[];\n}\nexport type UnknownRecord = Record<string, unknown>;\n\ntype SectionStats<S> = S extends ResultsMapper<infer T> ? T : never;\n\ninterface ReportRowBase {\n name: string;\n}\n\n/** Row data combining all section statistics */\ntype ReportRowData<S extends ReadonlyArray<ResultsMapper<any>>> =\n ReportRowBase & UnionToIntersection<SectionStats<S[number]>>;\n\n/** All reports in a group, including the baseline if present */\nexport function groupReports(group: ReportGroup): BenchmarkReport[] {\n return group.baseline ? [...group.reports, group.baseline] : group.reports;\n}\n\n/** @return formatted table report with optional baseline comparisons */\nexport function reportResults<S extends ReadonlyArray<ResultsMapper<any>>>(\n groups: ReportGroup[],\n sections: S,\n): string {\n const results = groups.map(group => resultGroupValues(group, sections));\n const hasBaseline = results.some(g => g.baseline);\n return buildTable(createColumnGroups(sections, hasBaseline), results);\n}\n\n/** @return rows with stats from sections */\nexport function valuesForReports<S extends ReadonlyArray<ResultsMapper<any>>>(\n reports: BenchmarkReport[],\n sections: S,\n): ReportRowData<S>[] {\n return reports.map(report => ({\n name: truncate(report.name),\n ...extractReportValues(report, sections),\n })) as ReportRowData<S>[];\n}\n\n/** @return groups with single CI column after first comparable field */\nexport function injectDiffColumns<T>(\n reportGroups: ReportColumnGroup<T>[],\n): ColumnGroup<T>[] {\n let ciAdded = false;\n\n return reportGroups.map(group => ({\n groupTitle: group.groupTitle,\n columns: group.columns.flatMap(col => {\n if (col.comparable && !ciAdded) {\n ciAdded = true;\n const fmt = col.higherIsBetter\n ? formatDiffWithCIHigherIsBetter\n : formatDiffWithCI;\n return [\n col,\n { title: \"Δ% CI\", key: \"diffCI\" as keyof T, formatter: fmt },\n ];\n }\n return [col];\n }),\n }));\n}\n\n/** @return values for report group */\nfunction resultGroupValues<S extends ReadonlyArray<ResultsMapper<any>>>(\n group: ReportGroup,\n sections: S,\n): ResultGroup<ReportRowData<S>> {\n const { reports, baseline } = group;\n const baselineSamples = baseline?.measuredResults.samples;\n\n const results = reports.map(report => {\n const row = {\n name: truncate(report.name),\n ...extractReportValues(report, sections),\n } as ReportRowData<S>;\n\n if (baselineSamples && report.measuredResults.samples) {\n (row as any).diffCI = bootstrapDifferenceCI(\n baselineSamples,\n report.measuredResults.samples,\n );\n }\n return row;\n });\n\n const baselineRow = baseline && valuesForReports([baseline], sections)[0];\n return { results, baseline: baselineRow };\n}\n\n/** @return column groups with diff columns if baseline exists */\nfunction createColumnGroups<S extends ReadonlyArray<ResultsMapper<any>>>(\n sections: S,\n hasBaseline: boolean,\n): ColumnGroup<ReportRowData<S>>[] {\n const nameColumn: ColumnGroup<ReportRowData<S>> = {\n columns: [{ key: \"name\" as keyof ReportRowData<S>, title: \"name\" }],\n };\n\n const groups = sections.flatMap(section => section.columns());\n return [nameColumn, ...(hasBaseline ? injectDiffColumns(groups) : groups)];\n}\n\n/** @return merged statistics from all sections */\nfunction extractReportValues(\n report: BenchmarkReport,\n sections: ReadonlyArray<ResultsMapper<any>>,\n): UnknownRecord {\n const { measuredResults, metadata } = report;\n const entries = sections.flatMap(s =>\n Object.entries(s.extract(measuredResults, metadata)),\n );\n return Object.fromEntries(entries);\n}\n","import type { Argv, InferredOptionTypes } from \"yargs\";\nimport yargs from \"yargs\";\n\nexport type Configure<T> = (yargs: Argv) => Argv<T>;\n\n/** CLI args type inferred from cliOptions, plus optional file positional */\nexport type DefaultCliArgs = InferredOptionTypes<typeof cliOptions> & {\n file?: string;\n};\n\nexport const defaultAdaptiveMaxTime = 20;\n\n// biome-ignore format: compact option definitions\nconst cliOptions = {\n time: { type: \"number\", default: 0.642, requiresArg: true, describe: \"test duration in seconds\" },\n cpu: { type: \"boolean\", default: false, describe: \"CPU counter measurements (requires root)\" },\n collect: { type: \"boolean\", default: false, describe: \"force GC after each iteration\" },\n \"gc-stats\": { type: \"boolean\", default: false, describe: \"collect GC statistics (Node: --trace-gc-nvp, browser: CDP tracing)\" },\n profile: { type: \"boolean\", default: false, describe: \"run once for profiling\" },\n filter: { type: \"string\", requiresArg: true, describe: \"filter benchmarks by regex or substring\" },\n all: { type: \"boolean\", default: false, describe: \"run all cases (ignore defaultCases)\" },\n worker: { type: \"boolean\", default: true, describe: \"run in worker process for isolation (default: true)\" },\n adaptive: { type: \"boolean\", default: false, describe: \"adaptive sampling (experimental)\" },\n \"min-time\": { type: \"number\", default: 1, describe: \"minimum time before adaptive convergence can stop\" },\n convergence: { type: \"number\", default: 95, describe: \"adaptive confidence threshold (0-100)\" },\n warmup: { type: \"number\", default: 0, describe: \"warmup iterations before measurement\" },\n html: { type: \"boolean\", default: false, describe: \"generate HTML report and open in browser\" },\n \"export-html\": { type: \"string\", requiresArg: true, describe: \"export HTML report to specified file\" },\n json: { type: \"string\", requiresArg: true, describe: \"export benchmark data to JSON file\" },\n \"export-perfetto\": { type: \"string\", requiresArg: true, describe: \"export Perfetto trace file (view at ui.perfetto.dev)\" },\n speedscope: { type: \"boolean\", default: false, describe: \"open heap profile in speedscope (via npx)\" },\n \"export-speedscope\": { type: \"string\", requiresArg: true, describe: \"export heap profile as speedscope JSON\" },\n \"trace-opt\": { type: \"boolean\", default: false, describe: \"trace V8 optimization tiers (requires --allow-natives-syntax)\" },\n \"skip-settle\": { type: \"boolean\", default: false, describe: \"skip post-warmup settle time (see V8 optimization cold start)\" },\n \"pause-first\": { type: \"number\", describe: \"iterations before first pause (then pause-interval applies)\" },\n \"pause-interval\": { type: \"number\", default: 0, describe: \"iterations between pauses for V8 optimization (0 to disable)\" },\n \"pause-duration\": { type: \"number\", default: 100, describe: \"pause duration in ms for V8 optimization\" },\n batches: { type: \"number\", default: 1, describe: \"divide time into N batches, alternating baseline/current order\" },\n iterations: { type: \"number\", requiresArg: true, describe: \"exact number of iterations (overrides --time)\" },\n \"heap-sample\": { type: \"boolean\", default: false, describe: \"heap sampling allocation attribution (includes garbage)\" },\n \"heap-interval\": { type: \"number\", default: 32768, describe: \"heap sampling interval in bytes\" },\n \"heap-depth\": { type: \"number\", default: 64, describe: \"heap sampling stack depth\" },\n \"heap-rows\": { type: \"number\", default: 20, describe: \"top allocation sites to show\" },\n \"heap-stack\": { type: \"number\", default: 3, describe: \"call stack depth to display\" },\n \"heap-verbose\": { type: \"boolean\", default: false, describe: \"verbose output with file:// paths and line numbers\" },\n \"heap-raw\": { type: \"boolean\", default: false, describe: \"dump every raw heap sample (ordinal, size, stack)\" },\n \"heap-user-only\": { type: \"boolean\", default: false, describe: \"filter to user code only (hide node internals)\" },\n url: { type: \"string\", requiresArg: true, describe: \"page URL for browser profiling (enables browser mode)\" },\n headless: { type: \"boolean\", default: true, describe: \"run browser in headless mode\" },\n timeout: { type: \"number\", default: 60, describe: \"browser page timeout in seconds\" },\n \"chrome-args\": { type: \"string\", array: true, requiresArg: true, describe: \"extra Chromium flags\" },\n} as const;\n\n/** @return yargs with standard benchmark options */\nexport function defaultCliArgs(yargsInstance: Argv): Argv<DefaultCliArgs> {\n return yargsInstance\n .command(\"$0 [file]\", \"run benchmarks\", y => {\n y.positional(\"file\", {\n type: \"string\",\n describe: \"benchmark file to run\",\n });\n })\n .options(cliOptions)\n .help()\n .strict() as Argv<DefaultCliArgs>;\n}\n\n/** @return parsed command line arguments */\nexport function parseCliArgs<T = DefaultCliArgs>(\n args: string[],\n configure: Configure<T> = defaultCliArgs as Configure<T>,\n): T {\n const yargsInstance = configure(yargs(args));\n return yargsInstance.parseSync() as T;\n}\n","import { writeFile } from \"node:fs/promises\";\nimport type { ReportGroup } from \"../BenchmarkReport.ts\";\nimport type { DefaultCliArgs } from \"../cli/CliArgs.ts\";\nimport type {\n BenchmarkGroup,\n BenchmarkJsonData,\n BenchmarkResult,\n} from \"./JsonFormat.ts\";\n\n/** Export benchmark results to JSON file */\nexport async function exportBenchmarkJson(\n groups: ReportGroup[],\n outputPath: string,\n args: DefaultCliArgs,\n suiteName = \"Benchmark Suite\",\n): Promise<void> {\n const jsonData = prepareJsonData(groups, args, suiteName);\n const jsonString = JSON.stringify(jsonData, null, 2);\n\n await writeFile(outputPath, jsonString, \"utf-8\");\n console.log(`Benchmark data exported to: ${outputPath}`);\n}\n\n/** Convert ReportGroup data to JSON format */\nfunction prepareJsonData(\n groups: ReportGroup[],\n args: DefaultCliArgs,\n suiteName: string,\n): BenchmarkJsonData {\n return {\n meta: {\n timestamp: new Date().toISOString(),\n version: process.env.npm_package_version || \"unknown\",\n args: cleanCliArgs(args),\n environment: {\n node: process.version,\n platform: process.platform,\n arch: process.arch,\n },\n },\n suites: [\n {\n name: suiteName,\n groups: groups.map(convertGroup),\n },\n ],\n };\n}\n\n/** Clean CLI args for JSON export (remove undefined values) */\nfunction cleanCliArgs(args: DefaultCliArgs): Record<string, any> {\n const toCamel = (k: string) =>\n k.replace(/-([a-z])/g, (_, l) => l.toUpperCase());\n const entries = Object.entries(args)\n .filter(([, v]) => v !== undefined && v !== null)\n .map(([k, v]) => [toCamel(k), v]);\n return Object.fromEntries(entries);\n}\n\n/** Convert a report group, mapping each report to the JSON result format */\nfunction convertGroup(group: ReportGroup): BenchmarkGroup {\n return {\n name: \"Benchmark Group\", // Could be enhanced to include actual group names\n baseline: group.baseline ? convertReport(group.baseline) : undefined,\n benchmarks: group.reports.map(convertReport),\n };\n}\n\n/** Extract measured stats and optional metrics into JSON result shape */\nfunction convertReport(report: any): BenchmarkResult {\n const { name, measuredResults: m } = report;\n const { time, heapSize, gcTime, cpu } = m;\n const minMaxMean = (s: any) =>\n s ? { min: s.min, max: s.max, mean: s.avg } : undefined;\n\n return {\n name,\n status: \"completed\",\n samples: m.samples || [],\n time: {\n ...minMaxMean(time)!,\n p50: time.p50,\n p75: time.p75,\n p99: time.p99,\n p999: time.p999,\n },\n heapSize: minMaxMean(heapSize),\n gcTime: minMaxMean(gcTime),\n cpu: cpu\n ? {\n instructions: cpu.instructions,\n cycles: cpu.cycles,\n cacheMisses: m.cpuCacheMiss,\n branchMisses: cpu.branchMisses,\n }\n : undefined,\n execution: {\n iterations: m.samples?.length || 0,\n totalTime: m.totalTime || 0,\n warmupRuns: undefined, // Not available in current data structure\n },\n };\n}\n","import { spawn } from \"node:child_process\";\nimport { readdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport type { ReportGroup } from \"../BenchmarkReport.ts\";\nimport type { DefaultCliArgs } from \"../cli/CliArgs.ts\";\nimport type { MeasuredResults } from \"../MeasuredResults.ts\";\n\n/** Chrome Trace Event format event */\ninterface TraceEvent {\n ph: string; // event type: M=metadata, C=counter, i=instant, B/E=begin/end\n ts: number; // timestamp in microseconds\n pid?: number;\n tid?: number;\n cat?: string;\n name: string;\n args?: Record<string, unknown>;\n s?: string; // scope for instant events: \"t\"=thread, \"p\"=process, \"g\"=global\n dur?: number; // duration for complete events\n}\n\n/** Chrome Trace Event format file structure */\ninterface TraceFile {\n traceEvents: TraceEvent[];\n}\n\nconst pid = 1;\nconst tid = 1;\n\n/** Export benchmark results to Perfetto-compatible trace file */\nexport function exportPerfettoTrace(\n groups: ReportGroup[],\n outputPath: string,\n args: DefaultCliArgs,\n): void {\n const absPath = resolve(outputPath);\n const events = buildTraceEvents(groups, args);\n\n // Try to merge any existing V8 trace from a previous run\n const merged = mergeV8Trace(events);\n writeTraceFile(absPath, merged);\n console.log(`Perfetto trace exported to: ${outputPath}`);\n\n // V8 writes trace files after process exit, so spawn a child to merge later\n scheduleDeferredMerge(absPath);\n}\n\n/** Build trace events from benchmark results */\nfunction buildTraceEvents(\n groups: ReportGroup[],\n args: DefaultCliArgs,\n): TraceEvent[] {\n const meta = (name: string, a: Record<string, unknown>): TraceEvent => ({\n ph: \"M\",\n ts: 0,\n pid,\n tid,\n name,\n args: a,\n });\n const events: TraceEvent[] = [\n meta(\"process_name\", { name: \"wesl-bench\" }),\n meta(\"thread_name\", { name: \"MainThread\" }),\n meta(\"bench_settings\", cleanArgs(args)),\n ];\n\n for (const group of groups) {\n for (const report of group.reports) {\n const results = report.measuredResults as MeasuredResults;\n events.push(...buildBenchmarkEvents(results));\n }\n }\n\n return events;\n}\n\n/** Merge V8 trace events from a previous run, aligning timestamps */\nfunction mergeV8Trace(customEvents: TraceEvent[]): TraceEvent[] {\n const traceFiles = readdirSync(\".\").filter(\n f => f.startsWith(\"node_trace.\") && f.endsWith(\".log\"),\n );\n\n const v8Events = loadV8Events(traceFiles[0]);\n normalizeTimestamps(customEvents);\n if (!v8Events) return customEvents;\n\n normalizeTimestamps(v8Events);\n return [...v8Events, ...customEvents];\n}\n\n/** Write trace events to JSON file */\nfunction writeTraceFile(outputPath: string, events: TraceEvent[]): void {\n const traceFile: TraceFile = { traceEvents: events };\n writeFileSync(outputPath, JSON.stringify(traceFile));\n}\n\n/** Spawn a detached child to merge V8 trace after process exit */\nfunction scheduleDeferredMerge(outputPath: string): void {\n const cwd = process.cwd();\n const mergeScript = `\n const { readdirSync, readFileSync, writeFileSync } = require('fs');\n function normalize(events) {\n const times = events.filter(e => e.ts > 0).map(e => e.ts);\n if (!times.length) return;\n const min = Math.min(...times);\n for (const e of events) if (e.ts > 0) e.ts -= min;\n }\n setTimeout(() => {\n const traceFiles = readdirSync('.').filter(f => f.startsWith('node_trace.') && f.endsWith('.log'));\n if (traceFiles.length === 0) process.exit(0);\n try {\n const v8Data = JSON.parse(readFileSync(traceFiles[0], 'utf-8'));\n const ourData = JSON.parse(readFileSync('${outputPath}', 'utf-8'));\n normalize(v8Data.traceEvents);\n const merged = { traceEvents: [...v8Data.traceEvents, ...ourData.traceEvents] };\n writeFileSync('${outputPath}', JSON.stringify(merged));\n console.log('Merged ' + v8Data.traceEvents.length + ' V8 events into ' + '${outputPath}');\n } catch (e) { console.error('Merge failed:', e.message); }\n }, 100);\n `;\n\n process.on(\"exit\", () => {\n const child = spawn(\"node\", [\"-e\", mergeScript], {\n detached: true,\n stdio: \"inherit\",\n cwd,\n });\n child.unref();\n });\n}\n\n/** Clean CLI args for metadata */\nfunction cleanArgs(args: DefaultCliArgs): Record<string, unknown> {\n const skip = new Set([\"_\", \"$0\"]);\n const entries = Object.entries(args).filter(\n ([k, v]) => v !== undefined && !skip.has(k),\n );\n return Object.fromEntries(entries);\n}\n\n/** Build events for a single benchmark run */\nfunction buildBenchmarkEvents(results: MeasuredResults): TraceEvent[] {\n const { samples, heapSamples, timestamps, pausePoints } = results;\n if (!timestamps?.length) return [];\n\n const events: TraceEvent[] = [];\n for (let i = 0; i < samples.length; i++) {\n const ts = timestamps[i];\n const ms = Math.round(samples[i] * 100) / 100;\n events.push(instant(ts, results.name, { n: i, ms }));\n events.push(counter(ts, \"duration\", { ms }));\n if (heapSamples?.[i] !== undefined) {\n const MB = Math.round((heapSamples[i] / 1024 / 1024) * 10) / 10;\n events.push(counter(ts, \"heap\", { MB }));\n }\n }\n\n for (const pause of pausePoints ?? []) {\n const ts = timestamps[pause.sampleIndex];\n if (ts) events.push(instant(ts, \"pause\", { ms: pause.durationMs }));\n }\n return events;\n}\n\n/** Load V8 trace events from file, or undefined if unavailable */\nfunction loadV8Events(\n v8TracePath: string | undefined,\n): TraceEvent[] | undefined {\n if (!v8TracePath) return undefined;\n try {\n const v8Data = JSON.parse(readFileSync(v8TracePath, \"utf-8\")) as TraceFile;\n console.log(\n `Merged ${v8Data.traceEvents.length} V8 events from ${v8TracePath}`,\n );\n return v8Data.traceEvents;\n } catch {\n console.warn(`Could not parse V8 trace file: ${v8TracePath}`);\n return undefined;\n }\n}\n\n/** Normalize timestamps so events start at 0 */\nfunction normalizeTimestamps(events: TraceEvent[]): void {\n const times = events.filter(e => e.ts > 0).map(e => e.ts);\n if (times.length === 0) return;\n const minTs = Math.min(...times);\n for (const e of events) if (e.ts > 0) e.ts -= minTs;\n}\n\nfunction instant(\n ts: number,\n name: string,\n args: Record<string, unknown>,\n): TraceEvent {\n return { ph: \"i\", ts, pid, tid, cat: \"bench\", name, s: \"t\", args };\n}\n\nfunction counter(\n ts: number,\n name: string,\n args: Record<string, unknown>,\n): TraceEvent {\n return { ph: \"C\", ts, pid, tid, cat: \"bench\", name, args };\n}\n","import type { HeapProfile, HeapSample, ProfileNode } from \"./HeapSampler.ts\";\n\n/** A call frame with display-ready 1-indexed source positions */\nexport interface ResolvedFrame {\n /** Function name, \"(anonymous)\" when empty */\n name: string;\n\n /** Script URL or file path, \"\" when unknown */\n url: string;\n\n /** 1-indexed line number */\n line: number;\n\n /** 1-indexed column number (undefined when unknown) */\n col?: number;\n}\n\n/** A profile node with its resolved call stack from root to this node */\nexport interface ResolvedNode {\n /** The call frame at this node */\n frame: ResolvedFrame;\n\n /** Call stack from root to this node (inclusive) */\n stack: ResolvedFrame[];\n\n /** Bytes allocated directly at this node */\n selfSize: number;\n\n /** V8 node ID, used to match {@link HeapSample.nodeId} */\n nodeId: number;\n}\n\n/** Pre-resolved heap profile: single tree walk produces all derived data */\nexport interface ResolvedProfile {\n /** All nodes from the profile tree, flattened */\n nodes: ResolvedNode[];\n\n /** nodeId -> ResolvedNode lookup */\n nodeMap: Map<number, ResolvedNode>;\n\n /** Nodes with selfSize > 0, sorted by selfSize descending */\n allocationNodes: ResolvedNode[];\n\n /** Samples sorted by ordinal (temporal order), if available */\n sortedSamples: HeapSample[] | undefined;\n\n /** Total bytes across all nodes (sum of selfSize) */\n totalBytes: number;\n}\n\n/** Walk a HeapProfile tree once, producing a fully resolved intermediate form */\nexport function resolveProfile(profile: HeapProfile): ResolvedProfile {\n const nodes: ResolvedNode[] = [];\n const nodeMap = new Map<number, ResolvedNode>();\n let totalBytes = 0;\n\n function walk(node: ProfileNode, parentStack: ResolvedFrame[]): void {\n const { functionName, url, lineNumber, columnNumber } = node.callFrame;\n const frame: ResolvedFrame = {\n name: functionName || \"(anonymous)\",\n url: url || \"\",\n line: lineNumber + 1,\n col: columnNumber != null ? columnNumber + 1 : undefined,\n };\n const stack = [...parentStack, frame];\n const resolved: ResolvedNode = {\n frame,\n stack,\n selfSize: node.selfSize,\n nodeId: node.id,\n };\n nodes.push(resolved);\n nodeMap.set(node.id, resolved);\n totalBytes += node.selfSize;\n for (const child of node.children || []) walk(child, stack);\n }\n\n walk(profile.head, []);\n\n const allocationNodes = nodes\n .filter(n => n.selfSize > 0)\n .sort((a, b) => b.selfSize - a.selfSize);\n\n const sortedSamples = profile.samples\n ? [...profile.samples].sort((a, b) => a.ordinal - b.ordinal)\n : undefined;\n\n return { nodes, nodeMap, allocationNodes, sortedSamples, totalBytes };\n}\n","import { spawn } from \"node:child_process\";\nimport { writeFileSync } from \"node:fs\";\nimport { tmpdir } from \"node:os\";\nimport { join, resolve } from \"node:path\";\n\nimport { groupReports, type ReportGroup } from \"../BenchmarkReport.ts\";\nimport type { HeapProfile } from \"../heap-sample/HeapSampler.ts\";\nimport {\n type ResolvedFrame,\n type ResolvedProfile,\n resolveProfile,\n} from \"../heap-sample/ResolvedProfile.ts\";\n\n/** speedscope file format (https://www.speedscope.app/file-format-schema.json) */\ninterface SpeedscopeFile {\n $schema: \"https://www.speedscope.app/file-format-schema.json\";\n shared: { frames: SpeedscopeFrame[] };\n profiles: SpeedscopeProfile[];\n name?: string;\n exporter?: string;\n}\n\ninterface SpeedscopeFrame {\n name: string;\n file?: string;\n line?: number;\n col?: number;\n}\n\ninterface SpeedscopeProfile {\n type: \"sampled\";\n name: string;\n unit: \"bytes\";\n startValue: number;\n endValue: number;\n samples: number[][]; // each sample is stack of frame indices\n weights: number[]; // bytes per sample\n}\n\n/** Export heap profiles from benchmark results to speedscope JSON format.\n * Creates one speedscope profile per benchmark that has a heapProfile.\n * @returns resolved output path, or undefined if no profiles were found */\nexport function exportSpeedscope(\n groups: ReportGroup[],\n outputPath: string,\n): string | undefined {\n const frames: SpeedscopeFrame[] = [];\n const frameIndex = new Map<string, number>();\n const profiles: SpeedscopeProfile[] = [];\n\n for (const group of groups) {\n for (const report of groupReports(group)) {\n const { heapProfile } = report.measuredResults;\n if (!heapProfile) continue;\n const resolved = resolveProfile(heapProfile);\n profiles.push(buildProfile(report.name, resolved, frames, frameIndex));\n }\n }\n\n if (profiles.length === 0) {\n console.log(\"No heap profiles to export.\");\n return undefined;\n }\n\n const file: SpeedscopeFile = {\n $schema: \"https://www.speedscope.app/file-format-schema.json\",\n shared: { frames },\n profiles,\n exporter: \"benchforge\",\n };\n\n const absPath = resolve(outputPath);\n writeFileSync(absPath, JSON.stringify(file));\n console.log(`Speedscope profile exported to: ${outputPath}`);\n return absPath;\n}\n\n/** Export to a temp file and open in speedscope via npx */\nexport function exportAndLaunchSpeedscope(groups: ReportGroup[]): void {\n const timestamp = new Date().toISOString().replace(/[:.]/g, \"-\");\n const outputPath = join(tmpdir(), `benchforge-${timestamp}.speedscope.json`);\n const absPath = exportSpeedscope(groups, outputPath);\n if (absPath) {\n launchSpeedscope(absPath);\n }\n}\n\n/** Launch speedscope viewer on a file via npx */\nexport function launchSpeedscope(filePath: string): void {\n console.log(\"Opening speedscope...\");\n const child = spawn(\"npx\", [\"speedscope\", filePath], {\n detached: true,\n stdio: \"ignore\",\n });\n child.unref();\n child.on(\"error\", () => {\n console.error(\n `Failed to launch speedscope. Run manually:\\n npx speedscope ${filePath}`,\n );\n });\n}\n\n/** Convert a single HeapProfile to speedscope format (for standalone use) */\nexport function heapProfileToSpeedscope(\n name: string,\n profile: HeapProfile,\n): SpeedscopeFile {\n const frames: SpeedscopeFrame[] = [];\n const frameIndex = new Map<string, number>();\n const resolved = resolveProfile(profile);\n const p = buildProfile(name, resolved, frames, frameIndex);\n\n return {\n $schema: \"https://www.speedscope.app/file-format-schema.json\",\n shared: { frames },\n profiles: [p],\n exporter: \"benchforge\",\n };\n}\n\n/** Build a single speedscope profile from a resolved heap profile */\nfunction buildProfile(\n name: string,\n resolved: ResolvedProfile,\n sharedFrames: SpeedscopeFrame[],\n frameIndex: Map<string, number>,\n): SpeedscopeProfile {\n // Build nodeId -> stack of frame indices\n const nodeStacks = new Map<number, number[]>();\n for (const node of resolved.nodes) {\n const stack = node.stack.map(f => internFrame(f, sharedFrames, frameIndex));\n nodeStacks.set(node.nodeId, stack);\n }\n\n const samples: number[][] = [];\n const weights: number[] = [];\n\n if (!resolved.sortedSamples || resolved.sortedSamples.length === 0) {\n console.error(\n `Speedscope export: no samples in heap profile for \"${name}\", skipping`,\n );\n return {\n type: \"sampled\",\n name,\n unit: \"bytes\",\n startValue: 0,\n endValue: 0,\n samples,\n weights,\n };\n }\n\n for (const sample of resolved.sortedSamples) {\n const stack = nodeStacks.get(sample.nodeId);\n if (stack) {\n samples.push(stack);\n weights.push(sample.size);\n }\n }\n\n const totalBytes = weights.reduce((sum, w) => sum + w, 0);\n\n return {\n type: \"sampled\",\n name,\n unit: \"bytes\",\n startValue: 0,\n endValue: totalBytes,\n samples,\n weights,\n };\n}\n\n/** Intern a call frame, returning its index in the shared frames array */\nfunction internFrame(\n frame: ResolvedFrame,\n sharedFrames: SpeedscopeFrame[],\n frameIndex: Map<string, number>,\n): number {\n const { name, url, line, col } = frame;\n const key = `${name}\\0${url}\\0${line}\\0${col}`;\n\n let idx = frameIndex.get(key);\n if (idx === undefined) {\n idx = sharedFrames.length;\n // Match speedscope's convention: anonymous functions include location in name\n const shortFile = url ? url.split(\"/\").pop() : undefined;\n const displayName =\n name !== \"(anonymous)\"\n ? name\n : shortFile\n ? `(anonymous ${shortFile}:${line})`\n : \"(anonymous)\";\n const entry: SpeedscopeFrame = { name: displayName };\n if (url) entry.file = url;\n if (line > 0) entry.line = line;\n if (col != null) entry.col = col;\n sharedFrames.push(entry);\n frameIndex.set(key, idx);\n }\n return idx;\n}\n","import type {\n ReportColumnGroup,\n ReportGroup,\n ResultsMapper,\n} from \"./BenchmarkReport.ts\";\nimport type { GitVersion } from \"./GitUtils.ts\";\nimport type {\n BenchmarkData,\n DifferenceCI,\n FormattedStat,\n GroupData,\n ReportData,\n} from \"./html/index.ts\";\nimport { bootstrapDifferenceCI } from \"./StatisticalUtils.ts\";\n\nexport interface PrepareHtmlOptions {\n cliArgs?: Record<string, unknown>;\n sections?: ResultsMapper[];\n currentVersion?: GitVersion;\n baselineVersion?: GitVersion;\n}\n\ntype ColumnLike = {\n key: string;\n title: string;\n formatter?: (v: unknown) => string | null;\n};\n\n/** Prepare ReportData from benchmark results for HTML rendering */\nexport function prepareHtmlData(\n groups: ReportGroup[],\n options: PrepareHtmlOptions,\n): ReportData {\n const { cliArgs, sections, currentVersion, baselineVersion } = options;\n const higherIsBetter = findHigherIsBetter(sections);\n return {\n groups: groups.map(group =>\n prepareGroupData(group, sections, higherIsBetter),\n ),\n metadata: {\n timestamp: new Date().toISOString(),\n bencherVersion: process.env.npm_package_version || \"unknown\",\n cliArgs,\n gcTrackingEnabled: cliArgs?.[\"gc-stats\"] === true,\n currentVersion,\n baselineVersion,\n },\n };\n}\n\n/** Find higherIsBetter from first comparable column in sections */\nfunction findHigherIsBetter(sections?: ResultsMapper[]): boolean {\n const cols = sections?.flatMap(s => s.columns().flatMap(g => g.columns));\n return cols?.find(c => c.comparable)?.higherIsBetter ?? false;\n}\n\n/** @return group data with bootstrap CI comparisons against baseline */\nfunction prepareGroupData(\n group: ReportGroup,\n sections?: ResultsMapper[],\n higherIsBetter?: boolean,\n): GroupData {\n const baselineSamples = group.baseline?.measuredResults.samples;\n return {\n name: group.name,\n baseline: group.baseline\n ? prepareBenchmarkData(group.baseline, sections)\n : undefined,\n benchmarks: group.reports.map(report => {\n const samples = report.measuredResults.samples;\n const rawCI =\n baselineSamples && samples\n ? bootstrapDifferenceCI(baselineSamples, samples)\n : undefined;\n const comparisonCI = rawCI && higherIsBetter ? flipCI(rawCI) : rawCI;\n return { ...prepareBenchmarkData(report, sections), comparisonCI };\n }),\n };\n}\n\n/** @return benchmark data with samples, stats, and formatted section values */\nfunction prepareBenchmarkData(\n report: {\n name: string;\n measuredResults: any;\n metadata?: Record<string, unknown>;\n },\n sections?: ResultsMapper[],\n): Omit<BenchmarkData, \"comparisonCI\"> {\n const { measuredResults } = report;\n return {\n name: report.name,\n samples: measuredResults.samples,\n warmupSamples: measuredResults.warmupSamples,\n allocationSamples: measuredResults.allocationSamples,\n heapSamples: measuredResults.heapSamples,\n gcEvents: measuredResults.nodeGcTime?.events,\n optSamples: measuredResults.optSamples,\n pausePoints: measuredResults.pausePoints,\n stats: measuredResults.time,\n heapSize: measuredResults.heapSize,\n sectionStats: sections ? extractSectionStats(report, sections) : undefined,\n };\n}\n\n/** Flip CI percent for metrics where higher is better (e.g., lines/sec) */\nfunction flipCI(ci: DifferenceCI): DifferenceCI {\n return {\n percent: -ci.percent,\n ci: [-ci.ci[1], -ci.ci[0]],\n direction: ci.direction,\n histogram: ci.histogram?.map(bin => ({ x: -bin.x, count: bin.count })),\n };\n}\n\n/** @return formatted stats from all sections for tooltip display */\nfunction extractSectionStats(\n report: { measuredResults: any; metadata?: Record<string, unknown> },\n sections: ResultsMapper[],\n): FormattedStat[] {\n return sections.flatMap(section => {\n const vals = section.extract(report.measuredResults, report.metadata);\n return section.columns().flatMap(g => formatGroupStats(vals, g));\n });\n}\n\n/** @return formatted stats for one column group, skipping undefined values */\nfunction formatGroupStats(\n values: Record<string, unknown>,\n group: ReportColumnGroup<Record<string, unknown>>,\n): FormattedStat[] {\n return group.columns\n .map(c => formatColumnStat(values, c, group.groupTitle))\n .filter((s): s is FormattedStat => s !== undefined);\n}\n\n/** @return formatted stat for a single column, or undefined if empty/placeholder */\nfunction formatColumnStat(\n values: Record<string, unknown>,\n col: ColumnLike,\n groupTitle?: string,\n): FormattedStat | undefined {\n const raw = values[col.key];\n if (raw === undefined) return undefined;\n const formatted = col.formatter ? col.formatter(raw) : String(raw);\n if (!formatted || formatted === \"—\" || formatted === \"\") return undefined;\n return { label: col.title, value: formatted, groupTitle };\n}\n","import pc from \"picocolors\";\n\nimport { formatBytes } from \"../table-util/Formatters.ts\";\nimport type { HeapProfile, HeapSample } from \"./HeapSampler.ts\";\nimport {\n type ResolvedFrame,\n type ResolvedProfile,\n resolveProfile,\n} from \"./ResolvedProfile.ts\";\n\nexport interface CallFrame {\n fn: string;\n url: string;\n line: number; // 1-indexed for display\n col?: number; // 1-indexed for display\n}\n\nexport interface HeapSite {\n fn: string;\n url: string;\n line: number; // 1-indexed for display\n col?: number;\n bytes: number;\n stack?: CallFrame[]; // call stack from root to this frame\n samples?: HeapSample[]; // individual allocation samples at this site\n callers?: { stack: CallFrame[]; bytes: number }[]; // distinct caller paths\n}\n\nexport type UserCodeFilter = (site: CallFrame) => boolean;\n\nexport interface HeapReportOptions {\n topN: number;\n stackDepth?: number;\n verbose?: boolean;\n raw?: boolean; // dump every raw sample\n userOnly?: boolean; // filter to user code only (hide node internals)\n isUserCode?: UserCodeFilter; // predicate for user vs internal code\n totalAll?: number; // total across all nodes (before filtering)\n totalUserCode?: number; // total for user code only\n sampleCount?: number; // number of samples taken\n}\n\n/** Sum selfSize across all nodes in profile (before any filtering) */\nexport function totalProfileBytes(profile: HeapProfile): number {\n return resolveProfile(profile).totalBytes;\n}\n\n/** Flatten resolved profile into sorted list of allocation sites with call stacks.\n * When raw samples are available, attaches them to corresponding sites. */\nexport function flattenProfile(resolved: ResolvedProfile): HeapSite[] {\n const sites: HeapSite[] = [];\n const nodeIdToSites = new Map<number, HeapSite[]>();\n\n for (const node of resolved.allocationNodes) {\n const frame = toCallFrame(node.frame);\n const stack = node.stack.map(toCallFrame);\n const site: HeapSite = { ...frame, bytes: node.selfSize, stack };\n sites.push(site);\n const existing = nodeIdToSites.get(node.nodeId);\n if (existing) existing.push(site);\n else nodeIdToSites.set(node.nodeId, [site]);\n }\n\n // Attach raw samples to their corresponding sites\n for (const sample of resolved.sortedSamples ?? []) {\n const matchingSites = nodeIdToSites.get(sample.nodeId);\n if (!matchingSites) continue;\n for (const site of matchingSites) {\n if (!site.samples) site.samples = [];\n site.samples.push(sample);\n }\n }\n\n return sites.sort((a, b) => b.bytes - a.bytes);\n}\n\n/** Check if site is user code (not node internals) */\nexport function isNodeUserCode(site: CallFrame): boolean {\n if (!site.url) return false;\n if (site.url.startsWith(\"node:\")) return false;\n if (site.url.includes(\"(native)\")) return false;\n if (site.url.includes(\"internal/\")) return false;\n return true;\n}\n\n/** Check if site is user code (not browser internals) */\nexport function isBrowserUserCode(site: CallFrame): boolean {\n if (!site.url) return false;\n if (site.url.startsWith(\"chrome-extension://\")) return false;\n if (site.url.startsWith(\"devtools://\")) return false;\n if (site.url.includes(\"(native)\")) return false;\n return true;\n}\n\n/** Filter sites to user code only */\nexport function filterSites(\n sites: HeapSite[],\n isUser: UserCodeFilter = isNodeUserCode,\n): HeapSite[] {\n return sites.filter(isUser);\n}\n\n/** Aggregate sites by location (combine same file:line:col).\n * Tracks distinct caller stacks with byte weights when merging. */\nexport function aggregateSites(sites: HeapSite[]): HeapSite[] {\n const byLocation = new Map<string, HeapSite>();\n\n for (const site of sites) {\n // When column is unknown, include fn name to avoid merging distinct sites\n const key =\n site.col != null\n ? `${site.url}:${site.line}:${site.col}`\n : `${site.url}:${site.line}:?:${site.fn}`;\n const existing = byLocation.get(key);\n if (existing) {\n existing.bytes += site.bytes;\n addCaller(existing, site);\n } else {\n const entry = { ...site };\n if (site.stack) {\n entry.callers = [{ stack: site.stack, bytes: site.bytes }];\n }\n byLocation.set(key, entry);\n }\n }\n\n // Sort callers by bytes descending, use top caller as primary stack\n for (const site of byLocation.values()) {\n if (site.callers && site.callers.length > 1) {\n site.callers.sort((a, b) => b.bytes - a.bytes);\n site.stack = site.callers[0].stack;\n }\n }\n\n return [...byLocation.values()].sort((a, b) => b.bytes - a.bytes);\n}\n\n/** Format heap report for console output */\nexport function formatHeapReport(\n sites: HeapSite[],\n options: HeapReportOptions,\n): string {\n const { topN, stackDepth = 3, verbose = false } = options;\n const { totalAll, totalUserCode, sampleCount } = options;\n const isUser = options.isUserCode ?? isNodeUserCode;\n const lines: string[] = [];\n lines.push(`Heap allocation sites (top ${topN}, garbage included):`);\n\n for (const site of sites.slice(0, topN)) {\n if (verbose) {\n formatVerboseSite(lines, site, stackDepth, isUser);\n } else {\n formatCompactSite(lines, site, stackDepth, isUser);\n }\n }\n\n lines.push(\"\");\n if (totalAll !== undefined)\n lines.push(`Total (all): ${fmtBytes(totalAll)}`);\n if (totalUserCode !== undefined)\n lines.push(`Total (user-code): ${fmtBytes(totalUserCode)}`);\n if (sampleCount !== undefined)\n lines.push(`Samples: ${sampleCount.toLocaleString()}`);\n\n return lines.join(\"\\n\");\n}\n\n/** Get total bytes from sites */\nexport function totalBytes(sites: HeapSite[]): number {\n return sites.reduce((sum, s) => sum + s.bytes, 0);\n}\n\n/** Format every raw sample as one line, ordered by ordinal (time).\n * Output is tab-separated for easy piping/grep/diff. */\nexport function formatRawSamples(resolved: ResolvedProfile): string {\n if (!resolved.sortedSamples || resolved.sortedSamples.length === 0) {\n return \"No raw samples available.\";\n }\n\n const lines: string[] = [\"ordinal\\tsize\\tfunction\\tlocation\"];\n for (const s of resolved.sortedSamples) {\n const node = resolved.nodeMap.get(s.nodeId);\n const fn = node?.frame.name || \"(unknown)\";\n const url = node?.frame.url || \"\";\n const loc = url\n ? fmtLoc(url, node!.frame.line, node!.frame.col)\n : \"(unknown)\";\n lines.push(`${s.ordinal}\\t${s.size}\\t${fn}\\t${loc}`);\n }\n return lines.join(\"\\n\");\n}\n\nfunction toCallFrame(f: ResolvedFrame): CallFrame {\n return { fn: f.name, url: f.url, line: f.line, col: f.col };\n}\n\n/** Add a caller stack to an aggregated site, merging if the same path exists */\nfunction addCaller(existing: HeapSite, site: HeapSite): void {\n if (!site.stack) return;\n if (!existing.callers) {\n existing.callers = [];\n }\n const key = callerKey(site.stack);\n const match = existing.callers.find(c => callerKey(c.stack) === key);\n if (match) {\n match.bytes += site.bytes;\n } else {\n existing.callers.push({ stack: site.stack, bytes: site.bytes });\n }\n}\n\n/** Verbose multi-line format with file:// paths and line numbers */\nfunction formatVerboseSite(\n lines: string[],\n site: HeapSite,\n stackDepth: number,\n isUser: UserCodeFilter,\n): void {\n const bytes = fmtBytes(site.bytes).padStart(10);\n const loc = site.url ? fmtLoc(site.url, site.line, site.col) : \"(unknown)\";\n const dimFn = isUser(site) ? (s: string) => s : pc.dim;\n\n lines.push(dimFn(`${bytes} ${site.fn} ${loc}`));\n\n if (site.stack && site.stack.length > 1) {\n const callers = site.stack.slice(0, -1).reverse().slice(0, stackDepth);\n for (const frame of callers) {\n if (!frame.url || !isUser(frame)) continue;\n const callerLoc = fmtLoc(frame.url, frame.line, frame.col);\n lines.push(dimFn(` <- ${frame.fn} ${callerLoc}`));\n }\n }\n}\n\n/** Compact single-line format: `49 MB fn1 <- fn2 <- fn3` */\nfunction formatCompactSite(\n lines: string[],\n site: HeapSite,\n stackDepth: number,\n isUser: UserCodeFilter,\n): void {\n const bytes = fmtBytes(site.bytes).padStart(10);\n const fns = [site.fn];\n\n if (site.stack && site.stack.length > 1) {\n const callers = site.stack.slice(0, -1).reverse().slice(0, stackDepth);\n for (const frame of callers) {\n if (!frame.url || !isUser(frame)) continue;\n fns.push(frame.fn);\n }\n }\n\n const line = `${bytes} ${fns.join(\" <- \")}`;\n lines.push(isUser(site) ? line : pc.dim(line));\n}\n\nfunction fmtBytes(bytes: number): string {\n return formatBytes(bytes, { space: true }) ?? `${bytes} B`;\n}\n\n/** Format location, omitting column when unknown */\nfunction fmtLoc(url: string, line: number, col?: number): string {\n return col != null ? `${url}:${line}:${col}` : `${url}:${line}`;\n}\n\n/** Serialize a call stack for dedup comparison */\nfunction callerKey(stack: CallFrame[]): string {\n return stack.map(f => `${f.url}:${f.line}:${f.col}`).join(\"|\");\n}\n","import type { GitVersion, GroupData, ReportData } from \"./Types.ts\";\n\nconst skipArgs = new Set([\"_\", \"$0\", \"html\", \"export-html\"]);\n\nconst badgeLabels = {\n faster: \"Faster\",\n slower: \"Slower\",\n uncertain: \"Inconclusive\",\n};\nconst defaultArgs: Record<string, unknown> = {\n worker: true,\n time: 5,\n warmup: 500,\n \"pause-interval\": 0,\n \"pause-duration\": 100,\n};\n\n/** Format ISO date as local time with UTC: \"Jan 9, 2026, 3:45 PM (2026-01-09T23:45:00Z)\" */\nexport function formatDateWithTimezone(isoDate: string): string {\n const date = new Date(isoDate);\n const local = date.toLocaleString(\"en-US\", {\n month: \"short\",\n day: \"numeric\",\n year: \"numeric\",\n hour: \"numeric\",\n minute: \"2-digit\",\n });\n const utc = date.toISOString().replace(\".000Z\", \"Z\");\n return `${local} (${utc})`;\n}\n\n/** Format relative time: \"5m ago\", \"2h ago\", \"yesterday\", \"3 days ago\" */\nexport function formatRelativeTime(isoDate: string): string {\n const date = new Date(isoDate);\n const now = new Date();\n const diffMs = now.getTime() - date.getTime();\n const diffMins = Math.floor(diffMs / 60000);\n const diffHours = Math.floor(diffMs / 3600000);\n const diffDays = Math.floor(diffMs / 86400000);\n\n if (diffMins < 1) return \"just now\";\n if (diffMins < 60) return `${diffMins}m ago`;\n if (diffHours < 24) return `${diffHours}h ago`;\n if (diffDays === 1) return \"yesterday\";\n if (diffDays < 30) return `${diffDays} days ago`;\n return date.toLocaleDateString(\"en-US\", { month: \"short\", day: \"numeric\" });\n}\n\n/** Generate complete HTML document with embedded data and visualizations */\nexport function generateHtmlDocument(data: ReportData): string {\n return `<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n <title>Benchmark Report - ${new Date().toLocaleDateString()}</title>\n <style>\n * { margin: 0; padding: 0; box-sizing: border-box; }\n body {\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif;\n background: #f5f5f5;\n padding: 20px;\n line-height: 1.6;\n }\n .header {\n background: white;\n padding: 10px 15px;\n border-radius: 8px;\n margin-bottom: 20px;\n box-shadow: 0 2px 4px rgba(0,0,0,0.1);\n display: flex;\n justify-content: space-between;\n align-items: center;\n }\n h1 { display: none; }\n h2 {\n color: #555;\n margin: 30px 0 20px;\n font-size: 20px;\n border-bottom: 2px solid #e0e0e0;\n padding-bottom: 10px;\n }\n .metadata { color: #666; font-size: 12px; }\n .cli-args {\n font-family: \"SF Mono\", Monaco, \"Consolas\", monospace;\n font-size: 11px;\n color: #555;\n background: #f0f0f0;\n padding: 6px 10px;\n border-radius: 4px;\n word-break: break-word;\n }\n .comparison-mode {\n background: #fff3cd;\n color: #856404;\n padding: 8px 12px;\n border-radius: 4px;\n display: inline-block;\n margin-top: 10px;\n font-weight: 500;\n }\n .plot-grid {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 20px;\n margin-bottom: 30px;\n }\n .plot-grid.second-row { grid-template-columns: 1fr; }\n .plot-container {\n background: white;\n padding: 20px;\n border-radius: 8px;\n box-shadow: 0 2px 4px rgba(0,0,0,0.1);\n }\n .plot-container.full-width { grid-column: 1 / -1; }\n .plot-title { font-size: 18px; font-weight: 600; margin-bottom: 8px; color: #333; }\n .plot-description { font-size: 14px; color: #666; margin-bottom: 15px; }\n .plot-area {\n display: flex;\n justify-content: center;\n align-items: center;\n min-height: 300px;\n }\n .plot-area svg { overflow: visible; }\n .plot-area svg g[aria-label=\"x-axis label\"] text { font-size: 14px; }\n .summary-stats { background: #f8f9fa; padding: 15px; border-radius: 6px; margin-top: 20px; }\n .stats-grid {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));\n gap: 10px;\n margin-top: 10px;\n }\n .stat-item { background: white; padding: 10px; border-radius: 4px; text-align: center; }\n .stat-label { font-size: 12px; color: #666; text-transform: uppercase; letter-spacing: 0.5px; }\n .stat-value { font-size: 18px; font-weight: 600; color: #333; margin-top: 4px; }\n .loading { color: #666; font-style: italic; padding: 20px; text-align: center; }\n .error { color: #d32f2f; background: #ffebee; padding: 15px; border-radius: 4px; margin: 10px 0; }\n .ci-faster { color: #22c55e; }\n .ci-slower { color: #ef4444; }\n .ci-uncertain { color: #6b7280; }\n .group-header {\n display: flex;\n align-items: center;\n gap: 12px;\n margin: 30px 0 20px;\n padding-bottom: 10px;\n border-bottom: 2px solid #e0e0e0;\n }\n .group-header h2 { margin: 0; border: none; padding: 0; }\n .badge {\n font-size: 12px;\n font-weight: 600;\n padding: 4px 10px;\n border-radius: 12px;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n }\n .badge-faster { background: #dcfce7; color: #166534; }\n .badge-slower { background: #fee2e2; color: #991b1b; }\n .badge-uncertain { background: #dbeafe; color: #1e40af; }\n .version-info { font-size: 12px; color: #666; margin-top: 6px; }\n .header-right { text-align: right; }\n .ci-plot-container { display: inline-block; vertical-align: middle; margin-left: 8px; }\n .ci-plot-container svg { display: block; }\n </style>\n</head>\n<body>\n <div class=\"header\">\n <div class=\"cli-args\">${formatCliArgs(data.metadata.cliArgs)}</div>\n <div class=\"header-right\">\n <div class=\"metadata\">Generated: ${formatDateWithTimezone(new Date().toISOString())}</div>\n ${versionInfoHtml(data)}\n </div>\n </div>\n\n ${data.groups\n .map(\n (group, i) => `\n <div id=\"group-${i}\">\n ${\n group.benchmarks.length > 0\n ? `\n <div class=\"group-header\">\n <h2>${group.name}</h2>\n ${comparisonBadge(group, i)}\n </div>\n\n <div class=\"plot-grid\">\n <div class=\"plot-container\">\n <div class=\"plot-title\">Time per Sample</div>\n <div class=\"plot-description\">Execution time for each sample in collection order</div>\n <div id=\"sample-timeseries-${i}\" class=\"plot-area\">\n <div class=\"loading\">Loading time series...</div>\n </div>\n </div>\n\n <div class=\"plot-container\">\n <div class=\"plot-title\">Time Distribution</div>\n <div class=\"plot-description\">Frequency distribution of execution times</div>\n <div id=\"histogram-${i}\" class=\"plot-area\">\n <div class=\"loading\">Loading histogram...</div>\n </div>\n </div>\n </div>\n\n <div id=\"stats-${i}\"></div>\n `\n : '<div class=\"error\">No benchmark data available for this group</div>'\n }\n </div>\n `,\n )\n .join(\"\")}\n\n <script type=\"importmap\">\n {\n \"imports\": {\n \"d3\": \"https://cdn.jsdelivr.net/npm/d3@7/+esm\",\n \"@observablehq/plot\": \"https://cdn.jsdelivr.net/npm/@observablehq/plot@0.6/+esm\"\n }\n }\n </script>\n <script type=\"module\">\n import { renderPlots } from \"./plots.js\";\n const benchmarkData = ${JSON.stringify(data, null, 2)};\n renderPlots(benchmarkData);\n </script>\n</body>\n</html>`;\n}\n\n/** Reconstruct the CLI invocation string, omitting default/internal args */\nfunction formatCliArgs(args?: Record<string, unknown>): string {\n if (!args) return \"bb bench\";\n const parts = [\"bb bench\"];\n for (const [key, value] of Object.entries(args)) {\n if (shouldSkipArg(key, value, args.adaptive)) continue;\n parts.push(value === true ? `--${key}` : `--${key} ${value}`);\n }\n return parts.join(\" \");\n}\n\n/** Render current/baseline version info as an HTML div */\nfunction versionInfoHtml(data: ReportData): string {\n const { currentVersion, baselineVersion } = data.metadata;\n if (!currentVersion && !baselineVersion) return \"\";\n const parts: string[] = [];\n if (currentVersion) parts.push(`Current: ${formatVersion(currentVersion)}`);\n if (baselineVersion)\n parts.push(`Baseline: ${formatVersion(baselineVersion)}`);\n return `<div class=\"version-info\">${parts.join(\" | \")}</div>`;\n}\n\n/** Render faster/slower/uncertain badge with CI plot container */\nfunction comparisonBadge(group: GroupData, groupIndex: number): string {\n const ci = group.benchmarks[0]?.comparisonCI;\n if (!ci) return \"\";\n const label = badgeLabels[ci.direction];\n return `\n <span class=\"badge badge-${ci.direction}\">${label}</span>\n <div id=\"ci-plot-${groupIndex}\" class=\"ci-plot-container\"></div>\n `;\n}\n\n/** @return true if this CLI arg should be hidden from the report header */\nfunction shouldSkipArg(\n key: string,\n value: unknown,\n adaptive: unknown,\n): boolean {\n if (skipArgs.has(key) || value === undefined || value === false) return true;\n if (defaultArgs[key] === value) return true;\n if (!key.includes(\"-\") && key !== key.toLowerCase()) return true; // skip yargs camelCase aliases\n if (key === \"convergence\" && !adaptive) return true;\n return false;\n}\n\n/** Format git version for display: \"abc1234* (5m ago)\" */\nfunction formatVersion(version?: GitVersion): string {\n if (!version || version.hash === \"unknown\") return \"unknown\";\n const hashDisplay = version.dirty ? `${version.hash}*` : version.hash;\n const timeDisplay = version.date ? formatRelativeTime(version.date) : \"\";\n return timeDisplay ? `${hashDisplay} (${timeDisplay})` : hashDisplay;\n}\n","import { mkdir, readFile, writeFile } from \"node:fs/promises\";\nimport { createServer, type Server } from \"node:http\";\nimport { dirname, extname, join } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport open from \"open\";\nimport { generateHtmlDocument } from \"./HtmlTemplate.ts\";\nimport type {\n HtmlReportOptions,\n HtmlReportResult,\n ReportData,\n} from \"./Types.ts\";\n\n/** Generate HTML report from prepared data and optionally open in browser */\nexport async function generateHtmlReport(\n data: ReportData,\n options: HtmlReportOptions,\n): Promise<HtmlReportResult> {\n const html = generateHtmlDocument(data);\n\n const reportDir = options.outputPath || (await createReportDir());\n await mkdir(reportDir, { recursive: true });\n\n await writeFile(join(reportDir, \"index.html\"), html, \"utf-8\");\n const plots = await loadPlotsBundle();\n await writeFile(join(reportDir, \"plots.js\"), plots, \"utf-8\");\n await writeLatestRedirect(reportDir);\n\n let server: Server | undefined;\n let closeServer: (() => void) | undefined;\n\n if (options.openBrowser) {\n const baseDir = dirname(reportDir);\n const reportName = reportDir.split(\"/\").pop();\n const result = await startReportServer(baseDir, 7979, 7978, 7977);\n server = result.server;\n closeServer = () => result.server.close();\n const openUrl = `http://localhost:${result.port}/${reportName}/`;\n await open(openUrl);\n console.log(`Report opened in browser: ${openUrl}`);\n } else {\n console.log(`Report saved to: ${reportDir}/`);\n }\n\n return { reportDir, server, closeServer };\n}\n\n/** Create a timestamped report directory under ./bench-report/ */\nasync function createReportDir(): Promise<string> {\n const base = \"./bench-report\";\n await mkdir(base, { recursive: true });\n const ts = new Date().toISOString().replace(/[:.]/g, \"-\").slice(0, 19);\n return join(base, `report-${ts}`);\n}\n\n/** Read the pre-built browser plots bundle from dist/ */\nasync function loadPlotsBundle(): Promise<string> {\n const thisDir = dirname(fileURLToPath(import.meta.url));\n const builtPath = join(thisDir, \"browser/index.js\");\n const devPath = join(thisDir, \"../../dist/browser/index.js\");\n try {\n return await readFile(builtPath, \"utf-8\");\n } catch {}\n return readFile(devPath, \"utf-8\");\n}\n\n/** Write an index.html in the parent dir that redirects to this report */\nasync function writeLatestRedirect(reportDir: string): Promise<void> {\n const baseDir = dirname(reportDir);\n const reportName = reportDir.split(\"/\").pop();\n const html = `<!DOCTYPE html>\n<html><head>\n <meta http-equiv=\"refresh\" content=\"0; url=./${reportName}/\">\n <script>location.href = \"./${reportName}/\";</script>\n</head><body>\n <a href=\"./${reportName}/\">Latest report</a>\n</body></html>`;\n await writeFile(join(baseDir, \"index.html\"), html, \"utf-8\");\n}\n\n/** Start HTTP server for report directory, trying fallback ports if needed */\nasync function startReportServer(\n baseDir: string,\n ...ports: number[]\n): Promise<{ server: Server; port: number }> {\n const mimeTypes: Record<string, string> = {\n \".html\": \"text/html\",\n \".js\": \"application/javascript\",\n \".css\": \"text/css\",\n \".json\": \"application/json\",\n };\n\n const server = createServer(async (req, res) => {\n const url = req.url || \"/\";\n const suffix = url.endsWith(\"/\") ? url + \"index.html\" : url;\n const filePath = join(baseDir, suffix);\n try {\n const content = await readFile(filePath);\n const mime = mimeTypes[extname(filePath)] || \"application/octet-stream\";\n res.setHeader(\"Content-Type\", mime);\n res.end(content);\n } catch {\n res.statusCode = 404;\n res.end(\"Not found\");\n }\n });\n\n for (const port of ports) {\n try {\n return await tryListen(server, port);\n } catch {\n // Port in use, try next\n }\n }\n return tryListen(server, 0);\n}\n\n/** Listen on a port, resolving with the actual port or rejecting on error */\nfunction tryListen(\n server: Server,\n port: number,\n): Promise<{ server: Server; port: number }> {\n return new Promise((resolve, reject) => {\n server.once(\"error\", reject);\n server.listen(port, () => {\n server.removeListener(\"error\", reject);\n const addr = server.address();\n const actualPort = typeof addr === \"object\" && addr ? addr.port : port;\n resolve({ server, port: actualPort });\n });\n });\n}\n","import type { BenchMatrix } from \"../BenchMatrix.ts\";\nimport { loadCasesModule } from \"./CaseLoader.ts\";\nimport { discoverVariants } from \"./VariantLoader.ts\";\n\n/** Filter for matrix case/variant selection */\nexport interface MatrixFilter {\n case?: string;\n variant?: string;\n}\n\n/** Filtered matrix with explicit case and variant lists */\nexport interface FilteredMatrix<T = unknown> extends BenchMatrix<T> {\n filteredCases?: string[];\n filteredVariants?: string[];\n}\n\n/** Parse filter string: \"case/variant\", \"case/\", \"/variant\", or \"case\" */\nexport function parseMatrixFilter(filter: string): MatrixFilter {\n if (filter.includes(\"/\")) {\n const [casePart, variantPart] = filter.split(\"/\", 2);\n return {\n case: casePart || undefined,\n variant: variantPart || undefined,\n };\n }\n return { case: filter };\n}\n\n/** Apply filter to a matrix, merging with existing filters via intersection */\nexport async function filterMatrix<T>(\n matrix: FilteredMatrix<T>,\n filter?: MatrixFilter,\n): Promise<FilteredMatrix<T>> {\n if (!filter || (!filter.case && !filter.variant)) return matrix;\n\n const caseList = await getFilteredCases(matrix, filter.case);\n const variantList = await getFilteredVariants(matrix, filter.variant);\n\n const filteredCases =\n caseList && matrix.filteredCases\n ? caseList.filter(c => matrix.filteredCases!.includes(c))\n : (caseList ?? matrix.filteredCases);\n\n const filteredVariants =\n variantList && matrix.filteredVariants\n ? variantList.filter(v => matrix.filteredVariants!.includes(v))\n : (variantList ?? matrix.filteredVariants);\n\n return { ...matrix, filteredCases, filteredVariants };\n}\n\n/** Get case IDs matching filter pattern */\nasync function getFilteredCases<T>(\n matrix: BenchMatrix<T>,\n casePattern?: string,\n): Promise<string[] | undefined> {\n if (!casePattern) return undefined;\n\n const caseIds = matrix.casesModule\n ? (await loadCasesModule(matrix.casesModule)).cases\n : matrix.cases;\n if (!caseIds) return [\"default\"]; // implicit single case\n\n const filtered = caseIds.filter(id => matchPattern(id, casePattern));\n if (filtered.length === 0) {\n throw new Error(`No cases match filter: \"${casePattern}\"`);\n }\n return filtered;\n}\n\n/** Get variant IDs matching filter pattern */\nasync function getFilteredVariants<T>(\n matrix: BenchMatrix<T>,\n variantPattern?: string,\n): Promise<string[] | undefined> {\n if (!variantPattern) return undefined;\n\n if (matrix.variants) {\n const ids = Object.keys(matrix.variants).filter(id =>\n matchPattern(id, variantPattern),\n );\n if (ids.length === 0) {\n throw new Error(`No variants match filter: \"${variantPattern}\"`);\n }\n return ids;\n }\n\n if (matrix.variantDir) {\n const allIds = await discoverVariants(matrix.variantDir);\n const filtered = allIds.filter(id => matchPattern(id, variantPattern));\n if (filtered.length === 0) {\n throw new Error(`No variants match filter: \"${variantPattern}\"`);\n }\n return filtered;\n }\n\n throw new Error(\"BenchMatrix requires 'variants' or 'variantDir'\");\n}\n\n/** Match id against pattern (case-insensitive substring) */\nfunction matchPattern(id: string, pattern: string): boolean {\n return id.toLowerCase().includes(pattern.toLowerCase());\n}\n","import pico from \"picocolors\";\n\nconst isTest = process.env.NODE_ENV === \"test\" || process.env.VITEST === \"true\";\nconst { red } = isTest ? { red: (str: string) => str } : pico;\n\nconst lowConfidence = 80;\n\n/** @return convergence percentage with color for low values */\nexport function formatConvergence(v: unknown): string {\n if (typeof v !== \"number\") return \"—\";\n const pct = `${Math.round(v)}%`;\n return v < lowConfidence ? red(pct) : pct;\n}\n\n/** @return coefficient of variation as ±percentage */\nexport function formatCV(v: unknown): string {\n if (typeof v !== \"number\") return \"\";\n return `±${(v * 100).toFixed(1)}%`;\n}\n","import type { ReportColumnGroup, ResultsMapper } from \"./BenchmarkReport.ts\";\nimport type { MeasuredResults } from \"./MeasuredResults.ts\";\nimport { formatConvergence } from \"./table-util/ConvergenceFormatters.ts\";\nimport {\n formatBytes,\n integer,\n percent,\n percentPrecision,\n timeMs,\n} from \"./table-util/Formatters.ts\";\n\nexport interface TimeStats {\n mean?: number;\n p50?: number;\n p99?: number;\n}\n\nexport interface GcSectionStats {\n gc?: number; // GC time as fraction of total bench time\n}\n\nexport interface GcStatsInfo {\n allocPerIter?: number;\n collected?: number;\n scavenges?: number;\n fullGCs?: number;\n promoPercent?: number;\n pausePerIter?: number;\n}\n\nexport interface CpuStats {\n cpuCacheMiss?: number;\n cpuStall?: number;\n}\n\nexport interface RunStats {\n runs?: number;\n}\n\nexport interface AdaptiveStats {\n median?: number;\n mean?: number;\n p99?: number;\n convergence?: number;\n}\n\nexport interface OptStats {\n tiers?: string; // tier distribution summary\n deopt?: number; // deopt count\n}\n\n/** Section: mean, p50, p99 timing */\nexport const timeSection: ResultsMapper<TimeStats> = {\n extract: (results: MeasuredResults) => ({\n mean: results.time?.avg,\n p50: results.time?.p50,\n p99: results.time?.p99,\n }),\n columns: (): ReportColumnGroup<TimeStats>[] => [\n {\n groupTitle: \"time\",\n columns: [\n { key: \"mean\", title: \"mean\", formatter: timeMs, comparable: true },\n { key: \"p50\", title: \"p50\", formatter: timeMs, comparable: true },\n { key: \"p99\", title: \"p99\", formatter: timeMs, comparable: true },\n ],\n },\n ],\n};\n\n/** Section: GC time as fraction of total benchmark time (Node performance hooks) */\nexport const gcSection: ResultsMapper<GcSectionStats> = {\n extract: (results: MeasuredResults) => {\n const { nodeGcTime, time, samples } = results;\n if (!nodeGcTime || !time?.avg) return { gc: undefined };\n const totalBenchTime = time.avg * samples.length;\n if (totalBenchTime <= 0) return { gc: undefined };\n const gcTime = nodeGcTime.inRun / totalBenchTime;\n // GC time can't exceed total time\n return { gc: gcTime <= 1 ? gcTime : undefined };\n },\n columns: (): ReportColumnGroup<GcSectionStats>[] => [\n {\n groupTitle: \"gc\",\n columns: [\n { key: \"gc\", title: \"mean\", formatter: percent, comparable: true },\n ],\n },\n ],\n};\n\n/** Section: detailed GC stats from --trace-gc-nvp (allocation, promotion, pauses) */\nexport const gcStatsSection: ResultsMapper<GcStatsInfo> = {\n extract: (results: MeasuredResults) => {\n const { gcStats, samples } = results;\n if (!gcStats) return {};\n const iterations = samples.length || 1;\n const { totalAllocated, totalPromoted } = gcStats;\n const hasAlloc = totalAllocated && totalAllocated > 0;\n const promoPercent = hasAlloc\n ? (totalPromoted ?? 0) / totalAllocated\n : undefined;\n return {\n allocPerIter:\n totalAllocated != null ? totalAllocated / iterations : undefined,\n collected: gcStats.totalCollected || undefined,\n scavenges: gcStats.scavenges,\n fullGCs: gcStats.markCompacts,\n promoPercent,\n pausePerIter: gcStats.gcPauseTime / iterations,\n };\n },\n columns: (): ReportColumnGroup<GcStatsInfo>[] => [\n {\n groupTitle: \"gc\",\n columns: [\n { key: \"allocPerIter\", title: \"alloc/iter\", formatter: formatBytes },\n { key: \"collected\", title: \"collected\", formatter: formatBytes },\n { key: \"scavenges\", title: \"scav\", formatter: integer },\n { key: \"fullGCs\", title: \"full\", formatter: integer },\n { key: \"promoPercent\", title: \"promo%\", formatter: percent },\n { key: \"pausePerIter\", title: \"pause/iter\", formatter: timeMs },\n ],\n },\n ],\n};\n\n/** Browser GC section: only fields available from CDP tracing */\nexport const browserGcStatsSection: ResultsMapper<GcStatsInfo> = {\n extract: gcStatsSection.extract,\n columns: (): ReportColumnGroup<GcStatsInfo>[] => [\n {\n groupTitle: \"gc\",\n columns: [\n { key: \"collected\", title: \"collected\", formatter: formatBytes },\n { key: \"scavenges\", title: \"scav\", formatter: integer },\n { key: \"fullGCs\", title: \"full\", formatter: integer },\n { key: \"pausePerIter\", title: \"pause\", formatter: timeMs },\n ],\n },\n ],\n};\n\n/** Section: CPU L1 cache miss rate and stall rate (requires @mitata/counters) */\nexport const cpuSection: ResultsMapper<CpuStats> = {\n extract: (results: MeasuredResults) => ({\n cpuCacheMiss: results.cpuCacheMiss,\n cpuStall: results.cpuStall,\n }),\n columns: (): ReportColumnGroup<CpuStats>[] => [\n {\n groupTitle: \"cpu\",\n columns: [\n { key: \"cpuCacheMiss\", title: \"L1 miss\", formatter: percent },\n { key: \"cpuStall\", title: \"stalls\", formatter: percentPrecision(2) },\n ],\n },\n ],\n};\n\n/** Section: number of sample iterations */\nexport const runsSection: ResultsMapper<RunStats> = {\n extract: (results: MeasuredResults) => ({\n runs: results.samples.length,\n }),\n columns: (): ReportColumnGroup<RunStats>[] => [\n { columns: [{ key: \"runs\", title: \"runs\", formatter: integer }] },\n ],\n};\n\n/** Section: total sampling duration in seconds (brackets if >= 30s) */\nexport const totalTimeSection: ResultsMapper<{ totalTime?: number }> = {\n extract: (results: MeasuredResults) => ({\n totalTime: results.totalTime,\n }),\n columns: (): ReportColumnGroup<{ totalTime?: number }>[] => [\n {\n columns: [\n {\n key: \"totalTime\",\n title: \"time\",\n formatter: v => {\n if (typeof v !== \"number\") return \"\";\n return v >= 30 ? `[${v.toFixed(1)}s]` : `${v.toFixed(1)}s`;\n },\n },\n ],\n },\n ],\n};\n\n/** Section: median, mean, p99, and convergence for adaptive mode */\nexport const adaptiveSection: ResultsMapper<AdaptiveStats> = {\n extract: (results: MeasuredResults) => ({\n median: results.time?.p50,\n mean: results.time?.avg,\n p99: results.time?.p99,\n convergence: results.convergence?.confidence,\n }),\n columns: (): ReportColumnGroup<AdaptiveStats>[] => [\n {\n groupTitle: \"time\",\n columns: [\n { key: \"median\", title: \"median\", formatter: timeMs, comparable: true },\n { key: \"mean\", title: \"mean\", formatter: timeMs, comparable: true },\n { key: \"p99\", title: \"p99\", formatter: timeMs },\n ],\n },\n {\n columns: [\n { key: \"convergence\", title: \"conv%\", formatter: formatConvergence },\n ],\n },\n ],\n};\n\n/** Section: V8 optimization tier distribution and deopt count */\nexport const optSection: ResultsMapper<OptStats> = {\n extract: (results: MeasuredResults) => {\n const opt = results.optStatus;\n if (!opt) return {};\n\n const total = Object.values(opt.byTier).reduce((s, t) => s + t.count, 0);\n const tierParts = Object.entries(opt.byTier)\n .sort((a, b) => b[1].count - a[1].count)\n .map(([name, t]) => `${name}:${((t.count / total) * 100).toFixed(0)}%`);\n\n return {\n tiers: tierParts.join(\" \"),\n deopt: opt.deoptCount > 0 ? opt.deoptCount : undefined,\n };\n },\n columns: (): ReportColumnGroup<OptStats>[] => [\n {\n groupTitle: \"v8 opt\",\n columns: [\n {\n key: \"tiers\",\n title: \"tiers\",\n formatter: v => (typeof v === \"string\" ? v : \"\"),\n },\n {\n key: \"deopt\",\n title: \"deopt\",\n formatter: v => (typeof v === \"number\" ? String(v) : \"\"),\n },\n ],\n },\n ],\n};\n\n/** Build generic sections based on CLI flags */\nexport function buildGenericSections(args: {\n \"gc-stats\"?: boolean;\n \"heap-sample\"?: boolean;\n}): ResultsMapper[] {\n const sections: ResultsMapper[] = [];\n if (args[\"gc-stats\"]) sections.push(gcStatsSection);\n sections.push(runsSection);\n return sections;\n}\n","import type { CaseResult, MatrixResults } from \"../BenchMatrix.ts\";\nimport { injectDiffColumns, type ResultsMapper } from \"../BenchmarkReport.ts\";\nimport { totalProfileBytes } from \"../heap-sample/HeapSampleReport.ts\";\nimport { type GcStatsInfo, gcStatsSection } from \"../StandardSections.ts\";\nimport {\n average,\n bootstrapDifferenceCI,\n type DifferenceCI,\n} from \"../StatisticalUtils.ts\";\nimport {\n duration,\n formatBytes,\n formatDiffWithCI,\n truncate,\n} from \"../table-util/Formatters.ts\";\nimport {\n buildTable,\n type ColumnGroup,\n type ResultGroup,\n} from \"../table-util/TableReport.ts\";\n\n/** Custom column definition for extra computed metrics */\nexport interface ExtraColumn {\n key: string;\n title: string;\n groupTitle?: string; // optional column group header\n extract: (caseResult: CaseResult) => unknown;\n formatter?: (value: unknown) => string;\n}\n\n/** Options for matrix report generation */\nexport interface MatrixReportOptions {\n extraColumns?: ExtraColumn[];\n sections?: ResultsMapper[]; // ResultsMapper sections (like BenchSuite)\n variantTitle?: string; // custom title for the variant column (default: \"variant\")\n}\n\n/** Row data for matrix report table */\ninterface MatrixReportRow extends Record<string, unknown> {\n name: string;\n time: number;\n samples: number;\n diffCI?: DifferenceCI;\n}\n\n/** GC statistics columns - derived from gcStatsSection for consistency */\nexport const gcStatsColumns: ExtraColumn[] = gcStatsSection\n .columns()[0]\n .columns.map(col => ({\n key: col.key as string,\n title: col.title,\n groupTitle: \"GC\",\n extract: (r: CaseResult) =>\n gcStatsSection.extract(r.measured)[col.key as keyof GcStatsInfo],\n formatter: (v: unknown) => col.formatter?.(v) ?? \"-\",\n }));\n\n/** GC pause time column */\nexport const gcPauseColumn: ExtraColumn = {\n key: \"gcPause\",\n title: \"pause\",\n groupTitle: \"GC\",\n extract: r => r.measured.gcStats?.gcPauseTime,\n formatter: v => (v != null ? `${(v as number).toFixed(1)}ms` : \"-\"),\n};\n\n/** Heap sampling total bytes column */\nexport const heapTotalColumn: ExtraColumn = {\n key: \"heapTotal\",\n title: \"heap\",\n extract: r => {\n const profile = r.measured.heapProfile;\n if (!profile?.head) return undefined;\n return totalProfileBytes(profile);\n },\n formatter: formatBytesOrDash,\n};\n\n/** Format matrix results as one table per case */\nexport function reportMatrixResults(\n results: MatrixResults,\n options?: MatrixReportOptions,\n): string {\n const tables = buildCaseTables(results, options);\n const header = `Matrix: ${results.name}`;\n return [header, ...tables].join(\"\\n\\n\");\n}\n\n/** Format bytes with fallback to \"-\" for missing values */\nfunction formatBytesOrDash(value: unknown): string {\n return formatBytes(value) ?? \"-\";\n}\n\n/** Build one table for each case showing all variants */\nfunction buildCaseTables(\n results: MatrixResults,\n options?: MatrixReportOptions,\n): string[] {\n if (results.variants.length === 0) return [];\n\n // Get all case IDs from first variant (all variants have same cases)\n const caseIds = results.variants[0].cases.map(c => c.caseId);\n return caseIds.map(caseId => buildCaseTable(results, caseId, options));\n}\n\n/** Build table for a single case showing all variants */\nfunction buildCaseTable(\n results: MatrixResults,\n caseId: string,\n options?: MatrixReportOptions,\n): string {\n const caseTitle = formatCaseTitle(results, caseId);\n\n if (options?.sections?.length) {\n return buildSectionTable(results, caseId, options, caseTitle);\n }\n\n const rows = buildCaseRows(results, caseId, options?.extraColumns);\n const hasBaseline = rows.some(r => r.diffCI);\n const columns = buildColumns(hasBaseline, options);\n\n const resultGroup: ResultGroup<MatrixReportRow> = { results: rows };\n const table = buildTable(columns, [resultGroup]);\n return `${caseTitle}\\n${table}`;\n}\n\n/** Format case title with metadata if available */\nfunction formatCaseTitle(results: MatrixResults, caseId: string): string {\n const caseResult = results.variants[0]?.cases.find(c => c.caseId === caseId);\n const metadata = caseResult?.metadata;\n\n if (metadata && Object.keys(metadata).length > 0) {\n const metaParts = Object.entries(metadata)\n .map(([k, v]) => `${v} ${k}`)\n .join(\", \");\n return `${caseId} (${metaParts})`;\n }\n return caseId;\n}\n\n/** Build table using ResultsMapper sections */\nfunction buildSectionTable(\n results: MatrixResults,\n caseId: string,\n options: MatrixReportOptions,\n caseTitle: string,\n): string {\n const sections = options.sections!;\n const variantTitle = options.variantTitle ?? \"name\";\n\n const rows: Record<string, unknown>[] = [];\n let hasBaseline = false;\n\n for (const variant of results.variants) {\n const caseResult = variant.cases.find(c => c.caseId === caseId);\n if (!caseResult) continue;\n\n const row: Record<string, unknown> = { name: truncate(variant.id, 25) };\n\n for (const section of sections) {\n Object.assign(\n row,\n section.extract(caseResult.measured, caseResult.metadata),\n );\n }\n\n if (caseResult.baseline) {\n hasBaseline = true;\n const { samples: base } = caseResult.baseline;\n row.diffCI = bootstrapDifferenceCI(base, caseResult.measured.samples);\n }\n\n rows.push(row);\n }\n\n const columnGroups = buildSectionColumns(sections, variantTitle, hasBaseline);\n const resultGroup: ResultGroup<Record<string, unknown>> = { results: rows };\n const table = buildTable(columnGroups, [resultGroup]);\n return `${caseTitle}\\n${table}`;\n}\n\n/** Build rows for all variants for a given case */\nfunction buildCaseRows(\n results: MatrixResults,\n caseId: string,\n extraColumns?: ExtraColumn[],\n): MatrixReportRow[] {\n return results.variants.flatMap(variant => {\n const caseResult = variant.cases.find(c => c.caseId === caseId);\n return caseResult ? [buildRow(variant.id, caseResult, extraColumns)] : [];\n });\n}\n\n/** Build column configuration */\nfunction buildColumns(\n hasBaseline: boolean,\n options?: MatrixReportOptions,\n): ColumnGroup<MatrixReportRow>[] {\n const variantTitle = options?.variantTitle ?? \"variant\";\n const nameCol: ColumnGroup<MatrixReportRow> = {\n columns: [{ key: \"name\", title: variantTitle }],\n };\n\n const ciKey = \"diffCI\" as keyof MatrixReportRow;\n const diffCol = { key: ciKey, title: \"Δ% CI\", formatter: formatDiff };\n const timeCol: ColumnGroup<MatrixReportRow> = {\n columns: [\n { key: \"time\", title: \"time\", formatter: duration },\n ...(hasBaseline ? [diffCol] : []),\n ],\n };\n\n const groups: ColumnGroup<MatrixReportRow>[] = [nameCol, timeCol];\n\n // Add extra columns, grouped by groupTitle\n const extraColumns = options?.extraColumns;\n if (extraColumns?.length) {\n const byGroup = new Map<string | undefined, ExtraColumn[]>();\n for (const col of extraColumns) {\n const group = byGroup.get(col.groupTitle) ?? [];\n group.push(col);\n byGroup.set(col.groupTitle, group);\n }\n for (const [groupTitle, cols] of byGroup) {\n groups.push({\n groupTitle,\n columns: cols.map(col => ({\n key: col.key as keyof MatrixReportRow,\n title: col.title,\n formatter: col.formatter ?? String,\n })),\n });\n }\n }\n\n return groups;\n}\n\n/** Build column groups from ResultsMapper sections */\nfunction buildSectionColumns(\n sections: ResultsMapper[],\n variantTitle: string,\n hasBaseline: boolean,\n): ColumnGroup<Record<string, unknown>>[] {\n const nameCol: ColumnGroup<Record<string, unknown>> = {\n columns: [{ key: \"name\", title: variantTitle }],\n };\n\n const sectionColumns = sections.flatMap(s => s.columns());\n const columnGroups = hasBaseline\n ? injectDiffColumns(sectionColumns)\n : (sectionColumns as ColumnGroup<Record<string, unknown>>[]);\n\n return [nameCol, ...columnGroups];\n}\n\n/** Build a single row from case result */\nfunction buildRow(\n variantId: string,\n caseResult: CaseResult,\n extraColumns?: ExtraColumn[],\n): MatrixReportRow {\n const { measured, baseline } = caseResult;\n const samples = measured.samples;\n const time = measured.time?.avg ?? average(samples);\n\n const row: MatrixReportRow = {\n name: truncate(variantId, 25),\n time,\n samples: samples.length,\n };\n\n if (baseline) {\n row.diffCI = bootstrapDifferenceCI(baseline.samples, samples);\n }\n\n if (extraColumns) {\n for (const col of extraColumns) {\n row[col.key] = col.extract(caseResult);\n }\n }\n\n return row;\n}\n\n/** Format diff with CI, or \"baseline\" marker */\nfunction formatDiff(value: unknown): string | null {\n if (!value) return null;\n return formatDiffWithCI(value as DifferenceCI);\n}\n","import type { BenchGroup, BenchSuite } from \"../Benchmark.ts\";\n\n/** Filter benchmarks by name pattern */\nexport function filterBenchmarks(\n suite: BenchSuite,\n filter?: string,\n removeEmpty = true,\n): BenchSuite {\n if (!filter) return suite;\n const regex = createFilterRegex(filter);\n const groups = suite.groups\n .map(group => ({\n ...group,\n benchmarks: group.benchmarks.filter(bench =>\n regex.test(stripCaseSuffix(bench.name)),\n ),\n baseline:\n group.baseline && regex.test(stripCaseSuffix(group.baseline.name))\n ? group.baseline\n : undefined,\n }))\n .filter(group => !removeEmpty || group.benchmarks.length > 0);\n validateFilteredSuite(groups, filter);\n return { name: suite.name, groups };\n}\n\n/** Create regex from filter (literal unless regex-like) */\nfunction createFilterRegex(filter: string): RegExp {\n const looksLikeRegex =\n (filter.startsWith(\"/\") && filter.endsWith(\"/\")) ||\n filter.includes(\"*\") ||\n filter.includes(\"?\") ||\n filter.includes(\"[\") ||\n filter.includes(\"|\") ||\n filter.startsWith(\"^\") ||\n filter.endsWith(\"$\");\n\n if (looksLikeRegex) {\n const pattern =\n filter.startsWith(\"/\") && filter.endsWith(\"/\")\n ? filter.slice(1, -1)\n : filter;\n try {\n return new RegExp(pattern, \"i\");\n } catch {\n return new RegExp(escapeRegex(filter), \"i\");\n }\n }\n\n return new RegExp(\"^\" + escapeRegex(filter), \"i\");\n}\n\n/** Strip case suffix like \" [large]\" from benchmark name for filtering */\nfunction stripCaseSuffix(name: string): string {\n return name.replace(/ \\[.*?\\]$/, \"\");\n}\n\n/** Ensure at least one benchmark matches filter */\nfunction validateFilteredSuite(groups: BenchGroup[], filter?: string): void {\n if (groups.every(g => g.benchmarks.length === 0)) {\n throw new Error(`No benchmarks match filter: \"${filter}\"`);\n }\n}\n\n/** Escape regex special characters */\nfunction escapeRegex(str: string): string {\n return str.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n}\n","import { basename, resolve } from \"node:path\";\nimport { pathToFileURL } from \"node:url\";\nimport pico from \"picocolors\";\nimport { hideBin } from \"yargs/helpers\";\nimport type {\n MatrixResults,\n MatrixSuite,\n RunMatrixOptions,\n} from \"../BenchMatrix.ts\";\nimport { runMatrix } from \"../BenchMatrix.ts\";\nimport type { BenchGroup, BenchmarkSpec, BenchSuite } from \"../Benchmark.ts\";\nimport type {\n BenchmarkReport,\n ReportGroup,\n ResultsMapper,\n} from \"../BenchmarkReport.ts\";\nimport { groupReports, reportResults } from \"../BenchmarkReport.ts\";\nimport type { BrowserProfileResult } from \"../browser/BrowserHeapSampler.ts\";\nimport { exportBenchmarkJson } from \"../export/JsonExport.ts\";\nimport { exportPerfettoTrace } from \"../export/PerfettoExport.ts\";\nimport {\n exportAndLaunchSpeedscope,\n exportSpeedscope,\n} from \"../export/SpeedscopeExport.ts\";\nimport type { GitVersion } from \"../GitUtils.ts\";\nimport { prepareHtmlData } from \"../HtmlDataPrep.ts\";\nimport {\n aggregateSites,\n filterSites,\n flattenProfile,\n formatHeapReport,\n formatRawSamples,\n type HeapReportOptions,\n isBrowserUserCode,\n} from \"../heap-sample/HeapSampleReport.ts\";\nimport { resolveProfile } from \"../heap-sample/ResolvedProfile.ts\";\nimport { generateHtmlReport } from \"../html/index.ts\";\nimport type { MeasuredResults } from \"../MeasuredResults.ts\";\nimport { loadCasesModule } from \"../matrix/CaseLoader.ts\";\nimport {\n type FilteredMatrix,\n filterMatrix,\n parseMatrixFilter,\n} from \"../matrix/MatrixFilter.ts\";\nimport {\n type MatrixReportOptions,\n reportMatrixResults,\n} from \"../matrix/MatrixReport.ts\";\nimport { computeStats } from \"../runners/BasicRunner.ts\";\nimport type { RunnerOptions } from \"../runners/BenchRunner.ts\";\nimport type { KnownRunner } from \"../runners/CreateRunner.ts\";\nimport { runBenchmark } from \"../runners/RunnerOrchestrator.ts\";\nimport {\n adaptiveSection,\n browserGcStatsSection,\n cpuSection,\n gcStatsSection,\n optSection,\n runsSection,\n timeSection,\n totalTimeSection,\n} from \"../StandardSections.ts\";\nimport {\n type Configure,\n type DefaultCliArgs,\n defaultAdaptiveMaxTime,\n parseCliArgs,\n} from \"./CliArgs.ts\";\nimport { filterBenchmarks } from \"./FilterBenchmarks.ts\";\n\nexport interface ExportOptions {\n results: ReportGroup[];\n args: DefaultCliArgs;\n sections?: any[];\n suiteName?: string;\n currentVersion?: GitVersion;\n baselineVersion?: GitVersion;\n}\n\nexport interface MatrixExportOptions {\n sections?: any[];\n currentVersion?: GitVersion;\n baselineVersion?: GitVersion;\n}\n\ntype RunParams = {\n runner: KnownRunner;\n options: RunnerOptions;\n useWorker: boolean;\n params: unknown;\n metadata?: Record<string, any>;\n};\n\ntype SuiteParams = {\n runner: KnownRunner;\n options: RunnerOptions;\n useWorker: boolean;\n suite: BenchSuite;\n batches: number;\n};\n\nconst isTest = process.env.NODE_ENV === \"test\" || process.env.VITEST === \"true\";\nconst { yellow, dim } = isTest\n ? { yellow: (s: string) => s, dim: (s: string) => s }\n : pico;\n\n/** Parse CLI with custom configuration */\nexport function parseBenchArgs<T = DefaultCliArgs>(\n configureArgs?: Configure<T>,\n): T & DefaultCliArgs {\n const argv = hideBin(process.argv);\n return parseCliArgs(argv, configureArgs) as T & DefaultCliArgs;\n}\n\n/** Run suite with CLI arguments */\nexport async function runBenchmarks(\n suite: BenchSuite,\n args: DefaultCliArgs,\n): Promise<ReportGroup[]> {\n validateArgs(args);\n const { filter, worker: useWorker, batches = 1 } = args;\n const options = cliToRunnerOptions(args);\n const filtered = filterBenchmarks(suite, filter);\n\n return runSuite({\n suite: filtered,\n runner: \"basic\",\n options,\n useWorker,\n batches,\n });\n}\n\n/** Generate table with standard sections */\nexport function defaultReport(\n groups: ReportGroup[],\n args: DefaultCliArgs,\n): string {\n const { adaptive, \"gc-stats\": gcStats, \"trace-opt\": traceOpt } = args;\n const hasCpu = hasField(groups, \"cpu\");\n const hasOpt = hasField(groups, \"optStatus\");\n const sections = buildReportSections(\n adaptive,\n gcStats,\n hasCpu,\n traceOpt && hasOpt,\n );\n return reportResults(groups, sections);\n}\n\n/** Run benchmarks, display table, and optionally generate HTML report */\nexport async function benchExports(\n suite: BenchSuite,\n args: DefaultCliArgs,\n): Promise<void> {\n const results = await runBenchmarks(suite, args);\n const report = defaultReport(results, args);\n console.log(report);\n await finishReports(results, args, suite.name);\n}\n\n/** Run browser profiling via Playwright + CDP, report with standard pipeline */\nexport async function browserBenchExports(args: DefaultCliArgs): Promise<void> {\n warnBrowserFlags(args);\n\n let profileBrowser: typeof import(\"../browser/BrowserHeapSampler.ts\").profileBrowser;\n try {\n ({ profileBrowser } = await import(\"../browser/BrowserHeapSampler.ts\"));\n } catch {\n throw new Error(\n \"playwright is required for browser benchmarking (--url).\\n\\n\" +\n \"Quick start: npx benchforge-browser --url <your-url>\\n\\n\" +\n \"Or install manually:\\n\" +\n \" npm install playwright\\n\" +\n \" npx playwright install chromium\",\n );\n }\n\n const url = args.url!;\n const { iterations, time } = args;\n const result = await profileBrowser({\n url,\n heapSample: needsHeapSample(args),\n heapOptions: {\n samplingInterval: args[\"heap-interval\"],\n stackDepth: args[\"heap-depth\"],\n },\n headless: args.headless,\n chromeArgs: args[\"chrome-args\"]\n ?.flatMap(a => a.split(/\\s+/))\n .map(stripQuotes)\n .filter(Boolean),\n timeout: args.timeout,\n gcStats: args[\"gc-stats\"],\n maxTime: iterations ? Number.MAX_SAFE_INTEGER : time * 1000,\n maxIterations: iterations,\n });\n\n const name = new URL(url).pathname.split(\"/\").pop() || \"browser\";\n const results = browserResultGroups(name, result);\n printBrowserReport(result, results, args);\n await exportReports({ results, args });\n}\n\n/** Print heap allocation reports for benchmarks with heap profiles */\nexport function printHeapReports(\n groups: ReportGroup[],\n options: HeapReportOptions,\n): void {\n for (const group of groups) {\n for (const report of groupReports(group)) {\n const { heapProfile } = report.measuredResults;\n if (!heapProfile) continue;\n\n console.log(dim(`\\n─── Heap profile: ${report.name} ───`));\n const resolved = resolveProfile(heapProfile);\n const sites = flattenProfile(resolved);\n const userSites = filterSites(sites, options.isUserCode);\n const totalUserCode = userSites.reduce((sum, s) => sum + s.bytes, 0);\n const aggregated = aggregateSites(options.userOnly ? userSites : sites);\n const extra = {\n totalAll: resolved.totalBytes,\n totalUserCode,\n sampleCount: resolved.sortedSamples?.length,\n };\n console.log(formatHeapReport(aggregated, { ...options, ...extra }));\n if (options.raw) {\n console.log(dim(`\\n─── Raw samples: ${report.name} ───`));\n console.log(formatRawSamples(resolved));\n }\n }\n }\n}\n\n/** Run benchmarks and display table. Suite is optional with --url (browser mode). */\nexport async function runDefaultBench(\n suite?: BenchSuite,\n configureArgs?: Configure<any>,\n): Promise<void> {\n const args = parseBenchArgs(configureArgs);\n if (args.url) {\n await browserBenchExports(args);\n } else if (suite) {\n await benchExports(suite, args);\n } else if (args.file) {\n await fileBenchExports(args.file, args);\n } else {\n throw new Error(\n \"Provide a benchmark file, --url for browser mode, or pass a BenchSuite directly.\",\n );\n }\n}\n\n/** Convert CLI args to runner options */\nexport function cliToRunnerOptions(args: DefaultCliArgs): RunnerOptions {\n const { profile, collect, iterations } = args;\n if (profile)\n return { maxIterations: iterations ?? 1, warmupTime: 0, collect };\n if (args.adaptive) return createAdaptiveOptions(args);\n\n return {\n maxTime: iterations ? Number.POSITIVE_INFINITY : args.time * 1000,\n maxIterations: iterations,\n ...cliCommonOptions(args),\n };\n}\n\n/** Log V8 optimization tier distribution and deoptimizations */\nexport function reportOptStatus(groups: ReportGroup[]): void {\n const optData = groups.flatMap(group => {\n return groupReports(group)\n .filter(r => r.measuredResults.optStatus)\n .map(r => ({\n name: r.name,\n opt: r.measuredResults.optStatus!,\n samples: r.measuredResults.samples.length,\n }));\n });\n if (optData.length === 0) return;\n\n console.log(dim(\"\\nV8 optimization:\"));\n for (const { name, opt, samples } of optData) {\n const total = Object.values(opt.byTier).reduce((s, t) => s + t.count, 0);\n const tierParts = Object.entries(opt.byTier)\n .sort((a, b) => b[1].count - a[1].count)\n .map(\n ([tier, info]) => `${tier} ${((info.count / total) * 100).toFixed(0)}%`,\n )\n .join(\", \");\n console.log(` ${name}: ${tierParts} ${dim(`(${samples} samples)`)}`);\n }\n\n const totalDeopts = optData.reduce((s, d) => s + d.opt.deoptCount, 0);\n if (totalDeopts > 0) {\n console.log(\n yellow(\n ` ⚠ ${totalDeopts} deoptimization${totalDeopts > 1 ? \"s\" : \"\"} detected`,\n ),\n );\n }\n}\n\n/** @return true if any result has the specified field with a defined value */\nexport function hasField(\n results: ReportGroup[],\n field: keyof MeasuredResults,\n): boolean {\n return results.some(group =>\n groupReports(group).some(\n ({ measuredResults }) => measuredResults[field] !== undefined,\n ),\n );\n}\n\n/** Export reports (HTML, JSON, Perfetto) based on CLI args */\nexport async function exportReports(options: ExportOptions): Promise<void> {\n const { results, args, sections, suiteName } = options;\n const { currentVersion, baselineVersion } = options;\n const openInBrowser = args.html && !args[\"export-html\"];\n let closeServer: (() => void) | undefined;\n\n if (args.html || args[\"export-html\"]) {\n const htmlOpts = {\n cliArgs: args,\n sections,\n currentVersion,\n baselineVersion,\n };\n const reportData = prepareHtmlData(results, htmlOpts);\n const result = await generateHtmlReport(reportData, {\n openBrowser: openInBrowser,\n outputPath: args[\"export-html\"],\n });\n closeServer = result.closeServer;\n }\n\n if (args.json) {\n await exportBenchmarkJson(results, args.json, args, suiteName);\n }\n\n if (args[\"export-perfetto\"]) {\n exportPerfettoTrace(results, args[\"export-perfetto\"], args);\n }\n\n if (args[\"export-speedscope\"]) {\n exportSpeedscope(results, args[\"export-speedscope\"]);\n }\n\n if (args.speedscope) {\n exportAndLaunchSpeedscope(results);\n }\n\n // Keep process running when HTML report is opened in browser\n if (openInBrowser) {\n await waitForCtrlC();\n closeServer?.();\n }\n}\n\n/** Run matrix suite with CLI arguments.\n * no options ==> defaultCases/defaultVariants, --filter ==> subset of defaults,\n * --all --filter ==> subset of all, --all ==> all cases/variants */\nexport async function runMatrixSuite(\n suite: MatrixSuite,\n args: DefaultCliArgs,\n): Promise<MatrixResults[]> {\n validateArgs(args);\n const filter = args.filter ? parseMatrixFilter(args.filter) : undefined;\n const options = cliToMatrixOptions(args);\n\n const results: MatrixResults[] = [];\n for (const matrix of suite.matrices) {\n const casesModule = matrix.casesModule\n ? await loadCasesModule(matrix.casesModule)\n : undefined;\n\n let filtered: FilteredMatrix<any> = matrix;\n if (!args.all && casesModule) {\n filtered = {\n ...matrix,\n filteredCases: casesModule.defaultCases,\n filteredVariants: casesModule.defaultVariants,\n };\n }\n\n // filter merges via intersection with defaults\n if (filter) {\n filtered = await filterMatrix(filtered, filter);\n }\n\n const { filteredCases, filteredVariants } = filtered;\n results.push(\n await runMatrix(filtered, {\n ...options,\n filteredCases,\n filteredVariants,\n }),\n );\n }\n return results;\n}\n\n/** Convert CLI args to matrix run options */\nexport function cliToMatrixOptions(args: DefaultCliArgs): RunMatrixOptions {\n const { time, iterations, worker } = args;\n return {\n iterations,\n maxTime: iterations ? undefined : time * 1000,\n useWorker: worker,\n ...cliCommonOptions(args),\n };\n}\n\n/** Generate report for matrix results. Uses same sections as regular benchmarks. */\nexport function defaultMatrixReport(\n results: MatrixResults[],\n reportOptions?: MatrixReportOptions,\n args?: DefaultCliArgs,\n): string {\n const options = args\n ? mergeMatrixDefaults(reportOptions, args, results)\n : reportOptions;\n return results.map(r => reportMatrixResults(r, options)).join(\"\\n\\n\");\n}\n\n/** Run matrix suite with full CLI handling (parse, run, report, export) */\nexport async function runDefaultMatrixBench(\n suite: MatrixSuite,\n configureArgs?: Configure<any>,\n reportOptions?: MatrixReportOptions,\n): Promise<void> {\n const args = parseBenchArgs(configureArgs);\n await matrixBenchExports(suite, args, reportOptions);\n}\n\n/** Convert MatrixResults to ReportGroup[] for export compatibility */\nexport function matrixToReportGroups(results: MatrixResults[]): ReportGroup[] {\n return results.flatMap(matrix =>\n matrix.variants.flatMap(variant =>\n variant.cases.map(c => {\n const { metadata } = c;\n const report = {\n name: variant.id,\n measuredResults: c.measured,\n metadata,\n };\n const baseline = c.baseline\n ? {\n name: `${variant.id} (baseline)`,\n measuredResults: c.baseline,\n metadata,\n }\n : undefined;\n return {\n name: `${variant.id} / ${c.caseId}`,\n reports: [report],\n baseline,\n };\n }),\n ),\n );\n}\n\n/** Run matrix benchmarks, display table, and generate exports */\nexport async function matrixBenchExports(\n suite: MatrixSuite,\n args: DefaultCliArgs,\n reportOptions?: MatrixReportOptions,\n exportOptions?: MatrixExportOptions,\n): Promise<void> {\n const results = await runMatrixSuite(suite, args);\n const report = defaultMatrixReport(results, reportOptions, args);\n console.log(report);\n\n const reportGroups = matrixToReportGroups(results);\n await finishReports(reportGroups, args, suite.name, exportOptions);\n}\n\n/** Validate CLI argument combinations */\nfunction validateArgs(args: DefaultCliArgs): void {\n if (args[\"gc-stats\"] && !args.worker && !args.url) {\n throw new Error(\n \"--gc-stats requires worker mode (the default). Remove --no-worker flag.\",\n );\n }\n}\n\n/** Execute all groups in suite */\nasync function runSuite(params: SuiteParams): Promise<ReportGroup[]> {\n const { suite, runner, options, useWorker, batches } = params;\n const results: ReportGroup[] = [];\n for (const group of suite.groups) {\n results.push(await runGroup(group, runner, options, useWorker, batches));\n }\n return results;\n}\n\n/** Build report sections based on CLI options */\nfunction buildReportSections(\n adaptive: boolean,\n gcStats: boolean,\n hasCpuData: boolean,\n hasOptData: boolean,\n) {\n const sections = adaptive\n ? [adaptiveSection, totalTimeSection]\n : [timeSection];\n\n if (gcStats) sections.push(gcStatsSection);\n if (hasCpuData) sections.push(cpuSection);\n if (hasOptData) sections.push(optSection);\n sections.push(runsSection);\n\n return sections;\n}\n\n/** Print heap reports (if enabled) and export results */\nasync function finishReports(\n results: ReportGroup[],\n args: DefaultCliArgs,\n suiteName?: string,\n exportOptions?: MatrixExportOptions,\n): Promise<void> {\n if (needsHeapSample(args)) {\n printHeapReports(results, cliHeapReportOptions(args));\n }\n await exportReports({ results, args, suiteName, ...exportOptions });\n}\n\n/** Warn about Node-only flags that are ignored in browser mode. */\nfunction warnBrowserFlags(args: DefaultCliArgs): void {\n const ignored: string[] = [];\n if (!args.worker) ignored.push(\"--no-worker\");\n if (args.cpu) ignored.push(\"--cpu\");\n if (args[\"trace-opt\"]) ignored.push(\"--trace-opt\");\n if (args.collect) ignored.push(\"--collect\");\n if (args.adaptive) ignored.push(\"--adaptive\");\n if (args.batches > 1) ignored.push(\"--batches\");\n if (ignored.length) {\n console.warn(yellow(`Ignored in browser mode: ${ignored.join(\", \")}`));\n }\n}\n\n/** @return true if any heap-related flag implies heap sampling */\nfunction needsHeapSample(args: DefaultCliArgs): boolean {\n return (\n args[\"heap-sample\"] ||\n args.speedscope ||\n !!args[\"export-speedscope\"] ||\n args[\"heap-raw\"] ||\n args[\"heap-verbose\"] ||\n args[\"heap-user-only\"]\n );\n}\n\n/** Strip surrounding quotes from a chrome arg token.\n *\n * (Needed because --chrome-args values pass through yargs and spawn() without\n * shell processing, so literal quote characters reach Chrome/V8 unrecognized.)\n */\nfunction stripQuotes(s: string): string {\n /* (['\"]): opening quote; (.*): content; \\1: require same closing quote */\n const unquote = s.replace(/^(['\"])(.*)\\1$/s, \"$2\");\n\n /* value portion: --flag=\"--value\" or --flag='--value'\n (-[^=]+=): flag name and =; (['\"])(.*)\\2: quoted value */\n const valueUnquote = unquote.replace(/^(-[^=]+=)(['\"])(.*)\\2$/s, \"$1$3\");\n\n return valueUnquote;\n}\n\n/** Wrap browser profile result as ReportGroup[] for the standard pipeline */\nfunction browserResultGroups(\n name: string,\n result: BrowserProfileResult,\n): ReportGroup[] {\n const { gcStats, heapProfile } = result;\n let measured: MeasuredResults;\n\n // Bench function mode: multiple timing samples with real statistics\n if (result.samples && result.samples.length > 0) {\n const { samples } = result;\n const totalTime = result.wallTimeMs ? result.wallTimeMs / 1000 : undefined;\n measured = {\n name,\n samples,\n time: computeStats(samples),\n totalTime,\n gcStats,\n heapProfile,\n };\n } else {\n // Lap mode: 0 laps = single wall-clock, N laps handled above\n const wallMs = result.wallTimeMs ?? 0;\n const time = {\n min: wallMs,\n max: wallMs,\n avg: wallMs,\n p50: wallMs,\n p75: wallMs,\n p99: wallMs,\n p999: wallMs,\n };\n measured = { name, samples: [wallMs], time, gcStats, heapProfile };\n }\n\n return [{ name, reports: [{ name, measuredResults: measured }] }];\n}\n\n/** Print browser benchmark tables and heap reports */\nfunction printBrowserReport(\n result: BrowserProfileResult,\n results: ReportGroup[],\n args: DefaultCliArgs,\n): void {\n const hasSamples = result.samples && result.samples.length > 0;\n const sections: ResultsMapper<any>[] = [];\n if (hasSamples || result.wallTimeMs != null) {\n sections.push(timeSection);\n }\n if (result.gcStats) {\n sections.push(browserGcStatsSection);\n }\n if (hasSamples || result.wallTimeMs != null) {\n sections.push(runsSection);\n }\n if (sections.length > 0) {\n console.log(reportResults(results, sections));\n }\n if (result.heapProfile) {\n printHeapReports(results, {\n ...cliHeapReportOptions(args),\n isUserCode: isBrowserUserCode,\n });\n }\n}\n\n/** Import a file and run it as a benchmark based on what it exports */\nasync function fileBenchExports(\n filePath: string,\n args: DefaultCliArgs,\n): Promise<void> {\n const fileUrl = pathToFileURL(resolve(filePath)).href;\n const mod = await import(fileUrl);\n const candidate = mod.default;\n\n if (candidate && Array.isArray(candidate.matrices)) {\n // MatrixSuite export\n await matrixBenchExports(candidate as MatrixSuite, args);\n } else if (candidate && Array.isArray(candidate.groups)) {\n // BenchSuite export\n await benchExports(candidate as BenchSuite, args);\n } else if (typeof candidate === \"function\") {\n // Default function export: wrap as a single benchmark\n const name = basename(filePath).replace(/\\.[^.]+$/, \"\");\n await benchExports(\n { name, groups: [{ name, benchmarks: [{ name, fn: candidate }] }] },\n args,\n );\n }\n // else: self-executing file already ran on import\n}\n\n/** Create options for adaptive mode */\nfunction createAdaptiveOptions(args: DefaultCliArgs): RunnerOptions {\n return {\n minTime: (args[\"min-time\"] ?? 1) * 1000,\n maxTime: defaultAdaptiveMaxTime * 1000,\n targetConfidence: args.convergence,\n adaptive: true,\n ...cliCommonOptions(args),\n } as any;\n}\n\n/** Runner/matrix options shared across all CLI modes */\nfunction cliCommonOptions(args: DefaultCliArgs) {\n const { collect, cpu, warmup } = args;\n const { \"trace-opt\": traceOpt, \"skip-settle\": noSettle } = args;\n const { \"pause-first\": pauseFirst, \"pause-interval\": pauseInterval } = args;\n const { \"pause-duration\": pauseDuration, \"gc-stats\": gcStats } = args;\n const heapSample = needsHeapSample(args);\n const { \"heap-interval\": heapInterval } = args;\n const { \"heap-depth\": heapDepth } = args;\n return {\n collect,\n cpuCounters: cpu,\n warmup,\n traceOpt,\n noSettle,\n pauseFirst,\n pauseInterval,\n pauseDuration,\n gcStats,\n heapSample,\n heapInterval,\n heapDepth,\n };\n}\n\n/** Wait for Ctrl+C before exiting */\nfunction waitForCtrlC(): Promise<void> {\n return new Promise(resolve => {\n console.log(dim(\"\\nPress Ctrl+C to exit\"));\n process.on(\"SIGINT\", () => {\n console.log();\n resolve();\n });\n });\n}\n\n/** Apply default sections and extra columns for matrix reports */\nfunction mergeMatrixDefaults(\n reportOptions: MatrixReportOptions | undefined,\n args: DefaultCliArgs,\n results: MatrixResults[],\n): MatrixReportOptions {\n const result: MatrixReportOptions = { ...reportOptions };\n\n if (!result.sections?.length) {\n const groups = matrixToReportGroups(results);\n result.sections = buildReportSections(\n args.adaptive,\n args[\"gc-stats\"],\n hasField(groups, \"cpu\"),\n args[\"trace-opt\"] && hasField(groups, \"optStatus\"),\n );\n }\n\n return result;\n}\n\n/** Execute group with shared setup, optionally batching to reduce ordering bias */\nasync function runGroup(\n group: BenchGroup,\n runner: KnownRunner,\n options: RunnerOptions,\n useWorker: boolean,\n batches = 1,\n): Promise<ReportGroup> {\n const { name, benchmarks, baseline, setup, metadata } = group;\n const setupParams = await setup?.();\n validateBenchmarkParameters(group);\n\n const runParams = {\n runner,\n options,\n useWorker,\n params: setupParams,\n metadata,\n };\n if (batches === 1) {\n return runSingleBatch(name, benchmarks, baseline, runParams);\n }\n return runMultipleBatches(name, benchmarks, baseline, runParams, batches);\n}\n\n/** @return HeapReportOptions from CLI args */\nfunction cliHeapReportOptions(args: DefaultCliArgs): HeapReportOptions {\n return {\n topN: args[\"heap-rows\"],\n stackDepth: args[\"heap-stack\"],\n verbose: args[\"heap-verbose\"],\n raw: args[\"heap-raw\"],\n userOnly: args[\"heap-user-only\"],\n };\n}\n\n/** Warn if parameterized benchmarks lack setup */\nfunction validateBenchmarkParameters(group: BenchGroup): void {\n const { name, setup, benchmarks, baseline } = group;\n if (setup) return;\n\n const allBenchmarks = baseline ? [...benchmarks, baseline] : benchmarks;\n for (const benchmark of allBenchmarks) {\n if (benchmark.fn.length > 0) {\n console.warn(\n `Benchmark \"${benchmark.name}\" in group \"${name}\" expects parameters but no setup() provided.`,\n );\n }\n }\n}\n\n/** Run benchmarks in a single batch */\nasync function runSingleBatch(\n name: string,\n benchmarks: BenchmarkSpec[],\n baseline: BenchmarkSpec | undefined,\n runParams: RunParams,\n): Promise<ReportGroup> {\n const baselineReport = baseline\n ? await runSingleBenchmark(baseline, runParams)\n : undefined;\n const reports = await serialMap(benchmarks, b =>\n runSingleBenchmark(b, runParams),\n );\n return { name, reports, baseline: baselineReport };\n}\n\n/** Run benchmarks in multiple batches, alternating order to reduce bias */\nasync function runMultipleBatches(\n name: string,\n benchmarks: BenchmarkSpec[],\n baseline: BenchmarkSpec | undefined,\n runParams: RunParams,\n batches: number,\n): Promise<ReportGroup> {\n const timePerBatch = (runParams.options.maxTime || 5000) / batches;\n const batchParams = {\n ...runParams,\n options: { ...runParams.options, maxTime: timePerBatch },\n };\n const baselineBatches: MeasuredResults[] = [];\n const benchmarkBatches = new Map<string, MeasuredResults[]>();\n\n for (let i = 0; i < batches; i++) {\n const reverseOrder = i % 2 === 1;\n await runBatchIteration(\n benchmarks,\n baseline,\n batchParams,\n reverseOrder,\n baselineBatches,\n benchmarkBatches,\n );\n }\n\n const meta = runParams.metadata;\n return mergeBatchResults(\n name,\n benchmarks,\n baseline,\n baselineBatches,\n benchmarkBatches,\n meta,\n );\n}\n\n/** Run single benchmark and create report */\nasync function runSingleBenchmark(\n spec: BenchmarkSpec,\n runParams: RunParams,\n): Promise<BenchmarkReport> {\n const { runner, options, useWorker, params, metadata } = runParams;\n const benchmarkParams = { spec, runner, options, useWorker, params };\n const [result] = await runBenchmark(benchmarkParams);\n return { name: spec.name, measuredResults: result, metadata };\n}\n\n/** Sequential map - like Promise.all(arr.map(fn)) but runs one at a time */\nasync function serialMap<T, R>(\n arr: T[],\n fn: (item: T) => Promise<R>,\n): Promise<R[]> {\n const results: R[] = [];\n for (const item of arr) {\n results.push(await fn(item));\n }\n return results;\n}\n\n/** Run one batch iteration in either order */\nasync function runBatchIteration(\n benchmarks: BenchmarkSpec[],\n baseline: BenchmarkSpec | undefined,\n runParams: RunParams,\n reverseOrder: boolean,\n baselineBatches: MeasuredResults[],\n benchmarkBatches: Map<string, MeasuredResults[]>,\n): Promise<void> {\n const runBaseline = async () => {\n if (baseline) {\n const r = await runSingleBenchmark(baseline, runParams);\n baselineBatches.push(r.measuredResults);\n }\n };\n const runBenches = async () => {\n for (const b of benchmarks) {\n const r = await runSingleBenchmark(b, runParams);\n appendToMap(benchmarkBatches, b.name, r.measuredResults);\n }\n };\n\n if (reverseOrder) {\n await runBenches();\n await runBaseline();\n } else {\n await runBaseline();\n await runBenches();\n }\n}\n\n/** Merge batch results into final ReportGroup */\nfunction mergeBatchResults(\n name: string,\n benchmarks: BenchmarkSpec[],\n baseline: BenchmarkSpec | undefined,\n baselineBatches: MeasuredResults[],\n benchmarkBatches: Map<string, MeasuredResults[]>,\n metadata?: Record<string, unknown>,\n): ReportGroup {\n const mergedBaseline = baseline\n ? {\n name: baseline.name,\n measuredResults: mergeResults(baselineBatches),\n metadata,\n }\n : undefined;\n const reports = benchmarks.map(b => ({\n name: b.name,\n measuredResults: mergeResults(benchmarkBatches.get(b.name) || []),\n metadata,\n }));\n return { name, reports, baseline: mergedBaseline };\n}\n\nfunction appendToMap(\n map: Map<string, MeasuredResults[]>,\n key: string,\n value: MeasuredResults,\n) {\n if (!map.has(key)) map.set(key, []);\n map.get(key)!.push(value);\n}\n\n/** Merge multiple batch results into a single MeasuredResults */\nfunction mergeResults(results: MeasuredResults[]): MeasuredResults {\n if (results.length === 0) {\n throw new Error(\"Cannot merge empty results array\");\n }\n if (results.length === 1) return results[0];\n\n const allSamples = results.flatMap(r => r.samples);\n const allWarmup = results.flatMap(r => r.warmupSamples || []);\n const time = computeStats(allSamples);\n\n let offset = 0;\n const allPausePoints = results.flatMap(r => {\n const pts = (r.pausePoints ?? []).map(p => ({\n sampleIndex: p.sampleIndex + offset,\n durationMs: p.durationMs,\n }));\n offset += r.samples.length;\n return pts;\n });\n\n return {\n name: results[0].name,\n samples: allSamples,\n warmupSamples: allWarmup.length ? allWarmup : undefined,\n time,\n totalTime: results.reduce((sum, r) => sum + (r.totalTime || 0), 0),\n pausePoints: allPausePoints.length ? allPausePoints : undefined,\n };\n}\n","import { execSync } from \"node:child_process\";\nimport { existsSync, readFileSync, statSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport type { GitVersion } from \"./html/index.ts\";\nimport { formatDateWithTimezone } from \"./html/index.ts\";\n\nexport type { GitVersion } from \"./html/index.ts\";\nexport { formatDateWithTimezone, formatRelativeTime } from \"./html/index.ts\";\n\n/** Get current git version info. For dirty repos, uses most recent modified file date. */\nexport function getCurrentGitVersion(): GitVersion | undefined {\n try {\n const exec = (cmd: string) => execSync(cmd, { encoding: \"utf-8\" }).trim();\n const hash = exec(\"git rev-parse --short HEAD\");\n const commitDate = exec(\"git log -1 --format=%aI\");\n const dirty = exec(\"git status --porcelain\").length > 0;\n\n const date = dirty\n ? (getMostRecentModifiedDate(\".\") ?? commitDate)\n : commitDate;\n return { hash, date, dirty };\n } catch {\n return undefined;\n }\n}\n\n/** Read baseline version from .baseline-version file */\nexport function getBaselineVersion(\n baselineDir = \"_baseline\",\n): GitVersion | undefined {\n const versionFile = join(baselineDir, \".baseline-version\");\n if (!existsSync(versionFile)) return undefined;\n\n try {\n const content = readFileSync(versionFile, \"utf-8\");\n const data = JSON.parse(content);\n return { hash: data.hash, date: data.date };\n } catch {\n return undefined;\n }\n}\n\n/** Format git version for display: \"abc1234 (Jan 9, 2026, 3:45 PM)\" or \"abc1234*\" if dirty */\nexport function formatGitVersion(version: GitVersion): string {\n const hashDisplay = version.dirty ? `${version.hash}*` : version.hash;\n const dateDisplay = formatDateWithTimezone(version.date);\n return `${hashDisplay} (${dateDisplay})`;\n}\n\n/** Get most recent modified file date in a directory (for dirty repos) */\nexport function getMostRecentModifiedDate(dir: string): string | undefined {\n try {\n const raw = execSync(\"git status --porcelain\", {\n encoding: \"utf-8\",\n cwd: dir,\n });\n const modifiedFiles = raw\n .trim()\n .split(\"\\n\")\n .filter(line => line.length > 0)\n .map(line => line.slice(3));\n\n if (modifiedFiles.length === 0) return undefined;\n\n let mostRecent = 0;\n for (const file of modifiedFiles) {\n try {\n const filePath = join(dir, file);\n if (!existsSync(filePath)) continue;\n const mtime = statSync(filePath).mtimeMs;\n if (mtime > mostRecent) mostRecent = mtime;\n } catch {}\n }\n\n return mostRecent > 0 ? new Date(mostRecent).toISOString() : undefined;\n } catch {\n return undefined;\n }\n}\n"],"mappings":"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"}
|