benchforge 0.1.9 → 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 -260
- 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-DglX1NOn.d.mts +302 -0
- 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 +731 -522
- 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 +92 -120
- 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 -26
- 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 -48
- 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 +138 -844
- 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 +91 -126
- package/src/export/SpeedscopeTypes.ts +98 -0
- package/src/export/TimeExport.ts +115 -0
- package/src/index.ts +87 -62
- 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 +55 -53
- package/src/matrix/MatrixInlineRunner.ts +50 -0
- package/src/matrix/MatrixReport.ts +94 -254
- package/src/matrix/VariantLoader.ts +9 -9
- 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 +55 -13
- package/src/profiling/node/ResolvedProfile.ts +98 -0
- 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 +167 -287
- package/src/runners/BenchRunner.ts +27 -22
- package/src/{Benchmark.ts → runners/BenchmarkSpec.ts} +5 -6
- package/src/runners/CreateRunner.ts +5 -7
- package/src/runners/GcStats.ts +58 -61
- 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 +180 -296
- 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 +162 -178
- package/src/stats/BootstrapDifference.ts +282 -0
- package/src/{PermutationTest.ts → stats/PermutationTest.ts} +31 -40
- 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 +9 -41
- package/src/{tests → test}/BenchMatrix.test.ts +31 -28
- 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 +51 -0
- package/src/{tests → test}/MatrixFilter.test.ts +16 -16
- 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 +57 -56
- 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 +35 -30
- 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 +42 -47
- 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/BenchRunner-CSKN9zPy.d.mts +0 -225
- package/dist/BrowserHeapSampler-DCeL42RE.mjs +0 -202
- package/dist/BrowserHeapSampler-DCeL42RE.mjs.map +0 -1
- package/dist/GcStats-ByEovUi1.mjs +0 -77
- package/dist/GcStats-ByEovUi1.mjs.map +0 -1
- package/dist/HeapSampler-B8dtKHn1.mjs.map +0 -1
- package/dist/TimingUtils-ClclVQ7E.mjs +0 -597
- package/dist/TimingUtils-ClclVQ7E.mjs.map +0 -1
- package/dist/browser/index.js +0 -914
- package/dist/src-Cf_LXwlp.mjs +0 -2873
- package/dist/src-Cf_LXwlp.mjs.map +0 -1
- package/src/BenchMatrix.ts +0 -380
- package/src/BenchmarkReport.ts +0 -156
- package/src/HtmlDataPrep.ts +0 -148
- package/src/StandardSections.ts +0 -261
- package/src/StatisticalUtils.ts +0 -176
- 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/heap-sample/HeapSampleReport.ts +0 -196
- 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 -152
- 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 +9 -9
package/src/cli/CliArgs.ts
CHANGED
|
@@ -1,72 +1,188 @@
|
|
|
1
1
|
import type { Argv, InferredOptionTypes } from "yargs";
|
|
2
2
|
import yargs from "yargs";
|
|
3
3
|
|
|
4
|
-
export const defaultAdaptiveMaxTime = 20;
|
|
5
|
-
|
|
6
4
|
export type Configure<T> = (yargs: Argv) => Argv<T>;
|
|
7
5
|
|
|
8
|
-
/** CLI args type inferred from cliOptions, plus optional file positional */
|
|
6
|
+
/** CLI args type inferred from cliOptions, plus optional file positional. */
|
|
9
7
|
export type DefaultCliArgs = InferredOptionTypes<typeof cliOptions> & {
|
|
10
8
|
file?: string;
|
|
11
9
|
};
|
|
12
10
|
|
|
13
11
|
// biome-ignore format: compact option definitions
|
|
14
12
|
const cliOptions = {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
"
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
html: { type: "boolean", default: false, describe: "generate HTML report and open in browser" },
|
|
28
|
-
"export-html": { type: "string", requiresArg: true, describe: "export HTML report to specified file" },
|
|
29
|
-
json: { type: "string", requiresArg: true, describe: "export benchmark data to JSON file" },
|
|
30
|
-
perfetto: { type: "string", requiresArg: true, describe: "export Perfetto trace file (view at ui.perfetto.dev)" },
|
|
31
|
-
"trace-opt": { type: "boolean", default: false, describe: "trace V8 optimization tiers (requires --allow-natives-syntax)" },
|
|
32
|
-
"skip-settle": { type: "boolean", default: false, describe: "skip post-warmup settle time (see V8 optimization cold start)" },
|
|
33
|
-
"pause-first": { type: "number", describe: "iterations before first pause (then pause-interval applies)" },
|
|
13
|
+
duration: { type: "number", requiresArg: true, describe: "duration per batch in seconds (default: 0.642)" },
|
|
14
|
+
iterations: { type: "number", requiresArg: true, describe: "iterations per batch (page loads for page-load mode, inner loop for bench)" },
|
|
15
|
+
warmup: { type: "number", default: 0, describe: "warmup iterations before measurement" },
|
|
16
|
+
filter: { type: "string", requiresArg: true, describe: "filter by name/regex. Matrix: case/variant, case/, /variant" },
|
|
17
|
+
all: { type: "boolean", default: false, describe: "run all cases (ignore defaultCases)" },
|
|
18
|
+
list: { type: "boolean", default: false, describe: "list available benchmarks (or matrix cases/variants)" },
|
|
19
|
+
worker: { type: "boolean", default: true, describe: "run in worker process for isolation (default: true)" },
|
|
20
|
+
batches: { type: "number", default: 1, describe: "divide time into N batches, alternating baseline/current order" },
|
|
21
|
+
"warmup-batch": { type: "boolean", default: false, describe: "include first batch in results (normally dropped to avoid OS cache warmup)" },
|
|
22
|
+
"equiv-margin": { type: "number", default: 2, describe: "equivalence margin % for baseline comparison (0 to disable)" },
|
|
23
|
+
"no-batch-trim": { type: "boolean", default: false, describe: "disable Tukey trimming of outlier batches" },
|
|
24
|
+
"pause-first": { type: "number", describe: "iterations before first pause (then pause-interval applies)" },
|
|
34
25
|
"pause-interval": { type: "number", default: 0, describe: "iterations between pauses for V8 optimization (0 to disable)" },
|
|
35
26
|
"pause-duration": { type: "number", default: 100, describe: "pause duration in ms for V8 optimization" },
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
"
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
"
|
|
43
|
-
"
|
|
44
|
-
"
|
|
27
|
+
"gc-stats": { type: "boolean", default: false, describe: "collect GC statistics (Node: --trace-gc-nvp, browser: CDP tracing)" },
|
|
28
|
+
"gc-force": { type: "boolean", default: false, describe: "force GC after each iteration" },
|
|
29
|
+
adaptive: { type: "boolean", default: false, describe: "adaptive sampling (experimental)" },
|
|
30
|
+
"min-time": { type: "number", default: 1, describe: "minimum time before adaptive convergence can stop" },
|
|
31
|
+
convergence: { type: "number", default: 95, describe: "adaptive confidence threshold (0-100)" },
|
|
32
|
+
alloc: { type: "boolean", default: false, describe: "allocation sampling attribution (includes garbage)" },
|
|
33
|
+
"alloc-interval": { type: "number", default: 32768, describe: "allocation sampling interval in bytes" },
|
|
34
|
+
"alloc-depth": { type: "number", default: 64, describe: "allocation sampling stack depth" },
|
|
35
|
+
"alloc-rows": { type: "number", default: 20, describe: "top allocation sites to show" },
|
|
36
|
+
"alloc-stack": { type: "number", default: 3, describe: "call stack depth to display" },
|
|
37
|
+
"alloc-verbose": { type: "boolean", default: false, describe: "verbose output with file:// paths and line numbers" },
|
|
38
|
+
"alloc-raw": { type: "boolean", default: false, describe: "dump every raw allocation sample (ordinal, size, stack)" },
|
|
39
|
+
"alloc-user-only":{ type: "boolean", default: false, describe: "filter to user code only (hide node internals)" },
|
|
40
|
+
profile: { type: "boolean", default: false, alias: "time-sample", describe: "V8 CPU time sampling profiler" },
|
|
41
|
+
"profile-interval":{ type: "number", default: 1000, alias: "time-interval", describe: "CPU sampling interval in microseconds" },
|
|
42
|
+
"call-counts": { type: "boolean", default: false, describe: "collect per-function execution counts via V8 precise coverage" },
|
|
43
|
+
stats: { type: "string", default: "mean,p50,p99", describe: "timing columns: mean|median|min|max|p<N> (e.g. mean,p70,p99)" },
|
|
44
|
+
view: { type: "boolean", default: false, alias: "html", describe: "open viewer in browser" },
|
|
45
|
+
"view-serve": { type: "boolean", default: false, describe: "start viewer server without opening browser (reload an existing tab)" },
|
|
46
|
+
"export-perfetto":{ type: "string", requiresArg: true, describe: "export Perfetto trace file (view at ui.perfetto.dev)" },
|
|
47
|
+
"export-profile": { type: "string", requiresArg: true, alias: "export-time", describe: "export CPU profile as .cpuprofile (V8/Chrome DevTools format)" },
|
|
48
|
+
archive: { type: "string", describe: "archive profile + sources to .benchforge file" },
|
|
49
|
+
editor: { type: "string", default: "vscode", describe: "editor for source links: vscode, cursor, or custom://scheme" },
|
|
50
|
+
inspect: { type: "boolean", default: false, describe: "run once for external profiler attach" },
|
|
51
|
+
"trace-opt": { type: "boolean", default: false, describe: "trace V8 optimization tiers (requires --allow-natives-syntax)" },
|
|
52
|
+
"pause-warmup": { type: "number", default: 0, requiresArg: true, describe: "post-warmup settle time in ms for V8 background compilation (0 to skip)" },
|
|
45
53
|
url: { type: "string", requiresArg: true, describe: "page URL for browser profiling (enables browser mode)" },
|
|
46
|
-
|
|
54
|
+
"page-load": { type: "boolean", default: false, describe: "passive page-load profiling (no __bench needed)" },
|
|
55
|
+
"wait-for": { type: "string", requiresArg: true, describe: "page-load completion: CSS selector, JS expression, 'load', or 'domcontentloaded'" },
|
|
56
|
+
headless: { type: "boolean", default: false, describe: "run browser in headless mode (default: headed)" },
|
|
47
57
|
timeout: { type: "number", default: 60, describe: "browser page timeout in seconds" },
|
|
58
|
+
chrome: { type: "string", requiresArg: true, describe: "Chrome binary path (default: auto-detect or CHROME_PATH)" },
|
|
59
|
+
"chrome-profile": { type: "string", requiresArg: true, describe: "Chrome user profile directory (default: temp profile)" },
|
|
60
|
+
"baseline-url": { type: "string", requiresArg: true, describe: "baseline URL for A/B comparison (fresh tab per batch)" },
|
|
48
61
|
"chrome-args": { type: "string", array: true, requiresArg: true, describe: "extra Chromium flags" },
|
|
49
62
|
} as const;
|
|
50
63
|
|
|
51
|
-
|
|
52
|
-
export
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
}
|
|
64
|
+
export const defaultDuration = 0.642;
|
|
65
|
+
export const defaultAdaptiveMaxTime = 20;
|
|
66
|
+
|
|
67
|
+
/** Default values for all CLI options, including alias keys for yargs filtering. */
|
|
68
|
+
export const cliDefaults: Record<string, unknown> = Object.fromEntries(
|
|
69
|
+
Object.entries(cliOptions)
|
|
70
|
+
.filter(([, opt]) => "default" in opt)
|
|
71
|
+
.flatMap(([key, opt]) => {
|
|
72
|
+
const o = opt as Record<string, unknown>;
|
|
73
|
+
const entries: [string, unknown][] = [[key, o.default]];
|
|
74
|
+
if (o.alias) entries.push([o.alias as string, o.default]);
|
|
75
|
+
return entries;
|
|
76
|
+
}),
|
|
77
|
+
);
|
|
78
|
+
|
|
79
|
+
const optionGroups = {
|
|
80
|
+
"Run:": ["duration", "iterations"],
|
|
81
|
+
"Batching:": ["batches", "warmup-batch", "no-batch-trim"],
|
|
82
|
+
"Node:": ["worker", "inspect"],
|
|
83
|
+
"Browser:": [
|
|
84
|
+
"url",
|
|
85
|
+
"baseline-url",
|
|
86
|
+
"page-load",
|
|
87
|
+
"wait-for",
|
|
88
|
+
"headless",
|
|
89
|
+
"timeout",
|
|
90
|
+
"chrome",
|
|
91
|
+
"chrome-profile",
|
|
92
|
+
"chrome-args",
|
|
93
|
+
],
|
|
94
|
+
"GC:": ["gc-stats", "gc-force"],
|
|
95
|
+
"Allocation Profiling:": [
|
|
96
|
+
"alloc",
|
|
97
|
+
"alloc-interval",
|
|
98
|
+
"alloc-depth",
|
|
99
|
+
"alloc-rows",
|
|
100
|
+
"alloc-stack",
|
|
101
|
+
"alloc-verbose",
|
|
102
|
+
"alloc-raw",
|
|
103
|
+
"alloc-user-only",
|
|
104
|
+
],
|
|
105
|
+
"CPU Profiling:": ["profile", "profile-interval", "call-counts"],
|
|
106
|
+
"Output:": [
|
|
107
|
+
"stats",
|
|
108
|
+
"view",
|
|
109
|
+
"view-serve",
|
|
110
|
+
"equiv-margin",
|
|
111
|
+
"archive",
|
|
112
|
+
"export-perfetto",
|
|
113
|
+
"export-profile",
|
|
114
|
+
"editor",
|
|
115
|
+
],
|
|
116
|
+
"Selecting Benchmarks:": ["filter", "all", "list"],
|
|
117
|
+
"V8 Tuning:": [
|
|
118
|
+
"warmup",
|
|
119
|
+
"trace-opt",
|
|
120
|
+
"pause-first",
|
|
121
|
+
"pause-interval",
|
|
122
|
+
"pause-duration",
|
|
123
|
+
"pause-warmup",
|
|
124
|
+
],
|
|
125
|
+
"Adaptive:": ["adaptive", "min-time", "convergence"],
|
|
126
|
+
} as const;
|
|
64
127
|
|
|
65
|
-
|
|
128
|
+
const { url: _url, ...browserOnlyOptions } = cliOptions;
|
|
129
|
+
|
|
130
|
+
/** Parse command line arguments with optional custom yargs configuration. */
|
|
66
131
|
export function parseCliArgs<T = DefaultCliArgs>(
|
|
67
132
|
args: string[],
|
|
68
133
|
configure: Configure<T> = defaultCliArgs as Configure<T>,
|
|
69
134
|
): T {
|
|
70
|
-
|
|
71
|
-
|
|
135
|
+
return configure(yargs(args)).parseSync() as T;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/** Configure yargs for browser benchmarking with url as a required positional. */
|
|
139
|
+
export function browserCliArgs(yargsInstance: Argv): Argv<DefaultCliArgs> {
|
|
140
|
+
return applyGroups(
|
|
141
|
+
yargsInstance
|
|
142
|
+
.command("$0 <url>", "run browser benchmarks", y => {
|
|
143
|
+
y.positional("url", {
|
|
144
|
+
type: "string",
|
|
145
|
+
describe: "page URL for browser profiling",
|
|
146
|
+
});
|
|
147
|
+
})
|
|
148
|
+
.options(browserOnlyOptions)
|
|
149
|
+
.help()
|
|
150
|
+
.strict(),
|
|
151
|
+
) as Argv<DefaultCliArgs>;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/** Configure yargs with standard benchmark options and file positional. */
|
|
155
|
+
export function defaultCliArgs(yargsInstance: Argv): Argv<DefaultCliArgs> {
|
|
156
|
+
return applyGroups(
|
|
157
|
+
yargsInstance
|
|
158
|
+
.command("$0 [file]", "run benchmarks", y => {
|
|
159
|
+
y.positional("file", {
|
|
160
|
+
type: "string",
|
|
161
|
+
describe: "benchmark file to run",
|
|
162
|
+
});
|
|
163
|
+
})
|
|
164
|
+
.options(cliOptions)
|
|
165
|
+
.help()
|
|
166
|
+
.strict(),
|
|
167
|
+
) as Argv<DefaultCliArgs>;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/** Strip yargs internals (`_`, `$0`) and undefined values, converting kebab-case to camelCase. */
|
|
171
|
+
export function cleanCliArgs(args: DefaultCliArgs): Record<string, unknown> {
|
|
172
|
+
const skip = new Set(["_", "$0"]);
|
|
173
|
+
const camel = (k: string) =>
|
|
174
|
+
k.replace(/-([a-z])/g, (_, l: string) => l.toUpperCase());
|
|
175
|
+
return Object.fromEntries(
|
|
176
|
+
Object.entries(args)
|
|
177
|
+
.filter(([k, v]) => v !== undefined && v !== null && !skip.has(k))
|
|
178
|
+
.map(([k, v]) => [camel(k), v]),
|
|
179
|
+
);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/** Assign options to their labeled groups in yargs help output. */
|
|
183
|
+
function applyGroups(y: Argv): Argv {
|
|
184
|
+
return Object.entries(optionGroups).reduce(
|
|
185
|
+
(acc, [label, keys]) => acc.group(keys as unknown as string[], label),
|
|
186
|
+
y,
|
|
187
|
+
);
|
|
72
188
|
}
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
import { writeFileSync } from "node:fs";
|
|
2
|
+
import { resolve } from "node:path";
|
|
3
|
+
import { buildSpeedscopeFile } from "../export/AllocExport.ts";
|
|
4
|
+
import { archiveBenchmark, collectSources } from "../export/ArchiveExport.ts";
|
|
5
|
+
import {
|
|
6
|
+
annotateFramesWithCounts,
|
|
7
|
+
buildCoverageMap,
|
|
8
|
+
} from "../export/CoverageExport.ts";
|
|
9
|
+
import { resolveEditorUri } from "../export/EditorUri.ts";
|
|
10
|
+
import { exportPerfettoTrace } from "../export/PerfettoExport.ts";
|
|
11
|
+
import { buildTimeSpeedscopeFile } from "../export/TimeExport.ts";
|
|
12
|
+
import type { CoverageData } from "../profiling/node/CoverageTypes.ts";
|
|
13
|
+
import type { TimeProfile } from "../profiling/node/TimeSampler.ts";
|
|
14
|
+
import type { ReportGroup, ReportSection } from "../report/BenchmarkReport.ts";
|
|
15
|
+
import { groupReports } from "../report/BenchmarkReport.ts";
|
|
16
|
+
import type { GitVersion } from "../report/GitUtils.ts";
|
|
17
|
+
import { prepareHtmlData } from "../report/HtmlReport.ts";
|
|
18
|
+
import type { ReportData } from "../viewer/ReportData.ts";
|
|
19
|
+
import type { DefaultCliArgs } from "./CliArgs.ts";
|
|
20
|
+
import {
|
|
21
|
+
cliComparisonOptions,
|
|
22
|
+
cliHeapReportOptions,
|
|
23
|
+
needsAlloc,
|
|
24
|
+
} from "./CliOptions.ts";
|
|
25
|
+
import { printHeapReports, withStatus } from "./CliReport.ts";
|
|
26
|
+
import {
|
|
27
|
+
optionalJson,
|
|
28
|
+
startViewerServer,
|
|
29
|
+
waitForCtrlC,
|
|
30
|
+
} from "./ViewerServer.ts";
|
|
31
|
+
|
|
32
|
+
/** Options for exporting benchmark results to various formats */
|
|
33
|
+
export interface ExportOptions {
|
|
34
|
+
results: ReportGroup[];
|
|
35
|
+
args: DefaultCliArgs;
|
|
36
|
+
sections?: ReportSection[];
|
|
37
|
+
currentVersion?: GitVersion;
|
|
38
|
+
baselineVersion?: GitVersion;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/** Export options for matrix benchmarks (results/args supplied by the matrix pipeline). */
|
|
42
|
+
export interface MatrixExportOptions {
|
|
43
|
+
sections?: ReportSection[];
|
|
44
|
+
currentVersion?: GitVersion;
|
|
45
|
+
baselineVersion?: GitVersion;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
type FrameContainer = {
|
|
49
|
+
shared: { frames: { name: string; file?: string; line?: number }[] };
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
/** Export reports (JSON, Perfetto, archive, viewer) based on CLI args. */
|
|
53
|
+
export async function exportReports(options: ExportOptions): Promise<void> {
|
|
54
|
+
const { results, args, sections, currentVersion, baselineVersion } = options;
|
|
55
|
+
|
|
56
|
+
const wantViewer = args.view || args["view-serve"] || args.archive != null;
|
|
57
|
+
const comparison = cliComparisonOptions(args);
|
|
58
|
+
const htmlOpts = {
|
|
59
|
+
cliArgs: args,
|
|
60
|
+
sections,
|
|
61
|
+
currentVersion,
|
|
62
|
+
baselineVersion,
|
|
63
|
+
...comparison,
|
|
64
|
+
};
|
|
65
|
+
const reportData = wantViewer
|
|
66
|
+
? withStatus("computing viewer data", () =>
|
|
67
|
+
prepareHtmlData(results, htmlOpts),
|
|
68
|
+
)
|
|
69
|
+
: undefined;
|
|
70
|
+
|
|
71
|
+
exportFileFormats(results, args);
|
|
72
|
+
|
|
73
|
+
const profileFile = buildSpeedscopeFile(results);
|
|
74
|
+
const timeFile = buildAllTimeProfiles(results);
|
|
75
|
+
const coverageData = await annotateCoverage(results, profileFile, timeFile);
|
|
76
|
+
const timeData = timeFile ? JSON.stringify(timeFile) : undefined;
|
|
77
|
+
|
|
78
|
+
if (args.archive != null) {
|
|
79
|
+
const outputPath = args.archive || undefined;
|
|
80
|
+
await archiveBenchmark({
|
|
81
|
+
groups: results,
|
|
82
|
+
reportData,
|
|
83
|
+
timeProfileData: timeData,
|
|
84
|
+
coverageData,
|
|
85
|
+
outputPath,
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
if (args.view || args["view-serve"]) {
|
|
89
|
+
await openViewer(profileFile, timeData, coverageData, reportData, args);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/** Print heap reports (if enabled) and export results. */
|
|
94
|
+
export async function finishReports(
|
|
95
|
+
results: ReportGroup[],
|
|
96
|
+
args: DefaultCliArgs,
|
|
97
|
+
exportOptions?: MatrixExportOptions,
|
|
98
|
+
): Promise<void> {
|
|
99
|
+
if (needsAlloc(args)) {
|
|
100
|
+
printHeapReports(results, cliHeapReportOptions(args));
|
|
101
|
+
}
|
|
102
|
+
await exportReports({ results, args, ...exportOptions });
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/** Write Perfetto and time profile files if requested by CLI args. */
|
|
106
|
+
function exportFileFormats(results: ReportGroup[], args: DefaultCliArgs): void {
|
|
107
|
+
if (args["export-perfetto"])
|
|
108
|
+
exportPerfettoTrace(results, args["export-perfetto"], args);
|
|
109
|
+
if (args["export-profile"])
|
|
110
|
+
exportTimeProfile(results, args["export-profile"]);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/** Build combined Speedscope file from all time profiles in results. */
|
|
114
|
+
function buildAllTimeProfiles(results: ReportGroup[]) {
|
|
115
|
+
const entries = results.flatMap(group =>
|
|
116
|
+
groupReports(group)
|
|
117
|
+
.filter(r => r.measuredResults.timeProfile)
|
|
118
|
+
.map(r => ({
|
|
119
|
+
name: r.name,
|
|
120
|
+
profile: r.measuredResults.timeProfile as TimeProfile,
|
|
121
|
+
})),
|
|
122
|
+
);
|
|
123
|
+
return buildTimeSpeedscopeFile(entries);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/** Annotate speedscope frame names with coverage counts. Returns serialized coverage map. */
|
|
127
|
+
async function annotateCoverage(
|
|
128
|
+
results: ReportGroup[],
|
|
129
|
+
profileFile?: FrameContainer,
|
|
130
|
+
timeFile?: FrameContainer,
|
|
131
|
+
): Promise<string | undefined> {
|
|
132
|
+
const coverage = mergeCoverage(results);
|
|
133
|
+
if (!coverage) return undefined;
|
|
134
|
+
|
|
135
|
+
const frames = coverage.scripts.map(s => ({ file: s.url }));
|
|
136
|
+
const sources = await collectSources(frames);
|
|
137
|
+
const covMap = buildCoverageMap(coverage, sources);
|
|
138
|
+
if (profileFile) annotateFramesWithCounts(profileFile.shared.frames, covMap);
|
|
139
|
+
if (timeFile) annotateFramesWithCounts(timeFile.shared.frames, covMap);
|
|
140
|
+
return JSON.stringify(Object.fromEntries(covMap.map));
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/** Start viewer server with profile data and block until Ctrl+C. */
|
|
144
|
+
async function openViewer(
|
|
145
|
+
profileFile: ReturnType<typeof buildSpeedscopeFile>,
|
|
146
|
+
timeData: string | undefined,
|
|
147
|
+
coverageData: string | undefined,
|
|
148
|
+
reportData: ReportData | undefined,
|
|
149
|
+
args: DefaultCliArgs,
|
|
150
|
+
): Promise<void> {
|
|
151
|
+
const viewer = await startViewerServer({
|
|
152
|
+
profileData: optionalJson(profileFile),
|
|
153
|
+
timeProfileData: timeData,
|
|
154
|
+
coverageData,
|
|
155
|
+
reportData: optionalJson(reportData),
|
|
156
|
+
editorUri: resolveEditorUri(args.editor),
|
|
157
|
+
open: !args["view-serve"],
|
|
158
|
+
});
|
|
159
|
+
await waitForCtrlC();
|
|
160
|
+
viewer.close();
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/** Export the first raw V8 TimeProfile to a JSON file. */
|
|
164
|
+
function exportTimeProfile(results: ReportGroup[], path: string): void {
|
|
165
|
+
const profile = results
|
|
166
|
+
.flatMap(g => groupReports(g))
|
|
167
|
+
.find(r => r.measuredResults.timeProfile)?.measuredResults.timeProfile;
|
|
168
|
+
if (!profile) return void console.log("No time profiles to export.");
|
|
169
|
+
writeFileSync(resolve(path), JSON.stringify(profile));
|
|
170
|
+
console.log(`Time profile exported to: ${path}`);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/** Merge coverage data from all results into a single CoverageData. */
|
|
174
|
+
function mergeCoverage(results: ReportGroup[]): CoverageData | undefined {
|
|
175
|
+
const scripts = results.flatMap(group =>
|
|
176
|
+
groupReports(group).flatMap(r => r.measuredResults.coverage?.scripts ?? []),
|
|
177
|
+
);
|
|
178
|
+
return scripts.length > 0 ? { scripts } : undefined;
|
|
179
|
+
}
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import type { RunMatrixOptions } from "../matrix/BenchMatrix.ts";
|
|
2
|
+
import type { HeapReportOptions } from "../profiling/node/HeapSampleReport.ts";
|
|
3
|
+
import type { ComparisonOptions } from "../report/BenchmarkReport.ts";
|
|
4
|
+
import { buildTimeSection } from "../report/StandardSections.ts";
|
|
5
|
+
import type { RunnerOptions } from "../runners/BenchRunner.ts";
|
|
6
|
+
import {
|
|
7
|
+
type DefaultCliArgs,
|
|
8
|
+
defaultAdaptiveMaxTime,
|
|
9
|
+
defaultDuration,
|
|
10
|
+
} from "./CliArgs.ts";
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Resolve duration/iterations flags into runner limits.
|
|
14
|
+
*
|
|
15
|
+
* | Flags set | maxTime | maxIterations |
|
|
16
|
+
* |-------------------|--------------------|---------------|
|
|
17
|
+
* | neither | defaultDuration*1000 | undefined |
|
|
18
|
+
* | --iterations only | undefined | N |
|
|
19
|
+
* | --duration only | duration*1000 | undefined |
|
|
20
|
+
* | both | duration*1000 | N |
|
|
21
|
+
*/
|
|
22
|
+
type Limits = {
|
|
23
|
+
maxTime: number | undefined;
|
|
24
|
+
maxIterations: number | undefined;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
/** Convert CLI args to matrix runner options. */
|
|
28
|
+
export function cliToMatrixOptions(args: DefaultCliArgs): RunMatrixOptions {
|
|
29
|
+
const { iterations, worker, batches } = args;
|
|
30
|
+
const { maxTime } = resolveLimits(args);
|
|
31
|
+
return {
|
|
32
|
+
iterations,
|
|
33
|
+
maxTime,
|
|
34
|
+
useWorker: worker,
|
|
35
|
+
batches,
|
|
36
|
+
warmupBatch: args["warmup-batch"],
|
|
37
|
+
...cliCommonOptions(args),
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/** Validate CLI argument combinations. */
|
|
42
|
+
export function validateArgs(args: DefaultCliArgs): void {
|
|
43
|
+
if (args["gc-stats"] && !args.worker && !args.url) {
|
|
44
|
+
throw new Error(
|
|
45
|
+
"--gc-stats requires worker mode (the default). Remove --no-worker flag.",
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
// Eagerly validate --stats tokens so users see the error before running benchmarks.
|
|
49
|
+
if (args.stats) buildTimeSection(args.stats);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/** Convert CLI args to benchmark runner options. */
|
|
53
|
+
export function cliToRunnerOptions(args: DefaultCliArgs): RunnerOptions {
|
|
54
|
+
const { inspect, iterations, adaptive } = args;
|
|
55
|
+
const gcForce = args["gc-force"];
|
|
56
|
+
if (inspect)
|
|
57
|
+
return { maxIterations: iterations ?? 1, warmupTime: 0, gcForce };
|
|
58
|
+
if (adaptive) return createAdaptiveOptions(args);
|
|
59
|
+
return { ...resolveLimits(args), ...cliCommonOptions(args) };
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/** Convert CLI args to heap report display options. */
|
|
63
|
+
export function cliHeapReportOptions(args: DefaultCliArgs): HeapReportOptions {
|
|
64
|
+
return {
|
|
65
|
+
topN: args["alloc-rows"],
|
|
66
|
+
stackDepth: args["alloc-stack"],
|
|
67
|
+
verbose: args["alloc-verbose"],
|
|
68
|
+
raw: args["alloc-raw"],
|
|
69
|
+
userOnly: args["alloc-user-only"],
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/** True if any alloc-related flag implies allocation sampling. */
|
|
74
|
+
export function needsAlloc(args: DefaultCliArgs): boolean {
|
|
75
|
+
return (
|
|
76
|
+
args.alloc ||
|
|
77
|
+
args.archive != null ||
|
|
78
|
+
args["alloc-raw"] ||
|
|
79
|
+
args["alloc-verbose"] ||
|
|
80
|
+
args["alloc-user-only"]
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/** True if any profiling flag implies CPU time sampling. */
|
|
85
|
+
export function needsProfile(args: DefaultCliArgs): boolean {
|
|
86
|
+
return args.profile || !!args["export-profile"];
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/** Extract baseline comparison options from CLI args. */
|
|
90
|
+
export function cliComparisonOptions(args: DefaultCliArgs): ComparisonOptions {
|
|
91
|
+
return {
|
|
92
|
+
equivMargin: args["equiv-margin"],
|
|
93
|
+
noBatchTrim: args["no-batch-trim"],
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
export function resolveLimits(args: {
|
|
98
|
+
duration?: number;
|
|
99
|
+
iterations?: number;
|
|
100
|
+
}): Limits {
|
|
101
|
+
const { duration, iterations } = args;
|
|
102
|
+
if (duration == null && iterations == null)
|
|
103
|
+
return { maxTime: defaultDuration * 1000, maxIterations: undefined };
|
|
104
|
+
return {
|
|
105
|
+
maxTime: duration != null ? duration * 1000 : undefined,
|
|
106
|
+
maxIterations: iterations,
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/** Runner/matrix options shared across all CLI modes. */
|
|
111
|
+
function cliCommonOptions(args: DefaultCliArgs) {
|
|
112
|
+
const { warmup } = args;
|
|
113
|
+
const { "gc-force": gcForce, "gc-stats": gcStats } = args;
|
|
114
|
+
const { "trace-opt": traceOpt, "call-counts": callCounts } = args;
|
|
115
|
+
const { "pause-warmup": pauseWarmup, "pause-first": pauseFirst } = args;
|
|
116
|
+
const { "pause-interval": pauseInterval, "pause-duration": pauseDuration } =
|
|
117
|
+
args;
|
|
118
|
+
const { "alloc-interval": allocInterval, "alloc-depth": allocDepth } = args;
|
|
119
|
+
const { "profile-interval": profileInterval } = args;
|
|
120
|
+
return {
|
|
121
|
+
gcForce,
|
|
122
|
+
warmup,
|
|
123
|
+
traceOpt,
|
|
124
|
+
gcStats,
|
|
125
|
+
callCounts,
|
|
126
|
+
pauseWarmup,
|
|
127
|
+
pauseFirst,
|
|
128
|
+
pauseInterval,
|
|
129
|
+
pauseDuration,
|
|
130
|
+
alloc: needsAlloc(args),
|
|
131
|
+
allocInterval,
|
|
132
|
+
allocDepth,
|
|
133
|
+
profile: needsProfile(args),
|
|
134
|
+
profileInterval,
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/** Build runner options for adaptive sampling mode. */
|
|
139
|
+
function createAdaptiveOptions(args: DefaultCliArgs): RunnerOptions {
|
|
140
|
+
return {
|
|
141
|
+
minTime: (args["min-time"] ?? 1) * 1000,
|
|
142
|
+
maxTime: defaultAdaptiveMaxTime * 1000,
|
|
143
|
+
targetConfidence: args.convergence,
|
|
144
|
+
adaptive: true,
|
|
145
|
+
...cliCommonOptions(args),
|
|
146
|
+
} as any;
|
|
147
|
+
}
|