benchforge 0.1.11 → 0.2.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +20 -0
- package/README.md +99 -294
- package/bin/benchforge +1 -2
- package/dist/AnalyzeArchive-8NCJhmhS.mjs +145 -0
- package/dist/AnalyzeArchive-8NCJhmhS.mjs.map +1 -0
- package/dist/BenchMatrix-BZVrBB_h.mjs +1050 -0
- package/dist/BenchMatrix-BZVrBB_h.mjs.map +1 -0
- package/dist/{BenchRunner-BzyUfiyB.d.mts → BenchRunner-DglX1NOn.d.mts} +119 -66
- package/dist/CoverageSampler-D5T9DRqe.mjs +27 -0
- package/dist/CoverageSampler-D5T9DRqe.mjs.map +1 -0
- package/dist/Formatters-BWj3d4sv.mjs +95 -0
- package/dist/Formatters-BWj3d4sv.mjs.map +1 -0
- package/dist/{HeapSampler-B8dtKHn1.mjs → HeapSampler-Dq-hpXem.mjs} +4 -4
- package/dist/HeapSampler-Dq-hpXem.mjs.map +1 -0
- package/dist/RunBenchCLI-C17DrJz8.mjs +3075 -0
- package/dist/RunBenchCLI-C17DrJz8.mjs.map +1 -0
- package/dist/StatisticalUtils-BD92crgM.mjs +255 -0
- package/dist/StatisticalUtils-BD92crgM.mjs.map +1 -0
- package/dist/TimeSampler-Ds8n7l2B.mjs +29 -0
- package/dist/TimeSampler-Ds8n7l2B.mjs.map +1 -0
- package/dist/ViewerServer-BJhdnxlN.mjs +639 -0
- package/dist/ViewerServer-BJhdnxlN.mjs.map +1 -0
- package/dist/ViewerServer-CuMNdNBz.mjs +2 -0
- package/dist/bin/benchforge.mjs +4 -5
- package/dist/bin/benchforge.mjs.map +1 -1
- package/dist/index.d.mts +711 -558
- package/dist/index.mjs +98 -3
- package/dist/index.mjs.map +1 -0
- package/dist/runners/WorkerScript.d.mts +12 -4
- package/dist/runners/WorkerScript.mjs +77 -105
- package/dist/runners/WorkerScript.mjs.map +1 -1
- package/dist/viewer/assets/CIPlot-BkOvMoMa.js +1 -0
- package/dist/viewer/assets/HistogramKde-CmSyUFY0.js +1 -0
- package/dist/viewer/assets/LegendUtils-BJpbn_jr.js +55 -0
- package/dist/viewer/assets/SampleTimeSeries-C4VBhXr3.js +1 -0
- package/dist/viewer/assets/index-Br9bp_cX.js +153 -0
- package/dist/viewer/assets/index-NzXXe_CC.css +1 -0
- package/dist/viewer/index.html +19 -0
- package/dist/viewer/speedscope/LICENSE +21 -0
- package/dist/viewer/speedscope/SourceCodePro-Regular.ttf-ILST5JV6.woff2 +0 -0
- package/dist/viewer/speedscope/favicon-16x16-V2DMIAZS.js +2 -0
- package/dist/viewer/speedscope/favicon-16x16-V2DMIAZS.js.map +7 -0
- package/dist/viewer/speedscope/favicon-16x16-VSI62OPJ.png +0 -0
- package/dist/viewer/speedscope/favicon-32x32-3EB2YCUY.png +0 -0
- package/dist/viewer/speedscope/favicon-32x32-THY3JDJL.js +2 -0
- package/dist/viewer/speedscope/favicon-32x32-THY3JDJL.js.map +7 -0
- package/dist/viewer/speedscope/favicon-FOKUP5Y5.ico +0 -0
- package/dist/viewer/speedscope/favicon-M34RF7BI.js +2 -0
- package/dist/viewer/speedscope/favicon-M34RF7BI.js.map +7 -0
- package/dist/viewer/speedscope/file-format-schema.json +274 -0
- package/dist/viewer/speedscope/index.html +19 -0
- package/dist/viewer/speedscope/jfrview_bg-BLJXNNQB.wasm +0 -0
- package/dist/viewer/speedscope/perf-vertx-stacks-01-collapsed-all-ZNUIGAJL.txt +199 -0
- package/dist/viewer/speedscope/release.txt +3 -0
- package/dist/viewer/speedscope/source-code-pro.LICENSE.md +93 -0
- package/dist/viewer/speedscope/speedscope-GHPHNKXC.css +2 -0
- package/dist/viewer/speedscope/speedscope-GHPHNKXC.css.map +7 -0
- package/dist/viewer/speedscope/speedscope-QZFMJ7VP.js +212 -0
- package/dist/viewer/speedscope/speedscope-QZFMJ7VP.js.map +7 -0
- package/package.json +52 -27
- package/src/bin/benchforge.ts +2 -2
- package/src/cli/AnalyzeArchive.ts +232 -0
- package/src/cli/BrowserBench.ts +322 -0
- package/src/cli/CliArgs.ts +164 -51
- package/src/cli/CliExport.ts +179 -0
- package/src/cli/CliOptions.ts +147 -0
- package/src/cli/CliReport.ts +197 -0
- package/src/cli/FilterBenchmarks.ts +18 -30
- package/src/cli/RunBenchCLI.ts +132 -866
- package/src/cli/SuiteRunner.ts +160 -0
- package/src/cli/ViewerServer.ts +282 -0
- package/src/export/AllocExport.ts +121 -0
- package/src/export/ArchiveExport.ts +146 -0
- package/src/export/ArchiveFormat.ts +50 -0
- package/src/export/CoverageExport.ts +148 -0
- package/src/export/EditorUri.ts +10 -0
- package/src/export/PerfettoExport.ts +64 -99
- package/src/export/SpeedscopeTypes.ts +98 -0
- package/src/export/TimeExport.ts +115 -0
- package/src/index.ts +86 -67
- package/src/matrix/BenchMatrix.ts +230 -0
- package/src/matrix/CaseLoader.ts +8 -6
- package/src/matrix/MatrixDirRunner.ts +153 -0
- package/src/matrix/MatrixFilter.ts +49 -47
- package/src/matrix/MatrixInlineRunner.ts +50 -0
- package/src/matrix/MatrixReport.ts +90 -250
- package/src/matrix/VariantLoader.ts +5 -5
- package/src/profiling/browser/BenchLoop.ts +51 -0
- package/src/profiling/browser/BrowserCDP.ts +133 -0
- package/src/profiling/browser/BrowserGcStats.ts +33 -0
- package/src/profiling/browser/BrowserProfiler.ts +160 -0
- package/src/profiling/browser/CdpClient.ts +82 -0
- package/src/profiling/browser/CdpPage.ts +138 -0
- package/src/profiling/browser/ChromeLauncher.ts +158 -0
- package/src/profiling/browser/ChromeTraceEvent.ts +28 -0
- package/src/profiling/browser/PageLoadMode.ts +61 -0
- package/src/profiling/node/CoverageSampler.ts +27 -0
- package/src/profiling/node/CoverageTypes.ts +23 -0
- package/src/profiling/node/HeapSampleReport.ts +261 -0
- package/src/{heap-sample → profiling/node}/HeapSampler.ts +1 -2
- package/src/{heap-sample → profiling/node}/ResolvedProfile.ts +18 -9
- package/src/profiling/node/TimeSampler.ts +57 -0
- package/src/report/BenchmarkReport.ts +146 -0
- package/src/report/Colors.ts +9 -0
- package/src/report/Formatters.ts +110 -0
- package/src/report/GcSections.ts +151 -0
- package/src/{GitUtils.ts → report/GitUtils.ts} +18 -19
- package/src/report/HtmlReport.ts +223 -0
- package/src/report/ParseStats.ts +73 -0
- package/src/report/StandardSections.ts +147 -0
- package/src/report/ViewerSections.ts +286 -0
- package/src/report/text/TableReport.ts +253 -0
- package/src/report/text/TextReport.ts +123 -0
- package/src/runners/AdaptiveWrapper.ts +116 -236
- package/src/runners/BenchRunner.ts +20 -15
- package/src/{Benchmark.ts → runners/BenchmarkSpec.ts} +5 -6
- package/src/runners/CreateRunner.ts +5 -7
- package/src/runners/GcStats.ts +47 -50
- package/src/{MeasuredResults.ts → runners/MeasuredResults.ts} +43 -37
- package/src/runners/MergeBatches.ts +123 -0
- package/src/{NodeGC.ts → runners/NodeGC.ts} +2 -3
- package/src/runners/RunnerOrchestrator.ts +127 -243
- package/src/runners/RunnerUtils.ts +75 -1
- package/src/runners/SampleStats.ts +100 -0
- package/src/runners/TimingRunner.ts +244 -0
- package/src/runners/TimingUtils.ts +3 -2
- package/src/runners/WorkerScript.ts +135 -151
- package/src/stats/BootstrapDifference.ts +282 -0
- package/src/{PermutationTest.ts → stats/PermutationTest.ts} +8 -17
- package/src/stats/StatisticalUtils.ts +445 -0
- package/src/{tests → test}/AdaptiveConvergence.test.ts +10 -10
- package/src/test/AdaptiveRunner.test.ts +39 -41
- package/src/{tests → test}/AdaptiveSampling.test.ts +9 -9
- package/src/test/AdaptiveStatistics.integration.ts +2 -2
- package/src/{tests → test}/BenchMatrix.test.ts +19 -16
- package/src/test/BenchmarkReport.test.ts +63 -13
- package/src/test/BrowserBench.e2e.test.ts +186 -17
- package/src/test/BrowserBench.test.ts +10 -5
- package/src/test/BuildTimeSection.test.ts +130 -0
- package/src/test/CapSamples.test.ts +82 -0
- package/src/test/CoverageExport.test.ts +115 -0
- package/src/test/CoverageSampler.test.ts +33 -0
- package/src/test/HeapAttribution.test.ts +14 -14
- package/src/{tests → test}/MatrixFilter.test.ts +1 -1
- package/src/{tests → test}/MatrixReport.test.ts +1 -1
- package/src/test/PermutationTest.test.ts +1 -1
- package/src/{tests → test}/RealDataValidation.test.ts +6 -6
- package/src/test/RunBenchCLI.test.ts +39 -38
- package/src/test/RunnerOrchestrator.test.ts +12 -12
- package/src/test/StatisticalUtils.test.ts +48 -12
- package/src/{table-util/test → test}/TableReport.test.ts +2 -2
- package/src/test/TestUtils.ts +12 -7
- package/src/test/TimeExport.test.ts +139 -0
- package/src/test/TimeSampler.test.ts +37 -0
- package/src/test/ViewerLive.e2e.test.ts +159 -0
- package/src/test/ViewerStatic.static.e2e.test.ts +137 -0
- package/src/{tests → test}/fixtures/baseline/impl.ts +1 -1
- package/src/{tests → test}/fixtures/bevy30-samples.ts +3 -1
- package/src/test/fixtures/cases/asyncCases.ts +9 -0
- package/src/{tests → test}/fixtures/cases/cases.ts +5 -2
- package/src/test/fixtures/cases/variants/product.ts +2 -0
- package/src/test/fixtures/cases/variants/sum.ts +2 -0
- package/src/test/fixtures/discover/fast.ts +1 -0
- package/src/{tests → test}/fixtures/discover/slow.ts +1 -1
- package/src/test/fixtures/invalid/bad.ts +1 -0
- package/src/test/fixtures/loader/fast.ts +1 -0
- package/src/{tests → test}/fixtures/loader/slow.ts +1 -1
- package/src/test/fixtures/loader/stateful.ts +2 -0
- package/src/test/fixtures/stateful/stateful.ts +2 -0
- package/src/test/fixtures/variants/extra.ts +1 -0
- package/src/test/fixtures/variants/impl.ts +1 -0
- package/src/test/fixtures/worker/fast.ts +1 -0
- package/src/{tests → test}/fixtures/worker/slow.ts +1 -1
- package/src/viewer/DateFormat.ts +30 -0
- package/src/viewer/Helpers.ts +23 -0
- package/src/viewer/LineData.ts +120 -0
- package/src/viewer/Providers.ts +191 -0
- package/src/viewer/ReportData.ts +123 -0
- package/src/viewer/State.ts +49 -0
- package/src/viewer/Theme.ts +15 -0
- package/src/viewer/components/App.tsx +73 -0
- package/src/viewer/components/DropZone.tsx +71 -0
- package/src/viewer/components/LazyPlot.ts +33 -0
- package/src/viewer/components/SamplesPanel.tsx +214 -0
- package/src/viewer/components/Shell.tsx +26 -0
- package/src/viewer/components/SourcePanel.tsx +216 -0
- package/src/viewer/components/SummaryPanel.tsx +332 -0
- package/src/viewer/components/TabBar.tsx +131 -0
- package/src/viewer/components/TabContent.tsx +46 -0
- package/src/viewer/components/ThemeToggle.tsx +50 -0
- package/src/viewer/index.html +20 -0
- package/src/viewer/main.tsx +4 -0
- package/src/viewer/plots/CIPlot.ts +313 -0
- package/src/{html/browser → viewer/plots}/HistogramKde.ts +33 -38
- package/src/viewer/plots/LegendUtils.ts +134 -0
- package/src/viewer/plots/PlotTypes.ts +85 -0
- package/src/viewer/plots/RenderPlots.ts +230 -0
- package/src/viewer/plots/SampleTimeSeries.ts +306 -0
- package/src/viewer/plots/SvgHelpers.ts +136 -0
- package/src/viewer/plots/TimeSeriesMarks.ts +319 -0
- package/src/viewer/report.css +427 -0
- package/src/viewer/shell.css +357 -0
- package/src/viewer/tsconfig.json +11 -0
- package/dist/BrowserHeapSampler-B6asLKWQ.mjs +0 -202
- package/dist/BrowserHeapSampler-B6asLKWQ.mjs.map +0 -1
- package/dist/GcStats-wX7Xyblu.mjs +0 -77
- package/dist/GcStats-wX7Xyblu.mjs.map +0 -1
- package/dist/HeapSampler-B8dtKHn1.mjs.map +0 -1
- package/dist/TimingUtils-DwOwkc8G.mjs +0 -597
- package/dist/TimingUtils-DwOwkc8G.mjs.map +0 -1
- package/dist/browser/index.js +0 -914
- package/dist/src-B-DDaCa9.mjs +0 -3108
- package/dist/src-B-DDaCa9.mjs.map +0 -1
- package/src/BenchMatrix.ts +0 -380
- package/src/BenchmarkReport.ts +0 -161
- package/src/HtmlDataPrep.ts +0 -148
- package/src/StandardSections.ts +0 -261
- package/src/StatisticalUtils.ts +0 -175
- package/src/TypeUtil.ts +0 -8
- package/src/browser/BrowserGcStats.ts +0 -44
- package/src/browser/BrowserHeapSampler.ts +0 -271
- package/src/export/JsonExport.ts +0 -103
- package/src/export/JsonFormat.ts +0 -91
- package/src/export/SpeedscopeExport.ts +0 -202
- package/src/heap-sample/HeapSampleReport.ts +0 -269
- package/src/html/HtmlReport.ts +0 -131
- package/src/html/HtmlTemplate.ts +0 -284
- package/src/html/Types.ts +0 -88
- package/src/html/browser/CIPlot.ts +0 -287
- package/src/html/browser/LegendUtils.ts +0 -163
- package/src/html/browser/RenderPlots.ts +0 -263
- package/src/html/browser/SampleTimeSeries.ts +0 -389
- package/src/html/browser/Types.ts +0 -96
- package/src/html/browser/index.ts +0 -1
- package/src/html/index.ts +0 -17
- package/src/runners/BasicRunner.ts +0 -364
- package/src/table-util/ConvergenceFormatters.ts +0 -19
- package/src/table-util/Formatters.ts +0 -157
- package/src/table-util/README.md +0 -70
- package/src/table-util/TableReport.ts +0 -293
- package/src/tests/fixtures/cases/asyncCases.ts +0 -7
- package/src/tests/fixtures/cases/variants/product.ts +0 -2
- package/src/tests/fixtures/cases/variants/sum.ts +0 -2
- package/src/tests/fixtures/discover/fast.ts +0 -1
- package/src/tests/fixtures/invalid/bad.ts +0 -1
- package/src/tests/fixtures/loader/fast.ts +0 -1
- package/src/tests/fixtures/loader/stateful.ts +0 -2
- package/src/tests/fixtures/stateful/stateful.ts +0 -2
- package/src/tests/fixtures/variants/extra.ts +0 -1
- package/src/tests/fixtures/variants/impl.ts +0 -1
- package/src/tests/fixtures/worker/fast.ts +0 -1
- /package/src/{table-util/test → test}/TableValueExtractor.test.ts +0 -0
- /package/src/{table-util/test → test}/TableValueExtractor.ts +0 -0
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"TimingUtils-DwOwkc8G.mjs","names":["percentile"],"sources":["../src/matrix/VariantLoader.ts","../src/runners/BenchRunner.ts","../src/runners/BasicRunner.ts","../src/StatisticalUtils.ts","../src/runners/RunnerUtils.ts","../src/runners/AdaptiveWrapper.ts","../src/runners/CreateRunner.ts","../src/runners/TimingUtils.ts"],"sourcesContent":["import fs from \"node:fs/promises\";\nimport { fileURLToPath } from \"node:url\";\nimport type { Variant } from \"../BenchMatrix.ts\";\n\n/** Discover variant ids from a directory of .ts files */\nexport async function discoverVariants(dirUrl: string): Promise<string[]> {\n const dirPath = fileURLToPath(dirUrl);\n const entries = await fs.readdir(dirPath, { withFileTypes: true });\n return entries\n .filter(e => e.isFile() && e.name.endsWith(\".ts\"))\n .map(e => e.name.slice(0, -3))\n .sort();\n}\n\n/** Load a variant module and extract run/setup exports */\nexport async function loadVariant<T = unknown>(\n dirUrl: string,\n variantId: string,\n): Promise<Variant<T>> {\n const moduleUrl = variantModuleUrl(dirUrl, variantId);\n const module = await import(moduleUrl);\n return extractVariant(module, variantId, moduleUrl);\n}\n\n/** Get module URL for a variant in a directory */\nexport function variantModuleUrl(dirUrl: string, variantId: string): string {\n return new URL(`${variantId}.ts`, dirUrl).href;\n}\n\n/** Extract variant from module exports */\nfunction extractVariant<T>(\n module: Record<string, unknown>,\n variantId: string,\n moduleUrl: string,\n): Variant<T> {\n const { setup, run } = module;\n const loc = `Variant '${variantId}' at ${moduleUrl}`;\n if (typeof run !== \"function\") {\n throw new Error(`${loc} must export 'run'`);\n }\n if (setup === undefined) return run as (data: T) => void;\n if (typeof setup !== \"function\") {\n throw new Error(`${loc}: 'setup' must be a function`);\n }\n return { setup: setup as (data: T) => unknown, run: run as () => void };\n}\n","import type { BenchmarkSpec } from \"../Benchmark.ts\";\nimport type { MeasuredResults } from \"../MeasuredResults.ts\";\n\n/** Interface for benchmark execution libraries */\nexport interface BenchRunner {\n runBench<T = unknown>(\n benchmark: BenchmarkSpec<T>,\n options: RunnerOptions,\n params?: T,\n ): Promise<MeasuredResults[]>;\n}\n\nexport interface RunnerOptions {\n /** Minimum time to run each benchmark (milliseconds) */\n minTime?: number;\n /** Maximum time to run each benchmark - ignored by mitata (milliseconds) */\n maxTime?: number;\n /** Maximum iterations per benchmark - ignored by TinyBench */\n maxIterations?: number;\n /** Warmup iterations before measurement (default: 0) */\n warmup?: number;\n /** Warmup time before measurement (milliseconds) */\n warmupTime?: number;\n /** Warmup samples - mitata only, for reducing test time */\n warmupSamples?: number;\n /** Warmup threshold - mitata only (nanoseconds) */\n warmupThreshold?: number;\n /** Minimum samples required - mitata only */\n minSamples?: number;\n /** Force GC after each iteration (requires --expose-gc) */\n collect?: boolean;\n /** Enable CPU performance counters (requires root access) */\n cpuCounters?: boolean;\n /** Trace V8 optimization tiers (requires --allow-natives-syntax) */\n traceOpt?: boolean;\n /** Skip post-warmup settle time (default: false) */\n noSettle?: boolean;\n /** Iterations before first pause (then pauseInterval applies) */\n pauseFirst?: number;\n /** Iterations between pauses for V8 optimization (0 to disable) */\n pauseInterval?: number;\n /** Pause duration in ms for V8 optimization */\n pauseDuration?: number;\n /** Collect GC stats via --trace-gc-nvp (requires worker mode) */\n gcStats?: boolean;\n /** Heap sampling allocation attribution */\n heapSample?: boolean;\n /** Heap sampling interval in bytes */\n heapInterval?: number;\n /** Heap sampling stack depth */\n heapDepth?: number;\n}\n\n/** Execute benchmark with optional parameters */\nexport function executeBenchmark<T>(\n benchmark: BenchmarkSpec<T>,\n params?: T,\n): void {\n (benchmark.fn as (params?: T) => void)(params);\n}\n","import { getHeapStatistics } from \"node:v8\";\nimport type { BenchmarkSpec } from \"../Benchmark.ts\";\nimport type {\n MeasuredResults,\n OptStatusInfo,\n PausePoint,\n} from \"../MeasuredResults.ts\";\nimport type { BenchRunner, RunnerOptions } from \"./BenchRunner.ts\";\nimport { executeBenchmark } from \"./BenchRunner.ts\";\n\nexport type SampleTimeStats = {\n min: number;\n max: number;\n avg: number;\n p50: number;\n p75: number;\n p99: number;\n p999: number;\n};\n\ntype CollectParams<T = unknown> = {\n benchmark: BenchmarkSpec<T>;\n maxTime: number;\n maxIterations: number;\n warmup: number;\n params?: T;\n skipWarmup?: boolean;\n traceOpt?: boolean;\n noSettle?: boolean;\n pauseFirst?: number;\n pauseInterval?: number;\n pauseDuration?: number;\n};\n\ntype CollectResult = {\n samples: number[];\n warmupSamples: number[]; // timing of warmup iterations\n heapGrowth: number; // amortized KB per sample\n heapSamples?: number[]; // heap size per sample (bytes)\n timestamps?: number[]; // wall-clock μs per sample for Perfetto\n optStatus?: OptStatusInfo;\n optSamples?: number[]; // per-sample V8 opt status codes\n pausePoints: PausePoint[]; // where pauses occurred\n};\n\ntype SampleLoopResult = {\n samples: number[];\n heapSamples?: number[];\n timestamps?: number[];\n optStatuses: number[];\n pausePoints: PausePoint[];\n};\n\ntype SampleArrays = {\n samples: number[];\n timestamps: number[];\n heapSamples: number[];\n optStatuses: number[];\n pausePoints: PausePoint[];\n};\n\n/**\n * Wait time after gc() for V8 to stabilize (ms).\n *\n * V8 has 4 compilation tiers: Ignition (interpreter) -> Sparkplug (baseline) ->\n * Maglev (mid-tier optimizer) -> TurboFan (full optimizer). Tiering thresholds:\n * - Ignition -> Sparkplug: 8 invocations\n * - Sparkplug -> Maglev: 500 invocations\n * - Maglev -> TurboFan: 6000 invocations\n *\n * Optimization compilation happens on background threads and requires idle time\n * on the main thread to complete. Without sufficient warmup + settle time,\n * benchmarks exhibit bimodal timing: slow Sparkplug samples (~30% slower) mixed\n * with fast optimized samples.\n *\n * The warmup iterations trigger the optimization decision, then gcSettleTime\n * provides idle time for background compilation to finish before measurement.\n *\n * @see https://v8.dev/blog/sparkplug\n * @see https://v8.dev/blog/maglev\n * @see https://v8.dev/blog/background-compilation\n */\nconst gcSettleTime = 1000;\n\nconst defaultCollectOptions = {\n maxTime: 5000,\n maxIterations: 1000000,\n warmup: 0,\n traceOpt: false,\n noSettle: false,\n};\n\n/**\n * V8 optimization status bit meanings:\n * Bit 0 (1): is_function\n * Bit 4 (16): is_optimized (TurboFan)\n * Bit 5 (32): is_optimized (Maglev)\n * Bit 7 (128): is_baseline (Sparkplug)\n * Bit 3 (8): maybe_deoptimized\n */\nconst statusNames: Record<number, string> = {\n 1: \"interpreted\",\n 129: \"sparkplug\", // 1 + 128\n 17: \"turbofan\", // 1 + 16\n 33: \"maglev\", // 1 + 32\n 49: \"turbofan+maglev\", // 1 + 16 + 32\n 32769: \"optimized\", // common optimized status\n};\n\n/** @return runner with time and iteration limits */\nexport class BasicRunner implements BenchRunner {\n async runBench<T = unknown>(\n benchmark: BenchmarkSpec<T>,\n options: RunnerOptions,\n params?: T,\n ): Promise<MeasuredResults[]> {\n const opts = { ...defaultCollectOptions, ...(options as any) };\n const collected = await collectSamples({ benchmark, params, ...opts });\n return [buildMeasuredResults(benchmark.name, collected)];\n }\n}\n\n/** @return percentiles and basic statistics */\nexport function computeStats(samples: number[]): SampleTimeStats {\n const sorted = [...samples].sort((a, b) => a - b);\n const avg = samples.reduce((sum, s) => sum + s, 0) / samples.length;\n return {\n min: sorted[0],\n max: sorted[sorted.length - 1],\n avg,\n p50: percentile(sorted, 0.5),\n p75: percentile(sorted, 0.75),\n p99: percentile(sorted, 0.99),\n p999: percentile(sorted, 0.999),\n };\n}\n\n/** @return timing samples and amortized allocation from benchmark execution */\nasync function collectSamples<T>(p: CollectParams<T>): Promise<CollectResult> {\n if (!p.maxIterations && !p.maxTime) {\n throw new Error(`At least one of maxIterations or maxTime must be set`);\n }\n const warmupSamples = p.skipWarmup ? [] : await runWarmup(p);\n const heapBefore = process.memoryUsage().heapUsed;\n const { samples, heapSamples, timestamps, optStatuses, pausePoints } =\n await runSampleLoop(p);\n const heapGrowth =\n Math.max(0, process.memoryUsage().heapUsed - heapBefore) /\n 1024 /\n samples.length;\n if (samples.length === 0) {\n throw new Error(`No samples collected for benchmark: ${p.benchmark.name}`);\n }\n const optStatus = p.traceOpt\n ? analyzeOptStatus(samples, optStatuses)\n : undefined;\n const optSamples =\n p.traceOpt && optStatuses.length > 0 ? optStatuses : undefined;\n return {\n samples,\n warmupSamples,\n heapGrowth,\n heapSamples,\n timestamps,\n optStatus,\n optSamples,\n pausePoints,\n };\n}\n\nfunction buildMeasuredResults(name: string, c: CollectResult): MeasuredResults {\n const time = computeStats(c.samples);\n return {\n name,\n samples: c.samples,\n warmupSamples: c.warmupSamples,\n heapSamples: c.heapSamples,\n timestamps: c.timestamps,\n time,\n heapSize: { avg: c.heapGrowth, min: c.heapGrowth, max: c.heapGrowth },\n optStatus: c.optStatus,\n optSamples: c.optSamples,\n pausePoints: c.pausePoints,\n };\n}\n\n/** @return percentile value with linear interpolation */\nfunction percentile(sortedArray: number[], p: number): number {\n const index = (sortedArray.length - 1) * p;\n const lower = Math.floor(index);\n const upper = Math.ceil(index);\n const weight = index % 1;\n\n if (upper >= sortedArray.length) return sortedArray[sortedArray.length - 1];\n\n return sortedArray[lower] * (1 - weight) + sortedArray[upper] * weight;\n}\n\n/** Run warmup iterations with gc + settle time for V8 optimization */\nasync function runWarmup<T>(p: CollectParams<T>): Promise<number[]> {\n const gc = gcFunction();\n const samples = new Array<number>(p.warmup);\n for (let i = 0; i < p.warmup; i++) {\n const start = performance.now();\n executeBenchmark(p.benchmark, p.params);\n samples[i] = performance.now() - start;\n }\n gc();\n if (!p.noSettle) {\n await new Promise(r => setTimeout(r, gcSettleTime));\n gc();\n }\n return samples;\n}\n\n/** Collect timing samples with periodic pauses for V8 optimization */\nasync function runSampleLoop<T>(\n p: CollectParams<T>,\n): Promise<SampleLoopResult> {\n const {\n maxTime,\n maxIterations,\n pauseFirst,\n pauseInterval = 0,\n pauseDuration = 100,\n } = p;\n const trackHeap = true; // Always track heap for charts\n const getOptStatus = p.traceOpt ? createOptStatusGetter() : undefined;\n const estimated = estimateSampleCount(maxTime, maxIterations);\n const a = createSampleArrays(estimated, trackHeap, !!getOptStatus);\n\n let count = 0;\n let elapsed = 0;\n let totalPauseTime = 0;\n const loopStart = performance.now();\n\n while (\n (!maxIterations || count < maxIterations) &&\n (!maxTime || elapsed < maxTime)\n ) {\n const start = performance.now();\n executeBenchmark(p.benchmark, p.params);\n const end = performance.now();\n a.samples[count] = end - start;\n a.timestamps[count] = Number(process.hrtime.bigint() / 1000n);\n if (trackHeap) a.heapSamples[count] = getHeapStatistics().used_heap_size;\n if (getOptStatus) a.optStatuses[count] = getOptStatus(p.benchmark.fn);\n count++;\n\n if (shouldPause(count, pauseFirst, pauseInterval)) {\n a.pausePoints.push({ sampleIndex: count - 1, durationMs: pauseDuration });\n const pauseStart = performance.now();\n await new Promise(r => setTimeout(r, pauseDuration));\n totalPauseTime += performance.now() - pauseStart;\n }\n elapsed = performance.now() - loopStart - totalPauseTime;\n }\n\n trimArrays(a, count, trackHeap, !!getOptStatus);\n return {\n samples: a.samples,\n heapSamples: trackHeap ? a.heapSamples : undefined,\n timestamps: a.timestamps,\n optStatuses: a.optStatuses,\n pausePoints: a.pausePoints,\n };\n}\n\n/** @return analysis of V8 optimization status per sample */\nfunction analyzeOptStatus(\n samples: number[],\n statuses: number[],\n): OptStatusInfo | undefined {\n if (statuses.length === 0 || statuses[0] === undefined) return undefined;\n\n const byStatusCode = new Map<number, number[]>();\n let deoptCount = 0;\n\n for (let i = 0; i < samples.length; i++) {\n const status = statuses[i];\n if (status === undefined) continue;\n\n // Check deopt flag (bit 3)\n if (status & 8) deoptCount++;\n\n if (!byStatusCode.has(status)) byStatusCode.set(status, []);\n byStatusCode.get(status)!.push(samples[i]);\n }\n\n const byTier: Record<string, { count: number; medianMs: number }> = {};\n for (const [status, times] of byStatusCode) {\n const name = statusNames[status] || `status=${status}`;\n const sorted = [...times].sort((a, b) => a - b);\n const median = sorted[Math.floor(sorted.length / 2)];\n byTier[name] = { count: times.length, medianMs: median };\n }\n\n return { byTier, deoptCount };\n}\n\n/** @return runtime gc() function, or no-op if unavailable */\nfunction gcFunction(): () => void {\n const gc = globalThis.gc || (globalThis as any).__gc;\n if (gc) return gc;\n console.warn(\"gc() not available, run node/bun with --expose-gc\");\n return () => {};\n}\n\n/** @return function to get V8 optimization status (requires --allow-natives-syntax) */\nfunction createOptStatusGetter(): ((fn: unknown) => number) | undefined {\n try {\n // %GetOptimizationStatus returns a bitmask\n const getter = new Function(\"f\", \"return %GetOptimizationStatus(f)\");\n getter(() => {});\n return getter as (fn: unknown) => number;\n } catch {\n return undefined;\n }\n}\n\n/** Estimate sample count for pre-allocation */\nfunction estimateSampleCount(maxTime: number, maxIterations: number): number {\n return maxIterations || Math.ceil(maxTime / 0.1); // assume 0.1ms per iteration minimum\n}\n\n/** Pre-allocate arrays to reduce GC pressure during measurement */\nfunction createSampleArrays(\n n: number,\n trackHeap: boolean,\n trackOpt: boolean,\n): SampleArrays {\n const arr = (track: boolean) => (track ? new Array<number>(n) : []);\n return {\n samples: new Array<number>(n),\n timestamps: new Array<number>(n),\n heapSamples: arr(trackHeap),\n optStatuses: arr(trackOpt),\n pausePoints: [],\n };\n}\n\n/** Check if we should pause at this iteration for V8 optimization */\nfunction shouldPause(\n iter: number,\n first: number | undefined,\n interval: number,\n): boolean {\n if (first !== undefined && iter === first) return true;\n if (interval <= 0) return false;\n if (first === undefined) return iter % interval === 0;\n return (iter - first) % interval === 0;\n}\n\n/** Trim arrays to actual sample count */\nfunction trimArrays(\n a: SampleArrays,\n count: number,\n trackHeap: boolean,\n trackOpt: boolean,\n): void {\n a.samples.length = a.timestamps.length = count;\n if (trackHeap) a.heapSamples.length = count;\n if (trackOpt) a.optStatuses.length = count;\n}\n","/** Bootstrap estimate with confidence interval and raw resample data */\nexport interface BootstrapResult {\n estimate: number;\n ci: [number, number];\n samples: number[];\n}\n\nexport type CIDirection = \"faster\" | \"slower\" | \"uncertain\";\n\n/** Binned histogram for efficient transfer to browser */\nexport interface HistogramBin {\n x: number; // bin center\n count: number;\n}\n\n/** Bootstrap confidence interval for percentage difference between two samples */\nexport interface DifferenceCI {\n percent: number;\n ci: [number, number];\n direction: CIDirection;\n /** Histogram of bootstrap distribution for visualization */\n histogram?: HistogramBin[];\n}\n\n/** Options for bootstrap resampling methods */\ntype BootstrapOptions = {\n resamples?: number;\n confidence?: number;\n};\nconst confidence = 0.95;\nconst outlierMultiplier = 1.5; // Tukey's fence multiplier\nconst bootstrapSamples = 10000;\n\n/** @return relative standard deviation (coefficient of variation) */\nexport function coefficientOfVariation(samples: number[]): number {\n const mean = average(samples);\n if (mean === 0) return 0;\n const stdDev = standardDeviation(samples);\n return stdDev / mean;\n}\n\n/** @return median absolute deviation for robust variability measure */\nexport function medianAbsoluteDeviation(samples: number[]): number {\n const median = percentile(samples, 0.5);\n const deviations = samples.map(x => Math.abs(x - median));\n return percentile(deviations, 0.5);\n}\n\n/** @return outliers detected via Tukey's interquartile range method */\nexport function findOutliers(samples: number[]): {\n rate: number;\n indices: number[];\n} {\n const q1 = percentile(samples, 0.25);\n const q3 = percentile(samples, 0.75);\n const iqr = q3 - q1;\n const lowerBound = q1 - outlierMultiplier * iqr;\n const upperBound = q3 + outlierMultiplier * iqr;\n\n const indices = samples\n .map((v, i) => (v < lowerBound || v > upperBound ? i : -1))\n .filter(i => i >= 0);\n return { rate: indices.length / samples.length, indices };\n}\n\n/** @return bootstrap confidence interval for median */\nexport function bootstrapMedian(\n samples: number[],\n options: BootstrapOptions = {},\n): BootstrapResult {\n const { resamples = bootstrapSamples, confidence: conf = confidence } =\n options;\n const medians = generateMedians(samples, resamples);\n const ci = computeInterval(medians, conf);\n\n return {\n estimate: percentile(samples, 0.5),\n ci,\n samples: medians,\n };\n}\n\n/** @return mean of values */\nexport function average(values: number[]): number {\n const sum = values.reduce((a, b) => a + b, 0);\n return sum / values.length;\n}\n\n/** @return standard deviation with Bessel's correction */\nexport function standardDeviation(samples: number[]): number {\n if (samples.length <= 1) return 0;\n const mean = average(samples);\n const variance =\n samples.reduce((sum, x) => sum + (x - mean) ** 2, 0) / (samples.length - 1);\n return Math.sqrt(variance);\n}\n\n/** @return value at percentile p (0-1) */\nexport function percentile(values: number[], p: number): number {\n const sorted = [...values].sort((a, b) => a - b);\n const index = Math.ceil(sorted.length * p) - 1;\n return sorted[Math.max(0, index)];\n}\n\n/** @return bootstrap resample with replacement */\nexport function createResample(samples: number[]): number[] {\n const n = samples.length;\n const rand = () => samples[Math.floor(Math.random() * n)];\n return Array.from({ length: n }, rand);\n}\n\n/** @return bootstrap CI for percentage difference between baseline and current medians */\nexport function bootstrapDifferenceCI(\n baseline: number[],\n current: number[],\n options: BootstrapOptions = {},\n): DifferenceCI {\n const { resamples = bootstrapSamples, confidence: conf = confidence } =\n options;\n\n const baselineMedian = percentile(baseline, 0.5);\n const currentMedian = percentile(current, 0.5);\n const observedPercent =\n ((currentMedian - baselineMedian) / baselineMedian) * 100;\n\n const diffs: number[] = [];\n for (let i = 0; i < resamples; i++) {\n const resB = createResample(baseline);\n const resC = createResample(current);\n const medB = percentile(resB, 0.5);\n const medC = percentile(resC, 0.5);\n diffs.push(((medC - medB) / medB) * 100);\n }\n\n const ci = computeInterval(diffs, conf);\n const excludesZero = ci[0] > 0 || ci[1] < 0;\n let direction: CIDirection = \"uncertain\";\n if (excludesZero) direction = observedPercent < 0 ? \"faster\" : \"slower\";\n const histogram = binValues(diffs);\n return { percent: observedPercent, ci, direction, histogram };\n}\n\n/** @return medians from bootstrap resamples */\nfunction generateMedians(samples: number[], resamples: number): number[] {\n return Array.from({ length: resamples }, () =>\n percentile(createResample(samples), 0.5),\n );\n}\n\n/** @return confidence interval [lower, upper] */\nfunction computeInterval(\n medians: number[],\n confidence: number,\n): [number, number] {\n const alpha = (1 - confidence) / 2;\n const lower = percentile(medians, alpha);\n const upper = percentile(medians, 1 - alpha);\n return [lower, upper];\n}\n\n/** Bin values into histogram for compact visualization */\nfunction binValues(values: number[], binCount = 30): HistogramBin[] {\n const sorted = [...values].sort((a, b) => a - b);\n const min = sorted[0];\n const max = sorted[sorted.length - 1];\n if (min === max) return [{ x: min, count: values.length }];\n\n const step = (max - min) / binCount;\n const counts = new Array(binCount).fill(0);\n for (const v of values) {\n const bin = Math.min(Math.floor((v - min) / step), binCount - 1);\n counts[bin]++;\n }\n return counts.map((count, i) => ({ x: min + (i + 0.5) * step, count }));\n}\n","export const msToNs = 1e6;\nexport const nsToMs = 1e-6;\n","import type { BenchmarkSpec } from \"../Benchmark.ts\";\nimport type { MeasuredResults } from \"../MeasuredResults.ts\";\nimport {\n coefficientOfVariation,\n medianAbsoluteDeviation,\n percentile,\n} from \"../StatisticalUtils.ts\";\nimport type { BenchRunner, RunnerOptions } from \"./BenchRunner.ts\";\nimport { msToNs } from \"./RunnerUtils.ts\";\n\nexport interface AdaptiveOptions extends RunnerOptions {\n adaptive?: boolean;\n minTime?: number;\n maxTime?: number;\n targetConfidence?: number;\n convergence?: number; // Confidence threshold (0-100)\n}\n\ntype Metrics = {\n medianDrift: number;\n impactDrift: number;\n medianStable: boolean;\n impactStable: boolean;\n};\n\ninterface ConvergenceResult {\n converged: boolean;\n confidence: number;\n reason: string;\n}\n\nconst minTime = 1000;\nconst maxTime = 10000;\nconst targetConfidence = 95;\nconst fallbackThreshold = 80;\nconst windowSize = 50;\nconst stability = 0.05; // 5% drift threshold (was 2%, too strict for real benchmarks)\nconst initialBatch = 100;\nconst continueBatch = 100;\nconst continueIterations = 10;\n\n/** @return adaptive sampling runner wrapper */\nexport function createAdaptiveWrapper(\n baseRunner: BenchRunner,\n options: AdaptiveOptions,\n): BenchRunner {\n return {\n async runBench<T = unknown>(\n benchmark: BenchmarkSpec<T>,\n runnerOptions: RunnerOptions,\n params?: T,\n ): Promise<MeasuredResults[]> {\n return runAdaptiveBench(\n baseRunner,\n benchmark,\n runnerOptions,\n options,\n params,\n );\n },\n };\n}\n\n/** @return convergence based on window stability */\nexport function checkConvergence(samples: number[]): ConvergenceResult {\n const windowSize = getWindowSize(samples);\n const minSamples = windowSize * 2;\n\n if (samples.length < minSamples) {\n return buildProgressResult(samples.length, minSamples);\n }\n\n const metrics = getStability(samples, windowSize);\n return buildConvergence(metrics);\n}\n\n/** @return results using adaptive sampling strategy */\nasync function runAdaptiveBench<T>(\n baseRunner: BenchRunner,\n benchmark: BenchmarkSpec<T>,\n runnerOptions: RunnerOptions,\n options: AdaptiveOptions,\n params?: T,\n): Promise<MeasuredResults[]> {\n const {\n minTime: min = options.minTime ?? minTime,\n maxTime: max = options.maxTime ?? maxTime,\n targetConfidence: target = options.convergence ?? targetConfidence,\n } = runnerOptions as AdaptiveOptions;\n const allSamples: number[] = [];\n\n // Collect initial batch (includes warmup + settle)\n const warmup = await collectInitial(\n baseRunner,\n benchmark,\n runnerOptions,\n params,\n allSamples,\n );\n\n // Start timing AFTER warmup - warmup time doesn't count against maxTime\n const startTime = performance.now();\n\n const limits = {\n minTime: min,\n maxTime: max,\n targetConfidence: target,\n startTime,\n };\n await collectAdaptive(\n baseRunner,\n benchmark,\n runnerOptions,\n params,\n allSamples,\n limits,\n );\n\n const convergence = checkConvergence(allSamples.map(s => s * msToNs));\n return buildResults(\n allSamples,\n startTime,\n convergence,\n benchmark.name,\n warmup,\n );\n}\n\n/** @return window size scaled to execution time */\nfunction getWindowSize(samples: number[]): number {\n if (samples.length < 20) return windowSize; // Default for initial samples\n\n const recentMs = samples.slice(-20).map(s => s / msToNs);\n const recentMedian = percentile(recentMs, 0.5);\n\n // Inverse scaling with execution time\n if (recentMedian < 0.01) return 200; // <10μs\n if (recentMedian < 0.1) return 100; // <100μs\n if (recentMedian < 1) return 50; // <1ms\n if (recentMedian < 10) return 30; // <10ms\n return 20; // >10ms\n}\n\n/** @return progress when samples insufficient */\nfunction buildProgressResult(\n currentSamples: number,\n minSamples: number,\n): ConvergenceResult {\n return {\n converged: false,\n confidence: (currentSamples / minSamples) * 100,\n reason: `Collecting samples: ${currentSamples}/${minSamples}`,\n };\n}\n\n/** @return stability metrics between windows */\nfunction getStability(samples: number[], windowSize: number): Metrics {\n const recent = samples.slice(-windowSize);\n const previous = samples.slice(-windowSize * 2, -windowSize);\n\n const recentMs = recent.map(s => s / msToNs);\n const previousMs = previous.map(s => s / msToNs);\n\n const medianRecent = percentile(recentMs, 0.5);\n const medianPrevious = percentile(previousMs, 0.5);\n const medianDrift = Math.abs(medianRecent - medianPrevious) / medianPrevious;\n\n const impactRecent = getOutlierImpact(recentMs);\n const impactPrevious = getOutlierImpact(previousMs);\n const impactDrift = Math.abs(impactRecent.ratio - impactPrevious.ratio);\n\n return {\n medianDrift,\n impactDrift,\n medianStable: medianDrift < stability,\n impactStable: impactDrift < stability,\n };\n}\n\n/** @return convergence from stability metrics */\nfunction buildConvergence(metrics: Metrics): ConvergenceResult {\n const { medianDrift, impactDrift, medianStable, impactStable } = metrics;\n\n if (medianStable && impactStable) {\n return {\n converged: true,\n confidence: 100,\n reason: \"Stable performance pattern\",\n };\n }\n\n const confidence = Math.min(\n 100,\n (1 - medianDrift / stability) * 50 + (1 - impactDrift / stability) * 50,\n );\n\n const reason =\n medianDrift > impactDrift\n ? `Median drifting: ${(medianDrift * 100).toFixed(1)}%`\n : `Outlier impact changing: ${(impactDrift * 100).toFixed(1)}%`;\n\n return { converged: false, confidence: Math.max(0, confidence), reason };\n}\n\n/** @return warmupSamples from initial batch */\nasync function collectInitial<T>(\n baseRunner: BenchRunner,\n benchmark: BenchmarkSpec<T>,\n runnerOptions: RunnerOptions,\n params: T | undefined,\n allSamples: number[],\n): Promise<number[] | undefined> {\n // Don't pass adaptive flag to base runner to avoid double wrapping\n const opts = {\n ...(runnerOptions as any),\n maxTime: initialBatch,\n maxIterations: undefined,\n };\n const results = await baseRunner.runBench(benchmark, opts, params);\n appendSamples(results[0], allSamples);\n return results[0].warmupSamples;\n}\n\n/** @return samples until convergence or timeout */\nasync function collectAdaptive<T>(\n baseRunner: BenchRunner,\n benchmark: BenchmarkSpec<T>,\n runnerOptions: RunnerOptions,\n params: T | undefined,\n allSamples: number[],\n limits: {\n minTime: number;\n maxTime: number;\n targetConfidence: number;\n startTime: number;\n },\n): Promise<void> {\n const { minTime, maxTime, targetConfidence, startTime } = limits;\n let lastLog = 0;\n while (performance.now() - startTime < maxTime) {\n const samplesNs = allSamples.map(s => s * msToNs);\n const convergence = checkConvergence(samplesNs);\n const elapsed = performance.now() - startTime;\n\n if (elapsed - lastLog > 1000) {\n const elapsedSec = (elapsed / 1000).toFixed(1);\n const conf = convergence.confidence.toFixed(0);\n process.stderr.write(\n `\\r◊ ${benchmark.name}: ${conf}% confident (${elapsedSec}s) `,\n );\n lastLog = elapsed;\n }\n\n if (shouldStop(convergence, targetConfidence, elapsed, minTime)) {\n break;\n }\n\n // Skip warmup for continuation batches (warmup done in initial batch)\n const opts = {\n ...(runnerOptions as any),\n maxTime: continueBatch,\n maxIterations: continueIterations,\n skipWarmup: true,\n };\n const batchResults = await baseRunner.runBench(benchmark, opts, params);\n appendSamples(batchResults[0], allSamples);\n }\n process.stderr.write(\"\\r\" + \" \".repeat(60) + \"\\r\");\n}\n\n/** @return measured results with convergence metrics */\nfunction buildResults(\n samplesMs: number[],\n startTime: number,\n convergence: ConvergenceResult,\n name: string,\n warmupSamples?: number[],\n): MeasuredResults[] {\n const totalTime = (performance.now() - startTime) / 1000;\n const samplesNs = samplesMs.map(s => s * msToNs);\n const timeStats = computeTimeStats(samplesNs);\n\n return [\n {\n name,\n samples: samplesMs,\n warmupSamples,\n time: timeStats,\n totalTime,\n convergence,\n },\n ];\n}\n\n/** @return outlier impact as proportion of total time */\nfunction getOutlierImpact(samples: number[]): { ratio: number; count: number } {\n if (samples.length === 0) return { ratio: 0, count: 0 };\n\n const median = percentile(samples, 0.5);\n const q75 = percentile(samples, 0.75);\n const threshold = median + 1.5 * (q75 - median);\n\n let excessTime = 0;\n let count = 0;\n\n for (const sample of samples) {\n if (sample > threshold) {\n excessTime += sample - median;\n count++;\n }\n }\n\n const totalTime = samples.reduce((a, b) => a + b, 0);\n return {\n ratio: totalTime > 0 ? excessTime / totalTime : 0,\n count,\n };\n}\n\n/** Append samples one-by-one to avoid stack overflow from spread on large arrays */\nfunction appendSamples(result: MeasuredResults, samples: number[]): void {\n if (!result.samples?.length) return;\n for (const sample of result.samples) samples.push(sample);\n}\n\n/** @return true if convergence reached or timeout */\nfunction shouldStop(\n convergence: ConvergenceResult,\n targetConfidence: number,\n elapsedTime: number,\n minTime: number,\n): boolean {\n if (convergence.converged && convergence.confidence >= targetConfidence) {\n return true;\n }\n // After minTime, accept whichever is higher: targetConfidence or fallbackThreshold\n const threshold = Math.max(targetConfidence, fallbackThreshold);\n return elapsedTime >= minTime && convergence.confidence >= threshold;\n}\n\n/** @return time percentiles and statistics in ms */\nfunction computeTimeStats(samplesNs: number[]) {\n const samplesMs = samplesNs.map(s => s / msToNs);\n const { min, max, sum } = getMinMaxSum(samplesNs);\n const percentiles = getPercentiles(samplesNs);\n const robust = getRobustMetrics(samplesMs);\n\n return {\n min: min / msToNs,\n max: max / msToNs,\n avg: sum / samplesNs.length / msToNs,\n ...percentiles,\n ...robust,\n };\n}\n\n/** @return min, max, sum of samples */\nfunction getMinMaxSum(samples: number[]) {\n const min = samples.reduce(\n (a, b) => Math.min(a, b),\n Number.POSITIVE_INFINITY,\n );\n const max = samples.reduce(\n (a, b) => Math.max(a, b),\n Number.NEGATIVE_INFINITY,\n );\n const sum = samples.reduce((a, b) => a + b, 0);\n return { min, max, sum };\n}\n\n/** @return percentiles in ms */\nfunction getPercentiles(samples: number[]) {\n return {\n p25: percentile(samples, 0.25) / msToNs,\n p50: percentile(samples, 0.5) / msToNs,\n p75: percentile(samples, 0.75) / msToNs,\n p95: percentile(samples, 0.95) / msToNs,\n p99: percentile(samples, 0.99) / msToNs,\n p999: percentile(samples, 0.999) / msToNs,\n };\n}\n\n/** @return robust variability metrics */\nfunction getRobustMetrics(samplesMs: number[]) {\n const impact = getOutlierImpact(samplesMs);\n return {\n cv: coefficientOfVariation(samplesMs),\n mad: medianAbsoluteDeviation(samplesMs),\n outlierRate: impact.ratio,\n };\n}\n","import { BasicRunner } from \"./BasicRunner.ts\";\nimport type { BenchRunner } from \"./BenchRunner.ts\";\n\nexport type KnownRunner = \"basic\";\n\n/** @return benchmark runner */\nexport async function createRunner(\n _runnerName: KnownRunner,\n): Promise<BenchRunner> {\n return new BasicRunner();\n}\n","export const debugWorkerTiming = false;\n\n/** Get current time or 0 if debugging disabled */\nexport function getPerfNow(): number {\n return debugWorkerTiming ? performance.now() : 0;\n}\n\n/** Calculate elapsed milliseconds between marks */\nexport function getElapsed(startMark: number, endMark?: number): number {\n if (!debugWorkerTiming) return 0;\n const end = endMark ?? performance.now();\n return end - startMark;\n}\n"],"mappings":"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"}
|