benchforge 0.1.8 → 0.1.11

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.
Files changed (68) hide show
  1. package/README.md +69 -42
  2. package/dist/{BenchRunner-CSKN9zPy.d.mts → BenchRunner-BzyUfiyB.d.mts} +32 -8
  3. package/dist/{BrowserHeapSampler-DCeL42RE.mjs → BrowserHeapSampler-B6asLKWQ.mjs} +57 -57
  4. package/dist/BrowserHeapSampler-B6asLKWQ.mjs.map +1 -0
  5. package/dist/{GcStats-ByEovUi1.mjs → GcStats-wX7Xyblu.mjs} +15 -15
  6. package/dist/GcStats-wX7Xyblu.mjs.map +1 -0
  7. package/dist/HeapSampler-B8dtKHn1.mjs.map +1 -1
  8. package/dist/{TimingUtils-ClclVQ7E.mjs → TimingUtils-DwOwkc8G.mjs} +225 -225
  9. package/dist/TimingUtils-DwOwkc8G.mjs.map +1 -0
  10. package/dist/bin/benchforge.mjs +1 -1
  11. package/dist/browser/index.js +210 -210
  12. package/dist/index.d.mts +106 -48
  13. package/dist/index.mjs +3 -3
  14. package/dist/runners/WorkerScript.d.mts +1 -1
  15. package/dist/runners/WorkerScript.mjs +66 -66
  16. package/dist/runners/WorkerScript.mjs.map +1 -1
  17. package/dist/{src-HfimYuW_.mjs → src-B-DDaCa9.mjs} +1250 -991
  18. package/dist/src-B-DDaCa9.mjs.map +1 -0
  19. package/package.json +4 -3
  20. package/src/BenchMatrix.ts +125 -125
  21. package/src/BenchmarkReport.ts +50 -45
  22. package/src/HtmlDataPrep.ts +21 -21
  23. package/src/PermutationTest.ts +24 -24
  24. package/src/StandardSections.ts +45 -45
  25. package/src/StatisticalUtils.ts +60 -61
  26. package/src/browser/BrowserGcStats.ts +5 -5
  27. package/src/browser/BrowserHeapSampler.ts +63 -63
  28. package/src/cli/CliArgs.ts +20 -6
  29. package/src/cli/FilterBenchmarks.ts +5 -5
  30. package/src/cli/RunBenchCLI.ts +533 -476
  31. package/src/export/JsonExport.ts +10 -10
  32. package/src/export/PerfettoExport.ts +74 -74
  33. package/src/export/SpeedscopeExport.ts +202 -0
  34. package/src/heap-sample/HeapSampleReport.ts +143 -70
  35. package/src/heap-sample/HeapSampler.ts +55 -12
  36. package/src/heap-sample/ResolvedProfile.ts +89 -0
  37. package/src/html/HtmlReport.ts +33 -33
  38. package/src/html/HtmlTemplate.ts +67 -67
  39. package/src/html/browser/CIPlot.ts +50 -50
  40. package/src/html/browser/HistogramKde.ts +13 -13
  41. package/src/html/browser/LegendUtils.ts +48 -48
  42. package/src/html/browser/RenderPlots.ts +98 -98
  43. package/src/html/browser/SampleTimeSeries.ts +79 -79
  44. package/src/index.ts +6 -0
  45. package/src/matrix/MatrixFilter.ts +6 -6
  46. package/src/matrix/MatrixReport.ts +96 -96
  47. package/src/matrix/VariantLoader.ts +5 -5
  48. package/src/runners/AdaptiveWrapper.ts +151 -151
  49. package/src/runners/BasicRunner.ts +175 -175
  50. package/src/runners/BenchRunner.ts +8 -8
  51. package/src/runners/GcStats.ts +22 -22
  52. package/src/runners/RunnerOrchestrator.ts +168 -168
  53. package/src/runners/WorkerScript.ts +96 -96
  54. package/src/table-util/Formatters.ts +41 -36
  55. package/src/table-util/TableReport.ts +122 -122
  56. package/src/table-util/test/TableValueExtractor.ts +9 -9
  57. package/src/test/AdaptiveStatistics.integration.ts +7 -39
  58. package/src/test/HeapAttribution.test.ts +51 -0
  59. package/src/test/RunBenchCLI.test.ts +36 -11
  60. package/src/test/TestUtils.ts +24 -24
  61. package/src/test/fixtures/fn-export-bench.ts +3 -0
  62. package/src/test/fixtures/suite-export-bench.ts +16 -0
  63. package/src/tests/BenchMatrix.test.ts +12 -12
  64. package/src/tests/MatrixFilter.test.ts +15 -15
  65. package/dist/BrowserHeapSampler-DCeL42RE.mjs.map +0 -1
  66. package/dist/GcStats-ByEovUi1.mjs.map +0 -1
  67. package/dist/TimingUtils-ClclVQ7E.mjs.map +0 -1
  68. package/dist/src-HfimYuW_.mjs.map +0 -1
