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
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
import type { MatrixResults } from "../matrix/BenchMatrix.ts";
|
|
2
|
+
import type { MatrixReportOptions } from "../matrix/MatrixReport.ts";
|
|
3
|
+
import { reportMatrixResults } from "../matrix/MatrixReport.ts";
|
|
4
|
+
import {
|
|
5
|
+
aggregateSites,
|
|
6
|
+
filterSites,
|
|
7
|
+
flattenProfile,
|
|
8
|
+
formatHeapReport,
|
|
9
|
+
formatRawSamples,
|
|
10
|
+
type HeapReportOptions,
|
|
11
|
+
} from "../profiling/node/HeapSampleReport.ts";
|
|
12
|
+
import { resolveProfile } from "../profiling/node/ResolvedProfile.ts";
|
|
13
|
+
import type { ReportGroup, ReportSection } from "../report/BenchmarkReport.ts";
|
|
14
|
+
import { groupReports, hasField } from "../report/BenchmarkReport.ts";
|
|
15
|
+
import colors from "../report/Colors.ts";
|
|
16
|
+
import { gcStatsSection } from "../report/GcSections.ts";
|
|
17
|
+
import {
|
|
18
|
+
adaptiveSections,
|
|
19
|
+
buildTimeSection,
|
|
20
|
+
formatTierSummary,
|
|
21
|
+
optSection,
|
|
22
|
+
runsSection,
|
|
23
|
+
totalTimeSection,
|
|
24
|
+
} from "../report/StandardSections.ts";
|
|
25
|
+
import { reportResults } from "../report/text/TextReport.ts";
|
|
26
|
+
import type { DefaultCliArgs } from "./CliArgs.ts";
|
|
27
|
+
import { cliComparisonOptions } from "./CliOptions.ts";
|
|
28
|
+
|
|
29
|
+
/** Options for defaultReport: custom sections replace the CLI-derived defaults. */
|
|
30
|
+
export interface DefaultReportOptions {
|
|
31
|
+
sections?: ReportSection[];
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const { yellow, dim } = colors;
|
|
35
|
+
|
|
36
|
+
/** Show a transient status message on stderr, run a sync computation, then clear. */
|
|
37
|
+
export function withStatus<T>(msg: string, fn: () => T): T {
|
|
38
|
+
process.stderr.write(`◊ ${msg}...\r`);
|
|
39
|
+
const result = fn();
|
|
40
|
+
process.stderr.write("\r" + " ".repeat(40) + "\r");
|
|
41
|
+
return result;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/** Generate text report table with standard sections based on CLI args. */
|
|
45
|
+
export function defaultReport(
|
|
46
|
+
groups: ReportGroup[],
|
|
47
|
+
args: DefaultCliArgs,
|
|
48
|
+
opts?: DefaultReportOptions,
|
|
49
|
+
): string {
|
|
50
|
+
const sections = opts?.sections?.length
|
|
51
|
+
? opts.sections
|
|
52
|
+
: cliDefaultSections(groups, args);
|
|
53
|
+
return reportResults(groups, sections, cliComparisonOptions(args));
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/** Log V8 optimization tier distribution and deoptimizations. */
|
|
57
|
+
export function reportOptStatus(groups: ReportGroup[]): void {
|
|
58
|
+
const optData = groups.flatMap(group =>
|
|
59
|
+
groupReports(group)
|
|
60
|
+
.filter(r => r.measuredResults.optStatus)
|
|
61
|
+
.map(({ name, measuredResults: m }) => ({
|
|
62
|
+
name,
|
|
63
|
+
opt: m.optStatus!,
|
|
64
|
+
samples: m.samples.length,
|
|
65
|
+
})),
|
|
66
|
+
);
|
|
67
|
+
if (optData.length === 0) return;
|
|
68
|
+
|
|
69
|
+
console.log(dim("\nV8 optimization:"));
|
|
70
|
+
for (const { name, opt, samples } of optData) {
|
|
71
|
+
const tierParts = formatTierSummary(opt, " ", ", ");
|
|
72
|
+
console.log(` ${name}: ${tierParts} ${dim(`(${samples} samples)`)}`);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const totalDeopts = optData.reduce((sum, d) => sum + d.opt.deoptCount, 0);
|
|
76
|
+
if (totalDeopts > 0) {
|
|
77
|
+
const plural = totalDeopts > 1 ? "s" : "";
|
|
78
|
+
console.log(yellow(` ⚠ ${totalDeopts} deoptimization${plural} detected`));
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/** Print heap allocation profiles for each benchmark in the report groups. */
|
|
83
|
+
export function printHeapReports(
|
|
84
|
+
groups: ReportGroup[],
|
|
85
|
+
options: HeapReportOptions,
|
|
86
|
+
): void {
|
|
87
|
+
for (const report of groups.flatMap(g => groupReports(g))) {
|
|
88
|
+
const { heapProfile } = report.measuredResults;
|
|
89
|
+
if (!heapProfile) continue;
|
|
90
|
+
console.log(dim(`\n─── Heap profile: ${report.name} ───`));
|
|
91
|
+
const resolved = resolveProfile(heapProfile);
|
|
92
|
+
const sites = flattenProfile(resolved);
|
|
93
|
+
const userSites = filterSites(sites, options.isUserCode);
|
|
94
|
+
const agg = aggregateSites(options.userOnly ? userSites : sites);
|
|
95
|
+
const { totalBytes, sortedSamples } = resolved;
|
|
96
|
+
const totalUserCode = userSites.reduce((sum, s) => sum + s.bytes, 0);
|
|
97
|
+
const sampleCount = sortedSamples?.length;
|
|
98
|
+
const heapOpts = {
|
|
99
|
+
...options,
|
|
100
|
+
totalAll: totalBytes,
|
|
101
|
+
totalUserCode,
|
|
102
|
+
sampleCount,
|
|
103
|
+
};
|
|
104
|
+
console.log(formatHeapReport(agg, heapOpts));
|
|
105
|
+
if (options.raw) {
|
|
106
|
+
console.log(dim(`\n─── Raw samples: ${report.name} ───`));
|
|
107
|
+
console.log(formatRawSamples(resolved));
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/** Format matrix benchmark results as text, applying default sections from CLI args. */
|
|
113
|
+
export function defaultMatrixReport(
|
|
114
|
+
results: MatrixResults[],
|
|
115
|
+
reportOptions?: MatrixReportOptions,
|
|
116
|
+
args?: DefaultCliArgs,
|
|
117
|
+
): string {
|
|
118
|
+
const options = args
|
|
119
|
+
? mergeMatrixDefaults(reportOptions, args, results)
|
|
120
|
+
: reportOptions;
|
|
121
|
+
return results.map(r => reportMatrixResults(r, options)).join("\n\n");
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/** Convert MatrixResults to ReportGroup[] for the standard export pipeline. */
|
|
125
|
+
export function matrixToReportGroups(results: MatrixResults[]): ReportGroup[] {
|
|
126
|
+
return results.flatMap(matrix =>
|
|
127
|
+
matrix.variants.flatMap(variant =>
|
|
128
|
+
variant.cases.map(c => caseToReportGroup(variant.id, c)),
|
|
129
|
+
),
|
|
130
|
+
);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/** Assemble report sections from CLI flags. Under --adaptive, the
|
|
134
|
+
* adaptive section provides its own time columns and `stats` is ignored. */
|
|
135
|
+
export function buildReportSections(
|
|
136
|
+
adaptive: boolean,
|
|
137
|
+
gcStats: boolean,
|
|
138
|
+
hasOptData: boolean,
|
|
139
|
+
stats?: string,
|
|
140
|
+
): ReportSection[] {
|
|
141
|
+
return [
|
|
142
|
+
...(adaptive
|
|
143
|
+
? [...adaptiveSections, totalTimeSection]
|
|
144
|
+
: [buildTimeSection(stats)]),
|
|
145
|
+
...(gcStats ? [gcStatsSection] : []),
|
|
146
|
+
...(hasOptData ? [optSection] : []),
|
|
147
|
+
runsSection,
|
|
148
|
+
];
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/** Build sections from CLI feature flags (time/gc/opt/runs). */
|
|
152
|
+
function cliDefaultSections(
|
|
153
|
+
groups: ReportGroup[],
|
|
154
|
+
args: DefaultCliArgs,
|
|
155
|
+
): ReportSection[] {
|
|
156
|
+
const { adaptive, "gc-stats": gcStats, "trace-opt": traceOpt, stats } = args;
|
|
157
|
+
const hasOpt = hasField(groups, "optStatus");
|
|
158
|
+
return buildReportSections(adaptive, gcStats, traceOpt && hasOpt, stats);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/** Apply default sections and extra columns for matrix reports. */
|
|
162
|
+
function mergeMatrixDefaults(
|
|
163
|
+
opts: MatrixReportOptions | undefined,
|
|
164
|
+
args: DefaultCliArgs,
|
|
165
|
+
results: MatrixResults[],
|
|
166
|
+
): MatrixReportOptions {
|
|
167
|
+
const merged: MatrixReportOptions = { ...opts };
|
|
168
|
+
if (!merged.sections?.length) {
|
|
169
|
+
const groups = matrixToReportGroups(results);
|
|
170
|
+
const hasOpt = args["trace-opt"] && hasField(groups, "optStatus");
|
|
171
|
+
merged.sections = buildReportSections(
|
|
172
|
+
args.adaptive,
|
|
173
|
+
args["gc-stats"],
|
|
174
|
+
hasOpt,
|
|
175
|
+
args.stats,
|
|
176
|
+
);
|
|
177
|
+
}
|
|
178
|
+
if (!merged.comparison) merged.comparison = cliComparisonOptions(args);
|
|
179
|
+
return merged;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/** Wrap a single matrix case and its optional baseline into a ReportGroup. */
|
|
183
|
+
function caseToReportGroup(
|
|
184
|
+
variantId: string,
|
|
185
|
+
c: MatrixResults["variants"][0]["cases"][0],
|
|
186
|
+
): ReportGroup {
|
|
187
|
+
const { metadata, baseline: baselineMeasured } = c;
|
|
188
|
+
const report = { name: variantId, measuredResults: c.measured, metadata };
|
|
189
|
+
const baseline = baselineMeasured
|
|
190
|
+
? {
|
|
191
|
+
name: `${variantId} (baseline)`,
|
|
192
|
+
measuredResults: baselineMeasured,
|
|
193
|
+
metadata,
|
|
194
|
+
}
|
|
195
|
+
: undefined;
|
|
196
|
+
return { name: `${variantId} / ${c.caseId}`, reports: [report], baseline };
|
|
197
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { BenchSuite } from "../runners/BenchmarkSpec.ts";
|
|
2
2
|
|
|
3
|
-
/** Filter benchmarks by name pattern */
|
|
3
|
+
/** Filter suite benchmarks by name pattern (substring or regex). */
|
|
4
4
|
export function filterBenchmarks(
|
|
5
5
|
suite: BenchSuite,
|
|
6
6
|
filter?: string,
|
|
@@ -20,49 +20,37 @@ export function filterBenchmarks(
|
|
|
20
20
|
: undefined,
|
|
21
21
|
}))
|
|
22
22
|
.filter(group => !removeEmpty || group.benchmarks.length > 0);
|
|
23
|
-
|
|
23
|
+
if (groups.every(g => g.benchmarks.length === 0)) {
|
|
24
|
+
throw new Error(`No benchmarks match filter: "${filter}"`);
|
|
25
|
+
}
|
|
24
26
|
return { name: suite.name, groups };
|
|
25
27
|
}
|
|
26
28
|
|
|
27
|
-
/** Create regex from filter
|
|
29
|
+
/** Create regex from filter string. Uses literal prefix match unless the string looks like regex. */
|
|
28
30
|
function createFilterRegex(filter: string): RegExp {
|
|
31
|
+
const isSlashed = filter.startsWith("/") && filter.endsWith("/");
|
|
29
32
|
const looksLikeRegex =
|
|
30
|
-
|
|
31
|
-
filter
|
|
32
|
-
filter.includes("?") ||
|
|
33
|
-
filter.includes("[") ||
|
|
34
|
-
filter.includes("|") ||
|
|
33
|
+
isSlashed ||
|
|
34
|
+
/[*?[|]/.test(filter) ||
|
|
35
35
|
filter.startsWith("^") ||
|
|
36
36
|
filter.endsWith("$");
|
|
37
37
|
|
|
38
|
-
if (looksLikeRegex)
|
|
39
|
-
const pattern =
|
|
40
|
-
filter.startsWith("/") && filter.endsWith("/")
|
|
41
|
-
? filter.slice(1, -1)
|
|
42
|
-
: filter;
|
|
43
|
-
try {
|
|
44
|
-
return new RegExp(pattern, "i");
|
|
45
|
-
} catch {
|
|
46
|
-
return new RegExp(escapeRegex(filter), "i");
|
|
47
|
-
}
|
|
48
|
-
}
|
|
38
|
+
if (!looksLikeRegex) return new RegExp("^" + escapeRegex(filter), "i");
|
|
49
39
|
|
|
50
|
-
|
|
40
|
+
const pattern = isSlashed ? filter.slice(1, -1) : filter;
|
|
41
|
+
try {
|
|
42
|
+
return new RegExp(pattern, "i");
|
|
43
|
+
} catch {
|
|
44
|
+
return new RegExp(escapeRegex(filter), "i");
|
|
45
|
+
}
|
|
51
46
|
}
|
|
52
47
|
|
|
53
|
-
/** Strip case suffix like " [large]" from benchmark name for filtering */
|
|
48
|
+
/** Strip case suffix like " [large]" from benchmark name for filtering. */
|
|
54
49
|
function stripCaseSuffix(name: string): string {
|
|
55
50
|
return name.replace(/ \[.*?\]$/, "");
|
|
56
51
|
}
|
|
57
52
|
|
|
58
|
-
/**
|
|
59
|
-
function validateFilteredSuite(groups: BenchGroup[], filter?: string): void {
|
|
60
|
-
if (groups.every(g => g.benchmarks.length === 0)) {
|
|
61
|
-
throw new Error(`No benchmarks match filter: "${filter}"`);
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
/** Escape regex special characters */
|
|
53
|
+
/** Escape special regex characters for literal matching. */
|
|
66
54
|
function escapeRegex(str: string): string {
|
|
67
55
|
return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
68
56
|
}
|