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
package/src/index.ts
CHANGED
|
@@ -1,3 +1,36 @@
|
|
|
1
|
+
export type { Configure, DefaultCliArgs } from "./cli/CliArgs.ts";
|
|
2
|
+
export { browserCliArgs, defaultCliArgs, parseCliArgs } from "./cli/CliArgs.ts";
|
|
3
|
+
export type { ExportOptions, MatrixExportOptions } from "./cli/CliExport.ts";
|
|
4
|
+
export { exportReports } from "./cli/CliExport.ts";
|
|
5
|
+
export { cliToMatrixOptions } from "./cli/CliOptions.ts";
|
|
6
|
+
export {
|
|
7
|
+
defaultMatrixReport,
|
|
8
|
+
defaultReport,
|
|
9
|
+
matrixToReportGroups,
|
|
10
|
+
printHeapReports,
|
|
11
|
+
reportOptStatus,
|
|
12
|
+
} from "./cli/CliReport.ts";
|
|
13
|
+
export {
|
|
14
|
+
benchExports,
|
|
15
|
+
dispatchCli,
|
|
16
|
+
matrixBenchExports,
|
|
17
|
+
parseBenchArgs,
|
|
18
|
+
runDefaultBench,
|
|
19
|
+
runDefaultMatrixBench,
|
|
20
|
+
runMatrixSuite,
|
|
21
|
+
} from "./cli/RunBenchCLI.ts";
|
|
22
|
+
export { runBenchmarks } from "./cli/SuiteRunner.ts";
|
|
23
|
+
export {
|
|
24
|
+
buildSpeedscopeFile,
|
|
25
|
+
exportSpeedscope,
|
|
26
|
+
heapProfileToSpeedscope,
|
|
27
|
+
} from "./export/AllocExport.ts";
|
|
28
|
+
export { archiveBenchmark } from "./export/ArchiveExport.ts";
|
|
29
|
+
export type {
|
|
30
|
+
ArchiveMetadata,
|
|
31
|
+
BenchforgeArchive,
|
|
32
|
+
} from "./export/ArchiveFormat.ts";
|
|
33
|
+
export { exportPerfettoTrace } from "./export/PerfettoExport.ts";
|
|
1
34
|
export type {
|
|
2
35
|
AnyVariant,
|
|
3
36
|
BenchMatrix,
|
|
@@ -11,88 +44,74 @@ export type {
|
|
|
11
44
|
Variant,
|
|
12
45
|
VariantFn,
|
|
13
46
|
VariantResult,
|
|
14
|
-
} from "./BenchMatrix.ts";
|
|
15
|
-
export { isStatefulVariant, runMatrix } from "./BenchMatrix.ts";
|
|
16
|
-
export type {
|
|
47
|
+
} from "./matrix/BenchMatrix.ts";
|
|
48
|
+
export { isStatefulVariant, runMatrix } from "./matrix/BenchMatrix.ts";
|
|
49
|
+
export type { CasesModule } from "./matrix/CaseLoader.ts";
|
|
50
|
+
export { loadCaseData, loadCasesModule } from "./matrix/CaseLoader.ts";
|
|
51
|
+
export type { FilteredMatrix, MatrixFilter } from "./matrix/MatrixFilter.ts";
|
|
52
|
+
export { filterMatrix, parseMatrixFilter } from "./matrix/MatrixFilter.ts";
|
|
53
|
+
export type { MatrixReportOptions } from "./matrix/MatrixReport.ts";
|
|
54
|
+
export { reportMatrixResults } from "./matrix/MatrixReport.ts";
|
|
17
55
|
export type {
|
|
18
56
|
BenchmarkReport,
|
|
19
|
-
|
|
57
|
+
ComparisonOptions,
|
|
58
|
+
ReportColumn,
|
|
20
59
|
ReportGroup,
|
|
21
|
-
|
|
60
|
+
ReportSection,
|
|
22
61
|
UnknownRecord,
|
|
23
|
-
} from "./BenchmarkReport.ts";
|
|
24
|
-
export { reportResults } from "./BenchmarkReport.ts";
|
|
25
|
-
export type { Configure, DefaultCliArgs } from "./cli/CliArgs.ts";
|
|
26
|
-
export { defaultCliArgs, parseCliArgs } from "./cli/CliArgs.ts";
|
|
27
|
-
export type { ExportOptions, MatrixExportOptions } from "./cli/RunBenchCLI.ts";
|
|
62
|
+
} from "./report/BenchmarkReport.ts";
|
|
28
63
|
export {
|
|
29
|
-
|
|
30
|
-
cliToMatrixOptions,
|
|
31
|
-
defaultMatrixReport,
|
|
32
|
-
defaultReport,
|
|
33
|
-
exportReports,
|
|
64
|
+
computeColumnValues,
|
|
34
65
|
hasField,
|
|
35
|
-
|
|
36
|
-
matrixToReportGroups,
|
|
37
|
-
parseBenchArgs,
|
|
38
|
-
printHeapReports,
|
|
39
|
-
reportOptStatus,
|
|
40
|
-
runBenchmarks,
|
|
41
|
-
runDefaultBench,
|
|
42
|
-
runDefaultMatrixBench,
|
|
43
|
-
runMatrixSuite,
|
|
44
|
-
} from "./cli/RunBenchCLI.ts";
|
|
45
|
-
export * from "./export/JsonFormat.ts";
|
|
46
|
-
export { exportPerfettoTrace } from "./export/PerfettoExport.ts";
|
|
66
|
+
} from "./report/BenchmarkReport.ts";
|
|
47
67
|
export {
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
68
|
+
formatBytes,
|
|
69
|
+
formatConvergence,
|
|
70
|
+
integer,
|
|
71
|
+
timeMs,
|
|
72
|
+
truncate,
|
|
73
|
+
} from "./report/Formatters.ts";
|
|
74
|
+
export {
|
|
75
|
+
gcSection,
|
|
76
|
+
gcSections,
|
|
77
|
+
gcStatsSection,
|
|
78
|
+
} from "./report/GcSections.ts";
|
|
79
|
+
export type { GitVersion } from "./report/GitUtils.ts";
|
|
54
80
|
export {
|
|
55
|
-
formatDateWithTimezone,
|
|
56
81
|
formatGitVersion,
|
|
57
82
|
getBaselineVersion,
|
|
58
83
|
getCurrentGitVersion,
|
|
59
|
-
} from "./GitUtils.ts";
|
|
60
|
-
export type { PrepareHtmlOptions } from "./
|
|
61
|
-
export { prepareHtmlData } from "./
|
|
62
|
-
export type { HtmlReportOptions, ReportData } from "./html/index.ts";
|
|
63
|
-
export { generateHtmlReport } from "./html/index.ts";
|
|
64
|
-
export type { MeasuredResults } from "./MeasuredResults.ts";
|
|
65
|
-
export type { CasesModule } from "./matrix/CaseLoader.ts";
|
|
66
|
-
export { loadCaseData, loadCasesModule } from "./matrix/CaseLoader.ts";
|
|
67
|
-
export type { FilteredMatrix, MatrixFilter } from "./matrix/MatrixFilter.ts";
|
|
68
|
-
export { filterMatrix, parseMatrixFilter } from "./matrix/MatrixFilter.ts";
|
|
69
|
-
export type {
|
|
70
|
-
ExtraColumn,
|
|
71
|
-
MatrixReportOptions,
|
|
72
|
-
} from "./matrix/MatrixReport.ts";
|
|
84
|
+
} from "./report/GitUtils.ts";
|
|
85
|
+
export type { PrepareHtmlOptions } from "./report/HtmlReport.ts";
|
|
86
|
+
export { prepareHtmlData } from "./report/HtmlReport.ts";
|
|
73
87
|
export {
|
|
74
|
-
|
|
75
|
-
gcStatsColumns,
|
|
76
|
-
heapTotalColumn,
|
|
77
|
-
reportMatrixResults,
|
|
78
|
-
} from "./matrix/MatrixReport.ts";
|
|
79
|
-
export type { RunnerOptions } from "./runners/BenchRunner.ts";
|
|
80
|
-
export {
|
|
81
|
-
adaptiveSection,
|
|
88
|
+
adaptiveSections,
|
|
82
89
|
buildGenericSections,
|
|
83
|
-
|
|
84
|
-
gcSection,
|
|
85
|
-
gcStatsSection,
|
|
90
|
+
buildTimeSection,
|
|
86
91
|
optSection,
|
|
87
92
|
runsSection,
|
|
88
93
|
timeSection,
|
|
89
94
|
totalTimeSection,
|
|
90
|
-
} from "./StandardSections.ts";
|
|
91
|
-
export {
|
|
92
|
-
export {
|
|
95
|
+
} from "./report/StandardSections.ts";
|
|
96
|
+
export { reportResults } from "./report/text/TextReport.ts";
|
|
97
|
+
export type {
|
|
98
|
+
BenchGroup,
|
|
99
|
+
BenchmarkSpec,
|
|
100
|
+
BenchSuite,
|
|
101
|
+
} from "./runners/BenchmarkSpec.ts";
|
|
102
|
+
export type { RunnerOptions } from "./runners/BenchRunner.ts";
|
|
103
|
+
export type { MeasuredResults } from "./runners/MeasuredResults.ts";
|
|
93
104
|
export {
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
105
|
+
average,
|
|
106
|
+
computeStat,
|
|
107
|
+
isBootstrappable,
|
|
108
|
+
maxBootstrapInput,
|
|
109
|
+
median,
|
|
110
|
+
percentile,
|
|
111
|
+
type StatKind,
|
|
112
|
+
} from "./stats/StatisticalUtils.ts";
|
|
113
|
+
export {
|
|
114
|
+
formatDateWithTimezone,
|
|
115
|
+
formatRelativeTime,
|
|
116
|
+
} from "./viewer/DateFormat.ts";
|
|
117
|
+
export type { ReportData } from "./viewer/ReportData.ts";
|
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
import type { RunnerOptions } from "../runners/BenchRunner.ts";
|
|
2
|
+
import type { MeasuredResults } from "../runners/MeasuredResults.ts";
|
|
3
|
+
import { average } from "../stats/StatisticalUtils.ts";
|
|
4
|
+
import type { CasesModule } from "./CaseLoader.ts";
|
|
5
|
+
import { loadCasesModule } from "./CaseLoader.ts";
|
|
6
|
+
import { runMatrixWithDir } from "./MatrixDirRunner.ts";
|
|
7
|
+
import { runMatrixInline } from "./MatrixInlineRunner.ts";
|
|
8
|
+
|
|
9
|
+
/** Stateless variant - called each iteration with case data */
|
|
10
|
+
export type VariantFn<T = unknown> = (caseData: T) => void;
|
|
11
|
+
|
|
12
|
+
/** Stateful variant - setup once, run many */
|
|
13
|
+
export interface StatefulVariant<T = unknown, S = unknown> {
|
|
14
|
+
setup: (caseData: T) => S | Promise<S>;
|
|
15
|
+
run: (state: S) => void;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/** A variant is either a plain function or a stateful setup+run pair */
|
|
19
|
+
export type Variant<T = unknown, S = unknown> =
|
|
20
|
+
| VariantFn<T>
|
|
21
|
+
| StatefulVariant<T, S>;
|
|
22
|
+
|
|
23
|
+
/** Variant with any state type, allowing mixed variants in a matrix */
|
|
24
|
+
export type AnyVariant<T = unknown> = VariantFn<T> | StatefulVariant<T, any>;
|
|
25
|
+
|
|
26
|
+
/** Case data and optional metadata returned by a cases module */
|
|
27
|
+
export interface LoadedCase<T = unknown> {
|
|
28
|
+
data: T;
|
|
29
|
+
metadata?: Record<string, unknown>;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/** Default runner settings applied to all matrix benchmarks */
|
|
33
|
+
export interface MatrixDefaults {
|
|
34
|
+
warmup?: number;
|
|
35
|
+
maxTime?: number;
|
|
36
|
+
iterations?: number;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/** Configuration for a cases x variants benchmark matrix */
|
|
40
|
+
export interface BenchMatrix<T = unknown> {
|
|
41
|
+
name: string;
|
|
42
|
+
variantDir?: string;
|
|
43
|
+
variants?: Record<string, AnyVariant<T>>;
|
|
44
|
+
cases?: string[];
|
|
45
|
+
casesModule?: string;
|
|
46
|
+
baselineDir?: string;
|
|
47
|
+
baselineVariant?: string;
|
|
48
|
+
defaults?: MatrixDefaults;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/** Named collection of benchmark matrices */
|
|
52
|
+
export interface MatrixSuite {
|
|
53
|
+
name: string;
|
|
54
|
+
matrices: BenchMatrix<any>[];
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/** Results for a single variant across all cases */
|
|
58
|
+
export interface VariantResult {
|
|
59
|
+
id: string;
|
|
60
|
+
cases: CaseResult[];
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/** Results for a single (variant, case) pair */
|
|
64
|
+
export interface CaseResult {
|
|
65
|
+
caseId: string;
|
|
66
|
+
measured: MeasuredResults;
|
|
67
|
+
metadata?: Record<string, unknown>;
|
|
68
|
+
baseline?: MeasuredResults;
|
|
69
|
+
deltaPercent?: number;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/** Aggregated results from running a benchmark matrix */
|
|
73
|
+
export interface MatrixResults {
|
|
74
|
+
name: string;
|
|
75
|
+
variants: VariantResult[];
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/** Options for {@link runMatrix} */
|
|
79
|
+
export interface RunMatrixOptions {
|
|
80
|
+
/** Maximum iterations per benchmark */
|
|
81
|
+
iterations?: number;
|
|
82
|
+
/** Maximum time in ms per benchmark */
|
|
83
|
+
maxTime?: number;
|
|
84
|
+
/** Number of warmup iterations before measurement */
|
|
85
|
+
warmup?: number;
|
|
86
|
+
/** Use worker process isolation (default: true for variantDir) */
|
|
87
|
+
useWorker?: boolean;
|
|
88
|
+
/** Number of interleaved batches for baseline comparison */
|
|
89
|
+
batches?: number;
|
|
90
|
+
/** Include first batch in results (normally dropped for OS cache warmup) */
|
|
91
|
+
warmupBatch?: boolean;
|
|
92
|
+
/** Run only these cases (from --filter) */
|
|
93
|
+
filteredCases?: string[];
|
|
94
|
+
/** Run only these variants (from --filter) */
|
|
95
|
+
filteredVariants?: string[];
|
|
96
|
+
/** Force garbage collection between iterations */
|
|
97
|
+
gcForce?: boolean;
|
|
98
|
+
/** Track V8 optimization/deoptimization events */
|
|
99
|
+
traceOpt?: boolean;
|
|
100
|
+
/** Pause duration in ms before warmup begins */
|
|
101
|
+
pauseWarmup?: number;
|
|
102
|
+
/** Pause duration in ms before first measurement */
|
|
103
|
+
pauseFirst?: number;
|
|
104
|
+
/** Pause every N iterations during measurement */
|
|
105
|
+
pauseInterval?: number;
|
|
106
|
+
/** Duration of each pause in ms */
|
|
107
|
+
pauseDuration?: number;
|
|
108
|
+
/** Collect GC statistics via --trace-gc-nvp */
|
|
109
|
+
gcStats?: boolean;
|
|
110
|
+
/** Enable heap allocation profiling */
|
|
111
|
+
alloc?: boolean;
|
|
112
|
+
/** Heap sampling interval in bytes */
|
|
113
|
+
allocInterval?: number;
|
|
114
|
+
/** Maximum stack depth for allocation traces */
|
|
115
|
+
allocDepth?: number;
|
|
116
|
+
/** Enable CPU time profiling */
|
|
117
|
+
profile?: boolean;
|
|
118
|
+
/** CPU profiling sample interval in microseconds */
|
|
119
|
+
profileInterval?: number;
|
|
120
|
+
/** Track function call counts via V8 coverage */
|
|
121
|
+
callCounts?: boolean;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/** Run a BenchMatrix with inline variants or variantDir */
|
|
125
|
+
export async function runMatrix<T>(
|
|
126
|
+
matrix: BenchMatrix<T>,
|
|
127
|
+
options: RunMatrixOptions = {},
|
|
128
|
+
): Promise<MatrixResults> {
|
|
129
|
+
if (matrix.baselineDir && matrix.baselineVariant)
|
|
130
|
+
throw new Error(
|
|
131
|
+
"BenchMatrix cannot have both 'baselineDir' and 'baselineVariant'",
|
|
132
|
+
);
|
|
133
|
+
if (!matrix.variantDir && !matrix.variants)
|
|
134
|
+
throw new Error("BenchMatrix requires either 'variants' or 'variantDir'");
|
|
135
|
+
|
|
136
|
+
const effectiveOptions = { ...matrix.defaults, ...options };
|
|
137
|
+
const result = matrix.variantDir
|
|
138
|
+
? await runMatrixWithDir(matrix, effectiveOptions)
|
|
139
|
+
: await runMatrixInline(matrix, effectiveOptions);
|
|
140
|
+
|
|
141
|
+
if (matrix.baselineVariant) {
|
|
142
|
+
applyBaselineVariant(result.variants, matrix.baselineVariant);
|
|
143
|
+
}
|
|
144
|
+
return result;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/** Prepare a benchmark function from a variant, calling setup if stateful. */
|
|
148
|
+
export async function prepareBenchFn<T>(
|
|
149
|
+
variant: Variant<T>,
|
|
150
|
+
data: T,
|
|
151
|
+
): Promise<() => void> {
|
|
152
|
+
if (isStatefulVariant(variant)) {
|
|
153
|
+
const state = await variant.setup(data);
|
|
154
|
+
return () => variant.run(state);
|
|
155
|
+
}
|
|
156
|
+
return () => variant(data);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/** Type guard for StatefulVariant */
|
|
160
|
+
export function isStatefulVariant<T, S>(
|
|
161
|
+
v: Variant<T, S>,
|
|
162
|
+
): v is StatefulVariant<T, S> {
|
|
163
|
+
return typeof v === "object" && "setup" in v && "run" in v;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/** Apply baselineVariant comparison - one variant is the reference for all others */
|
|
167
|
+
export function applyBaselineVariant(
|
|
168
|
+
variants: VariantResult[],
|
|
169
|
+
baselineVariantId: string,
|
|
170
|
+
): void {
|
|
171
|
+
const baselineVariant = variants.find(v => v.id === baselineVariantId);
|
|
172
|
+
if (!baselineVariant) return;
|
|
173
|
+
|
|
174
|
+
const baselineByCase = new Map(
|
|
175
|
+
baselineVariant.cases.map(c => [c.caseId, c.measured]),
|
|
176
|
+
);
|
|
177
|
+
|
|
178
|
+
for (const variant of variants) {
|
|
179
|
+
if (variant.id === baselineVariantId) continue;
|
|
180
|
+
for (const cr of variant.cases) {
|
|
181
|
+
const base = baselineByCase.get(cr.caseId);
|
|
182
|
+
if (base) {
|
|
183
|
+
cr.baseline = base;
|
|
184
|
+
cr.deltaPercent = computeDeltaPercent(base, cr.measured);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/** Load cases module and resolve filtered case IDs */
|
|
191
|
+
export async function resolveCases<T>(
|
|
192
|
+
matrix: BenchMatrix<T>,
|
|
193
|
+
options: RunMatrixOptions,
|
|
194
|
+
): Promise<{ casesModule: CasesModule<T> | undefined; caseIds: string[] }> {
|
|
195
|
+
const casesModule = matrix.casesModule
|
|
196
|
+
? await loadCasesModule<T>(matrix.casesModule)
|
|
197
|
+
: undefined;
|
|
198
|
+
const allCaseIds = casesModule?.cases ?? matrix.cases ?? ["default"];
|
|
199
|
+
const caseIds = options.filteredCases ?? allCaseIds;
|
|
200
|
+
return { casesModule, caseIds };
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
/** Map matrix options to runner options, applying defaults for maxTime and warmup */
|
|
204
|
+
export function buildRunnerOptions(opts: RunMatrixOptions): RunnerOptions {
|
|
205
|
+
const {
|
|
206
|
+
filteredCases,
|
|
207
|
+
filteredVariants,
|
|
208
|
+
useWorker,
|
|
209
|
+
batches,
|
|
210
|
+
warmupBatch,
|
|
211
|
+
...base
|
|
212
|
+
} = opts;
|
|
213
|
+
const { iterations, maxTime, warmup, ...rest } = base;
|
|
214
|
+
return {
|
|
215
|
+
maxIterations: iterations,
|
|
216
|
+
maxTime: maxTime ?? (iterations ? undefined : 1000),
|
|
217
|
+
warmup: warmup ?? 0,
|
|
218
|
+
...rest,
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
/** Compute percentage change of current vs baseline mean */
|
|
223
|
+
export function computeDeltaPercent(
|
|
224
|
+
base: MeasuredResults,
|
|
225
|
+
cur: MeasuredResults,
|
|
226
|
+
): number {
|
|
227
|
+
const avg = average(base.samples);
|
|
228
|
+
if (avg === 0) return 0;
|
|
229
|
+
return ((average(cur.samples) - avg) / avg) * 100;
|
|
230
|
+
}
|
package/src/matrix/CaseLoader.ts
CHANGED
|
@@ -1,14 +1,16 @@
|
|
|
1
|
-
import type { LoadedCase } from "
|
|
1
|
+
import type { LoadedCase } from "./BenchMatrix.ts";
|
|
2
2
|
|
|
3
|
-
/** Module
|
|
3
|
+
/** Module exporting case IDs and an optional loader for case data */
|
|
4
4
|
export interface CasesModule<T = unknown> {
|
|
5
5
|
cases: string[];
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
/** Subset of cases for quick runs */
|
|
7
|
+
defaultCases?: string[];
|
|
8
|
+
/** Subset of variants for quick runs */
|
|
9
|
+
defaultVariants?: string[];
|
|
8
10
|
loadCase?: (id: string) => LoadedCase<T> | Promise<LoadedCase<T>>;
|
|
9
11
|
}
|
|
10
12
|
|
|
11
|
-
/**
|
|
13
|
+
/** Import and validate a cases module, which must export a `cases` array */
|
|
12
14
|
export async function loadCasesModule<T = unknown>(
|
|
13
15
|
moduleUrl: string,
|
|
14
16
|
): Promise<CasesModule<T>> {
|
|
@@ -24,7 +26,7 @@ export async function loadCasesModule<T = unknown>(
|
|
|
24
26
|
};
|
|
25
27
|
}
|
|
26
28
|
|
|
27
|
-
/** Load case data from a CasesModule or
|
|
29
|
+
/** Load case data from a CasesModule, or use the caseId as data if no module */
|
|
28
30
|
export async function loadCaseData<T>(
|
|
29
31
|
casesModule: CasesModule<T> | undefined,
|
|
30
32
|
caseId: string,
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import type { RunnerOptions } from "../runners/BenchRunner.ts";
|
|
2
|
+
import type { MeasuredResults } from "../runners/MeasuredResults.ts";
|
|
3
|
+
import { runBatched } from "../runners/MergeBatches.ts";
|
|
4
|
+
import { runMatrixVariant } from "../runners/RunnerOrchestrator.ts";
|
|
5
|
+
import type {
|
|
6
|
+
BenchMatrix,
|
|
7
|
+
CaseResult,
|
|
8
|
+
RunMatrixOptions,
|
|
9
|
+
VariantResult,
|
|
10
|
+
} from "./BenchMatrix.ts";
|
|
11
|
+
import {
|
|
12
|
+
buildRunnerOptions,
|
|
13
|
+
computeDeltaPercent,
|
|
14
|
+
resolveCases,
|
|
15
|
+
} from "./BenchMatrix.ts";
|
|
16
|
+
import type { CasesModule } from "./CaseLoader.ts";
|
|
17
|
+
import { loadCaseData } from "./CaseLoader.ts";
|
|
18
|
+
import { discoverVariants } from "./VariantLoader.ts";
|
|
19
|
+
|
|
20
|
+
type VariantArgs = Parameters<typeof runMatrixVariant>[0];
|
|
21
|
+
|
|
22
|
+
/** Shared state for directory-based matrix execution */
|
|
23
|
+
interface DirMatrixContext<T> {
|
|
24
|
+
matrix: BenchMatrix<T>;
|
|
25
|
+
casesModule?: CasesModule<T>;
|
|
26
|
+
baselineIds: string[];
|
|
27
|
+
caseIds: string[];
|
|
28
|
+
runnerOpts: RunnerOptions;
|
|
29
|
+
batches: number;
|
|
30
|
+
warmupBatch: boolean;
|
|
31
|
+
useWorker: boolean;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/** Run matrix using variant files from a directory, each in a worker process */
|
|
35
|
+
export async function runMatrixWithDir<T>(
|
|
36
|
+
matrix: BenchMatrix<T>,
|
|
37
|
+
options: RunMatrixOptions,
|
|
38
|
+
): Promise<{ name: string; variants: VariantResult[] }> {
|
|
39
|
+
const allVariantIds = await discoverVariants(matrix.variantDir!);
|
|
40
|
+
if (allVariantIds.length === 0) {
|
|
41
|
+
throw new Error(`No variants found in ${matrix.variantDir}`);
|
|
42
|
+
}
|
|
43
|
+
const variantIds = options.filteredVariants ?? allVariantIds;
|
|
44
|
+
|
|
45
|
+
const ctx = await createDirContext(matrix, options);
|
|
46
|
+
const variants = await runDirVariants(variantIds, ctx);
|
|
47
|
+
return { name: matrix.name, variants };
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/** Create context for directory-based matrix execution */
|
|
51
|
+
async function createDirContext<T>(
|
|
52
|
+
matrix: BenchMatrix<T>,
|
|
53
|
+
options: RunMatrixOptions,
|
|
54
|
+
): Promise<DirMatrixContext<T>> {
|
|
55
|
+
const baselineIds = matrix.baselineDir
|
|
56
|
+
? await discoverVariants(matrix.baselineDir)
|
|
57
|
+
: [];
|
|
58
|
+
const { casesModule, caseIds } = await resolveCases(matrix, options);
|
|
59
|
+
const runnerOpts = buildRunnerOptions(options);
|
|
60
|
+
const { batches = 1, warmupBatch = false, useWorker = true } = options;
|
|
61
|
+
return {
|
|
62
|
+
matrix,
|
|
63
|
+
casesModule,
|
|
64
|
+
baselineIds,
|
|
65
|
+
caseIds,
|
|
66
|
+
runnerOpts,
|
|
67
|
+
batches,
|
|
68
|
+
warmupBatch,
|
|
69
|
+
useWorker,
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/** Run all variants sequentially, collecting per-case results */
|
|
74
|
+
async function runDirVariants<T>(
|
|
75
|
+
variantIds: string[],
|
|
76
|
+
ctx: DirMatrixContext<T>,
|
|
77
|
+
): Promise<VariantResult[]> {
|
|
78
|
+
const variants: VariantResult[] = [];
|
|
79
|
+
for (const id of variantIds) {
|
|
80
|
+
const cases = await runDirVariantCases(id, ctx);
|
|
81
|
+
variants.push({ id, cases });
|
|
82
|
+
}
|
|
83
|
+
return variants;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/** Run all cases for a single variant */
|
|
87
|
+
async function runDirVariantCases<T>(
|
|
88
|
+
variantId: string,
|
|
89
|
+
ctx: DirMatrixContext<T>,
|
|
90
|
+
): Promise<CaseResult[]> {
|
|
91
|
+
const { matrix, casesModule, caseIds, runnerOpts, batches } = ctx;
|
|
92
|
+
const cases: CaseResult[] = [];
|
|
93
|
+
|
|
94
|
+
for (const caseId of caseIds) {
|
|
95
|
+
const caseData = matrix.cases && !matrix.casesModule ? caseId : undefined;
|
|
96
|
+
const variantArgs: VariantArgs = {
|
|
97
|
+
variantDir: matrix.variantDir!,
|
|
98
|
+
variantId,
|
|
99
|
+
caseId,
|
|
100
|
+
caseData,
|
|
101
|
+
casesModule: matrix.casesModule,
|
|
102
|
+
runner: "timing" as const,
|
|
103
|
+
options: runnerOpts,
|
|
104
|
+
useWorker: ctx.useWorker,
|
|
105
|
+
};
|
|
106
|
+
const baselineArgs =
|
|
107
|
+
matrix.baselineDir && ctx.baselineIds.includes(variantId)
|
|
108
|
+
? { ...variantArgs, variantDir: matrix.baselineDir! }
|
|
109
|
+
: undefined;
|
|
110
|
+
|
|
111
|
+
const { metadata } = await loadCaseData(casesModule, caseId);
|
|
112
|
+
const { measured, baseline } =
|
|
113
|
+
batches > 1
|
|
114
|
+
? await runCaseBatched(variantArgs, baselineArgs, ctx)
|
|
115
|
+
: await runCaseSingle(variantArgs, baselineArgs);
|
|
116
|
+
const deltaPercent = baseline
|
|
117
|
+
? computeDeltaPercent(baseline, measured)
|
|
118
|
+
: undefined;
|
|
119
|
+
cases.push({ caseId, measured, metadata, baseline, deltaPercent });
|
|
120
|
+
}
|
|
121
|
+
return cases;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/** Run a batched measurement for a case, alternating current/baseline order. */
|
|
125
|
+
async function runCaseBatched<T>(
|
|
126
|
+
variantArgs: VariantArgs,
|
|
127
|
+
baselineArgs: VariantArgs | undefined,
|
|
128
|
+
ctx: DirMatrixContext<T>,
|
|
129
|
+
): Promise<{ measured: MeasuredResults; baseline?: MeasuredResults }> {
|
|
130
|
+
const runCurrent = async () => (await runMatrixVariant(variantArgs))[0];
|
|
131
|
+
const runBase = baselineArgs
|
|
132
|
+
? async () => (await runMatrixVariant(baselineArgs))[0]
|
|
133
|
+
: undefined;
|
|
134
|
+
const { results, baseline } = await runBatched(
|
|
135
|
+
[runCurrent],
|
|
136
|
+
runBase,
|
|
137
|
+
ctx.batches,
|
|
138
|
+
ctx.warmupBatch,
|
|
139
|
+
);
|
|
140
|
+
return { measured: results[0], baseline };
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/** Run a single unbatched measurement for a case. */
|
|
144
|
+
async function runCaseSingle(
|
|
145
|
+
variantArgs: VariantArgs,
|
|
146
|
+
baselineArgs: VariantArgs | undefined,
|
|
147
|
+
): Promise<{ measured: MeasuredResults; baseline?: MeasuredResults }> {
|
|
148
|
+
const [measured] = await runMatrixVariant(variantArgs);
|
|
149
|
+
const baseline = baselineArgs
|
|
150
|
+
? (await runMatrixVariant(baselineArgs))[0]
|
|
151
|
+
: undefined;
|
|
152
|
+
return { measured, baseline };
|
|
153
|
+
}
|