@@ -1 +0,0 @@
1
- {"version":3,"file":"src-HfimYuW_.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/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\nconst logTiming = debugWorkerTiming\n ? (message: string) => console.log(`[RunnerOrchestrator] ${message}`)\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\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/** 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/** 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/** 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/** 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/** 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/** 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/** 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/** 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/** 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/** 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\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/** 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/** 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\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","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/** @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/** 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/** 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\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/** 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\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/** 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/** 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/** 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/** 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/** 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\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/** 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/** 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","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 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/** 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) */\nexport function formatBytes(bytes: unknown): string | null {\n if (typeof bytes !== \"number\") return null;\n if (bytes < 1024) return `${bytes.toFixed(0)}B`;\n if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)}KB`;\n if (bytes < 1024 * 1024 * 1024)\n return `${(bytes / 1024 / 1024).toFixed(1)}MB`;\n return `${(bytes / 1024 / 1024 / 1024).toFixed(1)}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 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 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 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\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 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","import pico from \"picocolors\";\nimport type { Alignment, SpanningCellConfig, TableUserConfig } from \"table\";\nimport { table } from \"table\";\nimport { diffPercent } from \"./Formatters.ts\";\n\nconst isTest = process.env.NODE_ENV === \"test\" || process.env.VITEST === \"true\";\nconst { bold } = isTest ? { bold: (str: string) => str } : pico;\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/** 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\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/** 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 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/** 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\ninterface Lines {\n drawHorizontalLine: (index: number, size: number) => boolean;\n drawVerticalLine: (index: number, size: number) => boolean;\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 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/** @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/** @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/** 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/** 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/** 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/** 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/** 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\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/** 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// 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/** 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","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/** @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 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 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 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\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 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","import type { Argv, InferredOptionTypes } from \"yargs\";\nimport yargs from \"yargs\";\n\nexport const defaultAdaptiveMaxTime = 20;\n\nexport type Configure<T> = (yargs: Argv) => Argv<T>;\n\n/** CLI args type inferred from cliOptions */\nexport type DefaultCliArgs = InferredOptionTypes<typeof cliOptions>;\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 perfetto: { type: \"string\", requiresArg: true, describe: \"export Perfetto trace file (view at ui.perfetto.dev)\" },\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-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.options(cliOptions).help().strict();\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/** 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\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","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\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\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/** 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\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/** 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/** 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/** 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/** 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","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\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/** 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/** 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/** @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/** @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\ntype ColumnLike = {\n key: string;\n title: string;\n formatter?: (v: unknown) => string | null;\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\";\nimport type { HeapProfile, ProfileNode } from \"./HeapSampler.ts\";\n\n/** Sum selfSize across all nodes in profile (before any filtering) */\nexport function totalProfileBytes(profile: HeapProfile): number {\n let total = 0;\n function walk(node: ProfileNode): void {\n total += node.selfSize;\n for (const child of node.children || []) walk(child);\n }\n walk(profile.head);\n return total;\n}\n\nexport interface CallFrame {\n fn: string;\n url: string;\n line: number; // 1-indexed for display\n col: number;\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}\n\n/** Flatten profile tree into sorted list of allocation sites with call stacks */\nexport function flattenProfile(profile: HeapProfile): HeapSite[] {\n const sites: HeapSite[] = [];\n\n function walk(node: ProfileNode, stack: CallFrame[]): void {\n const { functionName, url, lineNumber, columnNumber } = node.callFrame;\n const fn = functionName || \"(anonymous)\";\n const col = columnNumber ?? 0;\n const frame: CallFrame = { fn, url: url || \"\", line: lineNumber + 1, col };\n const newStack = [...stack, frame];\n\n if (node.selfSize > 0) {\n sites.push({\n ...frame,\n bytes: node.selfSize,\n stack: newStack,\n });\n }\n for (const child of node.children || []) walk(child, newStack);\n }\n\n walk(profile.head, []);\n return sites.sort((a, b) => b.bytes - a.bytes);\n}\n\nexport type UserCodeFilter = (site: CallFrame) => boolean;\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) */\nexport function aggregateSites(sites: HeapSite[]): HeapSite[] {\n const byLocation = new Map<string, HeapSite>();\n\n for (const site of sites) {\n const key = `${site.url}:${site.line}:${site.col}`;\n const existing = byLocation.get(key);\n if (existing) {\n existing.bytes += site.bytes;\n } else {\n byLocation.set(key, { ...site });\n }\n }\n\n return [...byLocation.values()].sort((a, b) => b.bytes - a.bytes);\n}\n\nfunction fmtBytes(bytes: number): string {\n if (bytes >= 1024 * 1024) return `${(bytes / 1024 / 1024).toFixed(2)} MB`;\n if (bytes >= 1024) return `${(bytes / 1024).toFixed(1)} KB`;\n return `${bytes} B`;\n}\n\nexport interface HeapReportOptions {\n topN: number;\n stackDepth?: number;\n verbose?: boolean;\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/** 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/** 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\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 ? `${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 = `${frame.url}:${frame.line}:${frame.col}`;\n lines.push(dimFn(` <- ${frame.fn} ${callerLoc}`));\n }\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","import type { GitVersion, GroupData, ReportData } from \"./Types.ts\";\n\nconst skipArgs = new Set([\"_\", \"$0\", \"html\", \"export-html\"]);\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/** 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\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\nconst badgeLabels = {\n faster: \"Faster\",\n slower: \"Slower\",\n uncertain: \"Inconclusive\",\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}\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/** @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/** 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/** 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","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/** 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\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","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/** 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/** 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/** 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\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\nexport interface GcSectionStats {\n gc?: number; // GC time as fraction of total bench time\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\nexport interface GcStatsInfo {\n allocPerIter?: number;\n collected?: number;\n scavenges?: number;\n fullGCs?: number;\n promoPercent?: number;\n pausePerIter?: number;\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\nexport interface CpuStats {\n cpuCacheMiss?: number;\n cpuStall?: number;\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\nexport interface RunStats {\n runs?: number;\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\nexport interface AdaptiveStats {\n median?: number;\n mean?: number;\n p99?: number;\n convergence?: number;\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/** 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\nexport interface OptStats {\n tiers?: string; // tier distribution summary\n deopt?: number; // deopt count\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","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/** 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/** 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/** 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 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 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 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/** 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/** 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\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/** 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/** Format bytes with fallback to \"-\" for missing values */\nfunction formatBytesOrDash(value: unknown): string {\n return formatBytes(value) ?? \"-\";\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","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/** Escape regex special characters */\nfunction escapeRegex(str: string): string {\n return str.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\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","import 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 { reportResults } from \"../BenchmarkReport.ts\";\nimport type { BrowserProfileResult } from \"../browser/BrowserHeapSampler.ts\";\nimport { exportBenchmarkJson } from \"../export/JsonExport.ts\";\nimport { exportPerfettoTrace } from \"../export/PerfettoExport.ts\";\nimport type { GitVersion } from \"../GitUtils.ts\";\nimport { prepareHtmlData } from \"../HtmlDataPrep.ts\";\nimport {\n aggregateSites,\n filterSites,\n flattenProfile,\n formatHeapReport,\n type HeapReportOptions,\n isBrowserUserCode,\n totalProfileBytes,\n} from \"../heap-sample/HeapSampleReport.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\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/** 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\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\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/** 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/** 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/** 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 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\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/** 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/** 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\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/** 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/** 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/** 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: args[\"heap-sample\"],\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 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/** 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 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 const allReports = group.baseline\n ? [...group.reports, group.baseline]\n : group.reports;\n\n for (const report of allReports) {\n const { heapProfile } = report.measuredResults;\n if (!heapProfile) continue;\n\n console.log(dim(`\\n─── Heap profile: ${report.name} ───`));\n const totalAll = totalProfileBytes(heapProfile);\n const sites = flattenProfile(heapProfile);\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,\n totalUserCode,\n sampleCount: heapProfile.samples?.length,\n };\n console.log(formatHeapReport(aggregated, { ...options, ...extra }));\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 {\n throw new Error(\"Either --url or a BenchSuite is required.\");\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/** 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 { \"heap-sample\": heapSample, \"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\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/** Log V8 optimization tier distribution and deoptimizations */\nexport function reportOptStatus(groups: ReportGroup[]): void {\n const optData = groups.flatMap(({ reports, baseline }) => {\n const all = baseline ? [...reports, baseline] : reports;\n return all\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(({ reports, baseline }) => {\n const all = baseline ? [...reports, baseline] : reports;\n return all.some(\n ({ measuredResults }) => measuredResults[field] !== undefined,\n );\n });\n}\n\nexport interface ExportOptions {\n results: ReportGroup[];\n args: DefaultCliArgs;\n sections?: any[];\n suiteName?: string;\n currentVersion?: GitVersion;\n baselineVersion?: GitVersion;\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 (args[\"heap-sample\"]) {\n printHeapReports(results, cliHeapReportOptions(args));\n }\n await exportReports({ results, args, suiteName, ...exportOptions });\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.perfetto) {\n exportPerfettoTrace(results, args.perfetto, args);\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/** 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/** 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/** @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 userOnly: args[\"heap-user-only\"],\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/** 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\nexport interface MatrixExportOptions {\n sections?: any[];\n currentVersion?: GitVersion;\n baselineVersion?: GitVersion;\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/** 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 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","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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"}