overtake 1.4.0 → 2.0.0
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/README.md +4 -15
- package/bin/overtake.js +1 -1
- package/build/executor.d.ts +7 -3
- package/build/index.d.ts +10 -11
- package/build/reporter.d.ts +10 -2
- package/build/runner.d.ts +1 -1
- package/build/types.d.ts +6 -6
- package/build/utils.d.ts +1 -17
- package/package.json +8 -26
- package/src/__tests__/assert-no-closure.ts +135 -0
- package/src/__tests__/benchmark-execute.ts +48 -0
- package/src/cli.ts +139 -144
- package/src/executor.ts +48 -18
- package/src/index.ts +85 -57
- package/src/reporter.ts +27 -19
- package/src/runner.ts +2 -5
- package/src/types.ts +8 -8
- package/src/utils.ts +15 -54
- package/src/worker.ts +6 -3
- package/tsconfig.json +3 -1
- package/build/cli.cjs +0 -179
- package/build/cli.cjs.map +0 -1
- package/build/cli.js +0 -134
- package/build/cli.js.map +0 -1
- package/build/executor.cjs +0 -123
- package/build/executor.cjs.map +0 -1
- package/build/executor.js +0 -113
- package/build/executor.js.map +0 -1
- package/build/gc-watcher.cjs +0 -30
- package/build/gc-watcher.cjs.map +0 -1
- package/build/gc-watcher.js +0 -20
- package/build/gc-watcher.js.map +0 -1
- package/build/index.cjs +0 -442
- package/build/index.cjs.map +0 -1
- package/build/index.js +0 -377
- package/build/index.js.map +0 -1
- package/build/reporter.cjs +0 -311
- package/build/reporter.cjs.map +0 -1
- package/build/reporter.js +0 -293
- package/build/reporter.js.map +0 -1
- package/build/runner.cjs +0 -532
- package/build/runner.cjs.map +0 -1
- package/build/runner.js +0 -522
- package/build/runner.js.map +0 -1
- package/build/types.cjs +0 -66
- package/build/types.cjs.map +0 -1
- package/build/types.js +0 -33
- package/build/types.js.map +0 -1
- package/build/utils.cjs +0 -174
- package/build/utils.cjs.map +0 -1
- package/build/utils.js +0 -132
- package/build/utils.js.map +0 -1
- package/build/worker.cjs +0 -155
- package/build/worker.cjs.map +0 -1
- package/build/worker.js +0 -110
- package/build/worker.js.map +0 -1
- package/src/__tests__/assert-no-closure.js +0 -134
package/build/cli.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/cli.ts"],"sourcesContent":["import { createRequire, Module } from 'node:module';\nimport { fileURLToPath, pathToFileURL } from 'node:url';\nimport { SyntheticModule, createContext, SourceTextModule } from 'node:vm';\nimport { stat, readFile, writeFile } from 'node:fs/promises';\nimport { Command, Option } from 'commander';\nimport { glob } from 'glob';\nimport {\n Benchmark,\n printTableReports,\n printJSONReports,\n printSimpleReports,\n printMarkdownReports,\n printHistogramReports,\n printComparisonReports,\n reportsToBaseline,\n BaselineData,\n DEFAULT_REPORT_TYPES,\n DEFAULT_WORKERS,\n} from './index.js';\nimport { transpile } from './utils.js';\nimport { REPORT_TYPES } from './types.js';\n\nconst require = createRequire(import.meta.url);\nconst { name, description, version } = require('../package.json');\nconst BENCHMARK_URL = Symbol.for('overtake.benchmarkUrl');\n\nconst commander = new Command();\n\ncommander\n .name(name)\n .description(description)\n .version(version)\n .argument('<paths...>', 'glob pattern to find benchmarks')\n .addOption(new Option('-r, --report-types [reportTypes...]', 'statistic types to include in the report').choices(REPORT_TYPES).default(DEFAULT_REPORT_TYPES))\n .addOption(new Option('-w, --workers [workers]', 'number of concurent workers').default(DEFAULT_WORKERS).argParser(parseInt))\n .addOption(new Option('-f, --format [format]', 'output format').default('simple').choices(['simple', 'json', 'pjson', 'table', 'markdown', 'histogram']))\n .addOption(new Option('--abs-threshold [absThreshold]', 'absolute error threshold in nanoseconds').argParser(parseFloat))\n .addOption(new Option('--rel-threshold [relThreshold]', 'relative error threshold (fraction between 0 and 1)').argParser(parseFloat))\n .addOption(new Option('--warmup-cycles [warmupCycles]', 'number of warmup cycles before measuring').argParser(parseInt))\n .addOption(new Option('--max-cycles [maxCycles]', 'maximum measurement cycles per feed').argParser(parseInt))\n .addOption(new Option('--min-cycles [minCycles]', 'minimum measurement cycles per feed').argParser(parseInt))\n .addOption(new Option('--no-gc-observer', 'disable GC overlap detection'))\n .addOption(new Option('--progress', 'show progress bar during benchmark execution'))\n .addOption(new Option('--save-baseline <file>', 'save benchmark results to baseline file'))\n .addOption(new Option('--compare-baseline <file>', 'compare results against baseline file'))\n .action(async (patterns: string[], executeOptions) => {\n let baseline: BaselineData | null = null;\n if (executeOptions.compareBaseline) {\n try {\n const content = await readFile(executeOptions.compareBaseline, 'utf8');\n baseline = JSON.parse(content) as BaselineData;\n } catch {\n console.error(`Warning: Could not load baseline file: ${executeOptions.compareBaseline}`);\n }\n }\n\n const files = new Set<string>();\n await Promise.all(\n patterns.map(async (pattern) => {\n const matches = await glob(pattern, { absolute: true, cwd: process.cwd() }).catch(() => []);\n matches.forEach((file) => files.add(file));\n }),\n );\n\n for (const file of files) {\n const stats = await stat(file).catch(() => false as const);\n if (stats && stats.isFile()) {\n const content = await readFile(file, 'utf8');\n const identifier = pathToFileURL(file).href;\n const code = await transpile(content);\n let instance: Benchmark<unknown> | undefined;\n const benchmark = (...args: Parameters<(typeof Benchmark)['create']>) => {\n if (instance) {\n throw new Error('Only one benchmark per file is supported');\n }\n instance = Benchmark.create(...args);\n return instance;\n };\n const globals = Object.create(null);\n for (const k of Object.getOwnPropertyNames(globalThis)) {\n globals[k] = (globalThis as any)[k];\n }\n globals.benchmark = benchmark;\n const script = new SourceTextModule(code, {\n identifier,\n context: createContext(globals),\n initializeImportMeta(meta) {\n meta.url = identifier;\n },\n async importModuleDynamically(specifier, referencingModule) {\n if (Module.isBuiltin(specifier)) {\n return import(specifier);\n }\n const baseIdentifier = referencingModule.identifier ?? identifier;\n const resolveFrom = createRequire(fileURLToPath(baseIdentifier));\n const resolved = resolveFrom.resolve(specifier);\n return import(resolved);\n },\n });\n const imports = new Map<string, SyntheticModule>();\n await script.link(async (specifier: string, referencingModule) => {\n const baseIdentifier = referencingModule.identifier ?? identifier;\n const resolveFrom = createRequire(fileURLToPath(baseIdentifier));\n const target = Module.isBuiltin(specifier) ? specifier : resolveFrom.resolve(specifier);\n const cached = imports.get(target);\n if (cached) {\n return cached;\n }\n const mod = await import(target);\n const exportNames = Object.keys(mod);\n const imported = new SyntheticModule(\n exportNames,\n () => {\n exportNames.forEach((key) => imported.setExport(key, mod[key]));\n },\n { identifier: target, context: referencingModule.context },\n );\n\n imports.set(target, imported);\n return imported;\n });\n await script.evaluate();\n\n if (instance) {\n const reports = await instance.execute({\n ...executeOptions,\n [BENCHMARK_URL]: identifier,\n } as typeof executeOptions);\n\n if (executeOptions.saveBaseline) {\n const baselineData = reportsToBaseline(reports);\n await writeFile(executeOptions.saveBaseline, JSON.stringify(baselineData, null, 2));\n console.log(`Baseline saved to: ${executeOptions.saveBaseline}`);\n }\n\n if (baseline) {\n printComparisonReports(reports, baseline);\n } else {\n switch (executeOptions.format) {\n case 'json':\n printJSONReports(reports);\n break;\n case 'pjson':\n printJSONReports(reports, 2);\n break;\n case 'table':\n printTableReports(reports);\n break;\n case 'markdown':\n printMarkdownReports(reports);\n break;\n case 'histogram':\n printHistogramReports(reports);\n break;\n default:\n printSimpleReports(reports);\n }\n }\n }\n }\n }\n });\n\ncommander.parse(process.argv);\n"],"names":["createRequire","Module","fileURLToPath","pathToFileURL","SyntheticModule","createContext","SourceTextModule","stat","readFile","writeFile","Command","Option","glob","Benchmark","printTableReports","printJSONReports","printSimpleReports","printMarkdownReports","printHistogramReports","printComparisonReports","reportsToBaseline","DEFAULT_REPORT_TYPES","DEFAULT_WORKERS","transpile","REPORT_TYPES","require","url","name","description","version","BENCHMARK_URL","Symbol","for","commander","argument","addOption","choices","default","argParser","parseInt","parseFloat","action","patterns","executeOptions","baseline","compareBaseline","content","JSON","parse","console","error","files","Set","Promise","all","map","pattern","matches","absolute","cwd","process","catch","forEach","file","add","stats","isFile","identifier","href","code","instance","benchmark","args","Error","create","globals","Object","k","getOwnPropertyNames","globalThis","script","context","initializeImportMeta","meta","importModuleDynamically","specifier","referencingModule","isBuiltin","baseIdentifier","resolveFrom","resolved","resolve","imports","Map","link","target","cached","get","mod","exportNames","keys","imported","key","setExport","set","evaluate","reports","execute","saveBaseline","baselineData","stringify","log","format","argv"],"mappings":"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"}
|
package/build/executor.cjs
DELETED
|
@@ -1,123 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", {
|
|
3
|
-
value: true
|
|
4
|
-
});
|
|
5
|
-
Object.defineProperty(exports, "createExecutor", {
|
|
6
|
-
enumerable: true,
|
|
7
|
-
get: function() {
|
|
8
|
-
return createExecutor;
|
|
9
|
-
}
|
|
10
|
-
});
|
|
11
|
-
const _nodeworker_threads = require("node:worker_threads");
|
|
12
|
-
const _nodeevents = require("node:events");
|
|
13
|
-
const _async = require("async");
|
|
14
|
-
const _nodeurl = require("node:url");
|
|
15
|
-
const _reportercjs = require("./reporter.cjs");
|
|
16
|
-
const _utilscjs = require("./utils.cjs");
|
|
17
|
-
const _typescjs = require("./types.cjs");
|
|
18
|
-
const BENCHMARK_URL = Symbol.for('overtake.benchmarkUrl');
|
|
19
|
-
const createExecutor = (options)=>{
|
|
20
|
-
const { workers, warmupCycles, maxCycles, minCycles, absThreshold, relThreshold, gcObserver = true, reportTypes, onProgress, progressInterval = 100 } = options;
|
|
21
|
-
const benchmarkUrl = options[BENCHMARK_URL];
|
|
22
|
-
const resolvedBenchmarkUrl = typeof benchmarkUrl === 'string' ? benchmarkUrl : (0, _nodeurl.pathToFileURL)(process.cwd()).href;
|
|
23
|
-
const executor = (0, _async.queue)(async ({ id, setup, teardown, pre, run, post, data })=>{
|
|
24
|
-
const setupCode = setup?.toString();
|
|
25
|
-
const teardownCode = teardown?.toString();
|
|
26
|
-
const preCode = pre?.toString();
|
|
27
|
-
const runCode = run.toString();
|
|
28
|
-
const postCode = post?.toString();
|
|
29
|
-
if (setupCode) (0, _utilscjs.assertNoClosure)(setupCode, 'setup');
|
|
30
|
-
if (teardownCode) (0, _utilscjs.assertNoClosure)(teardownCode, 'teardown');
|
|
31
|
-
if (preCode) (0, _utilscjs.assertNoClosure)(preCode, 'pre');
|
|
32
|
-
(0, _utilscjs.assertNoClosure)(runCode, 'run');
|
|
33
|
-
if (postCode) (0, _utilscjs.assertNoClosure)(postCode, 'post');
|
|
34
|
-
const controlSAB = new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * _typescjs.CONTROL_SLOTS);
|
|
35
|
-
const durationsSAB = new SharedArrayBuffer(BigUint64Array.BYTES_PER_ELEMENT * maxCycles);
|
|
36
|
-
const workerFile = new URL('./worker.js', require("url").pathToFileURL(__filename).toString());
|
|
37
|
-
const workerData = {
|
|
38
|
-
benchmarkUrl: resolvedBenchmarkUrl,
|
|
39
|
-
setupCode,
|
|
40
|
-
teardownCode,
|
|
41
|
-
preCode,
|
|
42
|
-
runCode,
|
|
43
|
-
postCode,
|
|
44
|
-
data,
|
|
45
|
-
warmupCycles,
|
|
46
|
-
minCycles,
|
|
47
|
-
absThreshold,
|
|
48
|
-
relThreshold,
|
|
49
|
-
gcObserver,
|
|
50
|
-
controlSAB,
|
|
51
|
-
durationsSAB
|
|
52
|
-
};
|
|
53
|
-
const worker = new _nodeworker_threads.Worker(workerFile, {
|
|
54
|
-
workerData
|
|
55
|
-
});
|
|
56
|
-
const control = new Int32Array(controlSAB);
|
|
57
|
-
let progressIntervalId;
|
|
58
|
-
if (onProgress && id) {
|
|
59
|
-
progressIntervalId = setInterval(()=>{
|
|
60
|
-
const progress = control[_typescjs.Control.PROGRESS] / _typescjs.COMPLETE_VALUE;
|
|
61
|
-
onProgress({
|
|
62
|
-
id,
|
|
63
|
-
progress
|
|
64
|
-
});
|
|
65
|
-
}, progressInterval);
|
|
66
|
-
}
|
|
67
|
-
const WORKER_TIMEOUT_MS = 300_000;
|
|
68
|
-
const exitPromise = (0, _nodeevents.once)(worker, 'exit');
|
|
69
|
-
const timeoutId = setTimeout(()=>worker.terminate(), WORKER_TIMEOUT_MS);
|
|
70
|
-
let workerError;
|
|
71
|
-
try {
|
|
72
|
-
const [exitCode] = await exitPromise;
|
|
73
|
-
clearTimeout(timeoutId);
|
|
74
|
-
if (progressIntervalId) clearInterval(progressIntervalId);
|
|
75
|
-
if (exitCode !== 0) {
|
|
76
|
-
workerError = `worker exited with code ${exitCode}`;
|
|
77
|
-
}
|
|
78
|
-
} catch (err) {
|
|
79
|
-
clearTimeout(timeoutId);
|
|
80
|
-
if (progressIntervalId) clearInterval(progressIntervalId);
|
|
81
|
-
workerError = err instanceof Error ? err.message : String(err);
|
|
82
|
-
}
|
|
83
|
-
const count = control[_typescjs.Control.INDEX];
|
|
84
|
-
const heapUsedKB = control[_typescjs.Control.HEAP_USED];
|
|
85
|
-
const durations = new BigUint64Array(durationsSAB).slice(0, count).sort(_utilscjs.cmp);
|
|
86
|
-
const DCE_THRESHOLD_OPS = 5_000_000_000;
|
|
87
|
-
let dceWarning = false;
|
|
88
|
-
if (count > 0) {
|
|
89
|
-
let sum = 0n;
|
|
90
|
-
for (const d of durations)sum += d;
|
|
91
|
-
const avgNs = Number(sum / BigInt(count)) / 1000;
|
|
92
|
-
const opsPerSec = avgNs > 0 ? 1_000_000_000 / avgNs : Infinity;
|
|
93
|
-
if (opsPerSec > DCE_THRESHOLD_OPS) {
|
|
94
|
-
dceWarning = true;
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
const report = reportTypes.map((type)=>[
|
|
98
|
-
type,
|
|
99
|
-
(0, _reportercjs.createReport)(durations, type)
|
|
100
|
-
]).concat([
|
|
101
|
-
[
|
|
102
|
-
'count',
|
|
103
|
-
count
|
|
104
|
-
],
|
|
105
|
-
[
|
|
106
|
-
'heapUsedKB',
|
|
107
|
-
heapUsedKB
|
|
108
|
-
],
|
|
109
|
-
[
|
|
110
|
-
'dceWarning',
|
|
111
|
-
dceWarning
|
|
112
|
-
],
|
|
113
|
-
[
|
|
114
|
-
'error',
|
|
115
|
-
workerError
|
|
116
|
-
]
|
|
117
|
-
]);
|
|
118
|
-
return Object.fromEntries(report);
|
|
119
|
-
}, workers);
|
|
120
|
-
return executor;
|
|
121
|
-
};
|
|
122
|
-
|
|
123
|
-
//# sourceMappingURL=executor.cjs.map
|
package/build/executor.cjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/executor.ts"],"sourcesContent":["import { Worker } from 'node:worker_threads';\nimport { once } from 'node:events';\nimport { queue } from 'async';\nimport { pathToFileURL } from 'node:url';\nimport { createReport, Report } from './reporter.js';\nimport { cmp, assertNoClosure } from './utils.js';\nimport {\n ExecutorRunOptions,\n ReportOptions,\n WorkerOptions,\n BenchmarkOptions,\n Control,\n ReportType,\n ReportTypeList,\n CONTROL_SLOTS,\n COMPLETE_VALUE,\n ProgressCallback,\n} from './types.js';\n\nexport type ExecutorReport<R extends ReportTypeList> = Record<R[number], Report> & {\n count: number;\n heapUsedKB: number;\n dceWarning: boolean;\n error?: string;\n};\n\nexport interface ExecutorOptions<R extends ReportTypeList> extends BenchmarkOptions, ReportOptions<R> {\n workers?: number;\n maxCycles?: number;\n onProgress?: ProgressCallback;\n progressInterval?: number;\n}\n\nconst BENCHMARK_URL = Symbol.for('overtake.benchmarkUrl');\n\nexport const createExecutor = <TContext, TInput, R extends ReportTypeList>(options: Required<ExecutorOptions<R>>) => {\n const { workers, warmupCycles, maxCycles, minCycles, absThreshold, relThreshold, gcObserver = true, reportTypes, onProgress, progressInterval = 100 } = options;\n const benchmarkUrl = (options as Record<symbol, unknown>)[BENCHMARK_URL];\n const resolvedBenchmarkUrl = typeof benchmarkUrl === 'string' ? benchmarkUrl : pathToFileURL(process.cwd()).href;\n\n const executor = queue<ExecutorRunOptions<TContext, TInput>>(async ({ id, setup, teardown, pre, run, post, data }) => {\n const setupCode = setup?.toString();\n const teardownCode = teardown?.toString();\n const preCode = pre?.toString();\n const runCode = run.toString()!;\n const postCode = post?.toString();\n\n if (setupCode) assertNoClosure(setupCode, 'setup');\n if (teardownCode) assertNoClosure(teardownCode, 'teardown');\n if (preCode) assertNoClosure(preCode, 'pre');\n assertNoClosure(runCode, 'run');\n if (postCode) assertNoClosure(postCode, 'post');\n\n const controlSAB = new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * CONTROL_SLOTS);\n const durationsSAB = new SharedArrayBuffer(BigUint64Array.BYTES_PER_ELEMENT * maxCycles);\n\n const workerFile = new URL('./worker.js', import.meta.url);\n const workerData: WorkerOptions = {\n benchmarkUrl: resolvedBenchmarkUrl,\n setupCode,\n teardownCode,\n preCode,\n runCode,\n postCode,\n data,\n\n warmupCycles,\n minCycles,\n absThreshold,\n relThreshold,\n gcObserver,\n\n controlSAB,\n durationsSAB,\n };\n\n const worker = new Worker(workerFile, {\n workerData,\n });\n\n const control = new Int32Array(controlSAB);\n let progressIntervalId: ReturnType<typeof setInterval> | undefined;\n if (onProgress && id) {\n progressIntervalId = setInterval(() => {\n const progress = control[Control.PROGRESS] / COMPLETE_VALUE;\n onProgress({ id, progress });\n }, progressInterval);\n }\n\n const WORKER_TIMEOUT_MS = 300_000;\n const exitPromise = once(worker, 'exit');\n const timeoutId = setTimeout(() => worker.terminate(), WORKER_TIMEOUT_MS);\n let workerError: string | undefined;\n try {\n const [exitCode] = await exitPromise;\n clearTimeout(timeoutId);\n if (progressIntervalId) clearInterval(progressIntervalId);\n if (exitCode !== 0) {\n workerError = `worker exited with code ${exitCode}`;\n }\n } catch (err) {\n clearTimeout(timeoutId);\n if (progressIntervalId) clearInterval(progressIntervalId);\n workerError = err instanceof Error ? err.message : String(err);\n }\n\n const count = control[Control.INDEX];\n const heapUsedKB = control[Control.HEAP_USED];\n const durations = new BigUint64Array(durationsSAB).slice(0, count).sort(cmp);\n\n const DCE_THRESHOLD_OPS = 5_000_000_000;\n let dceWarning = false;\n if (count > 0) {\n let sum = 0n;\n for (const d of durations) sum += d;\n const avgNs = Number(sum / BigInt(count)) / 1000;\n const opsPerSec = avgNs > 0 ? 1_000_000_000 / avgNs : Infinity;\n if (opsPerSec > DCE_THRESHOLD_OPS) {\n dceWarning = true;\n }\n }\n\n const report = reportTypes\n .map<[string, unknown]>((type) => [type, createReport(durations, type)] as [ReportType, Report])\n .concat([\n ['count', count],\n ['heapUsedKB', heapUsedKB],\n ['dceWarning', dceWarning],\n ['error', workerError],\n ]);\n return Object.fromEntries(report);\n }, workers);\n\n return executor;\n};\n"],"names":["createExecutor","BENCHMARK_URL","Symbol","for","options","workers","warmupCycles","maxCycles","minCycles","absThreshold","relThreshold","gcObserver","reportTypes","onProgress","progressInterval","benchmarkUrl","resolvedBenchmarkUrl","pathToFileURL","process","cwd","href","executor","queue","id","setup","teardown","pre","run","post","data","setupCode","toString","teardownCode","preCode","runCode","postCode","assertNoClosure","controlSAB","SharedArrayBuffer","Int32Array","BYTES_PER_ELEMENT","CONTROL_SLOTS","durationsSAB","BigUint64Array","workerFile","URL","workerData","worker","Worker","control","progressIntervalId","setInterval","progress","Control","PROGRESS","COMPLETE_VALUE","WORKER_TIMEOUT_MS","exitPromise","once","timeoutId","setTimeout","terminate","workerError","exitCode","clearTimeout","clearInterval","err","Error","message","String","count","INDEX","heapUsedKB","HEAP_USED","durations","slice","sort","cmp","DCE_THRESHOLD_OPS","dceWarning","sum","d","avgNs","Number","BigInt","opsPerSec","Infinity","report","map","type","createReport","concat","Object","fromEntries"],"mappings":"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"}
|
package/build/executor.js
DELETED
|
@@ -1,113 +0,0 @@
|
|
|
1
|
-
import { Worker } from 'node:worker_threads';
|
|
2
|
-
import { once } from 'node:events';
|
|
3
|
-
import { queue } from 'async';
|
|
4
|
-
import { pathToFileURL } from 'node:url';
|
|
5
|
-
import { createReport } from "./reporter.js";
|
|
6
|
-
import { cmp, assertNoClosure } from "./utils.js";
|
|
7
|
-
import { Control, CONTROL_SLOTS, COMPLETE_VALUE } from "./types.js";
|
|
8
|
-
const BENCHMARK_URL = Symbol.for('overtake.benchmarkUrl');
|
|
9
|
-
export const createExecutor = (options)=>{
|
|
10
|
-
const { workers, warmupCycles, maxCycles, minCycles, absThreshold, relThreshold, gcObserver = true, reportTypes, onProgress, progressInterval = 100 } = options;
|
|
11
|
-
const benchmarkUrl = options[BENCHMARK_URL];
|
|
12
|
-
const resolvedBenchmarkUrl = typeof benchmarkUrl === 'string' ? benchmarkUrl : pathToFileURL(process.cwd()).href;
|
|
13
|
-
const executor = queue(async ({ id, setup, teardown, pre, run, post, data })=>{
|
|
14
|
-
const setupCode = setup?.toString();
|
|
15
|
-
const teardownCode = teardown?.toString();
|
|
16
|
-
const preCode = pre?.toString();
|
|
17
|
-
const runCode = run.toString();
|
|
18
|
-
const postCode = post?.toString();
|
|
19
|
-
if (setupCode) assertNoClosure(setupCode, 'setup');
|
|
20
|
-
if (teardownCode) assertNoClosure(teardownCode, 'teardown');
|
|
21
|
-
if (preCode) assertNoClosure(preCode, 'pre');
|
|
22
|
-
assertNoClosure(runCode, 'run');
|
|
23
|
-
if (postCode) assertNoClosure(postCode, 'post');
|
|
24
|
-
const controlSAB = new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * CONTROL_SLOTS);
|
|
25
|
-
const durationsSAB = new SharedArrayBuffer(BigUint64Array.BYTES_PER_ELEMENT * maxCycles);
|
|
26
|
-
const workerFile = new URL('./worker.js', import.meta.url);
|
|
27
|
-
const workerData = {
|
|
28
|
-
benchmarkUrl: resolvedBenchmarkUrl,
|
|
29
|
-
setupCode,
|
|
30
|
-
teardownCode,
|
|
31
|
-
preCode,
|
|
32
|
-
runCode,
|
|
33
|
-
postCode,
|
|
34
|
-
data,
|
|
35
|
-
warmupCycles,
|
|
36
|
-
minCycles,
|
|
37
|
-
absThreshold,
|
|
38
|
-
relThreshold,
|
|
39
|
-
gcObserver,
|
|
40
|
-
controlSAB,
|
|
41
|
-
durationsSAB
|
|
42
|
-
};
|
|
43
|
-
const worker = new Worker(workerFile, {
|
|
44
|
-
workerData
|
|
45
|
-
});
|
|
46
|
-
const control = new Int32Array(controlSAB);
|
|
47
|
-
let progressIntervalId;
|
|
48
|
-
if (onProgress && id) {
|
|
49
|
-
progressIntervalId = setInterval(()=>{
|
|
50
|
-
const progress = control[Control.PROGRESS] / COMPLETE_VALUE;
|
|
51
|
-
onProgress({
|
|
52
|
-
id,
|
|
53
|
-
progress
|
|
54
|
-
});
|
|
55
|
-
}, progressInterval);
|
|
56
|
-
}
|
|
57
|
-
const WORKER_TIMEOUT_MS = 300_000;
|
|
58
|
-
const exitPromise = once(worker, 'exit');
|
|
59
|
-
const timeoutId = setTimeout(()=>worker.terminate(), WORKER_TIMEOUT_MS);
|
|
60
|
-
let workerError;
|
|
61
|
-
try {
|
|
62
|
-
const [exitCode] = await exitPromise;
|
|
63
|
-
clearTimeout(timeoutId);
|
|
64
|
-
if (progressIntervalId) clearInterval(progressIntervalId);
|
|
65
|
-
if (exitCode !== 0) {
|
|
66
|
-
workerError = `worker exited with code ${exitCode}`;
|
|
67
|
-
}
|
|
68
|
-
} catch (err) {
|
|
69
|
-
clearTimeout(timeoutId);
|
|
70
|
-
if (progressIntervalId) clearInterval(progressIntervalId);
|
|
71
|
-
workerError = err instanceof Error ? err.message : String(err);
|
|
72
|
-
}
|
|
73
|
-
const count = control[Control.INDEX];
|
|
74
|
-
const heapUsedKB = control[Control.HEAP_USED];
|
|
75
|
-
const durations = new BigUint64Array(durationsSAB).slice(0, count).sort(cmp);
|
|
76
|
-
const DCE_THRESHOLD_OPS = 5_000_000_000;
|
|
77
|
-
let dceWarning = false;
|
|
78
|
-
if (count > 0) {
|
|
79
|
-
let sum = 0n;
|
|
80
|
-
for (const d of durations)sum += d;
|
|
81
|
-
const avgNs = Number(sum / BigInt(count)) / 1000;
|
|
82
|
-
const opsPerSec = avgNs > 0 ? 1_000_000_000 / avgNs : Infinity;
|
|
83
|
-
if (opsPerSec > DCE_THRESHOLD_OPS) {
|
|
84
|
-
dceWarning = true;
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
const report = reportTypes.map((type)=>[
|
|
88
|
-
type,
|
|
89
|
-
createReport(durations, type)
|
|
90
|
-
]).concat([
|
|
91
|
-
[
|
|
92
|
-
'count',
|
|
93
|
-
count
|
|
94
|
-
],
|
|
95
|
-
[
|
|
96
|
-
'heapUsedKB',
|
|
97
|
-
heapUsedKB
|
|
98
|
-
],
|
|
99
|
-
[
|
|
100
|
-
'dceWarning',
|
|
101
|
-
dceWarning
|
|
102
|
-
],
|
|
103
|
-
[
|
|
104
|
-
'error',
|
|
105
|
-
workerError
|
|
106
|
-
]
|
|
107
|
-
]);
|
|
108
|
-
return Object.fromEntries(report);
|
|
109
|
-
}, workers);
|
|
110
|
-
return executor;
|
|
111
|
-
};
|
|
112
|
-
|
|
113
|
-
//# sourceMappingURL=executor.js.map
|
package/build/executor.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/executor.ts"],"sourcesContent":["import { Worker } from 'node:worker_threads';\nimport { once } from 'node:events';\nimport { queue } from 'async';\nimport { pathToFileURL } from 'node:url';\nimport { createReport, Report } from './reporter.js';\nimport { cmp, assertNoClosure } from './utils.js';\nimport {\n ExecutorRunOptions,\n ReportOptions,\n WorkerOptions,\n BenchmarkOptions,\n Control,\n ReportType,\n ReportTypeList,\n CONTROL_SLOTS,\n COMPLETE_VALUE,\n ProgressCallback,\n} from './types.js';\n\nexport type ExecutorReport<R extends ReportTypeList> = Record<R[number], Report> & {\n count: number;\n heapUsedKB: number;\n dceWarning: boolean;\n error?: string;\n};\n\nexport interface ExecutorOptions<R extends ReportTypeList> extends BenchmarkOptions, ReportOptions<R> {\n workers?: number;\n maxCycles?: number;\n onProgress?: ProgressCallback;\n progressInterval?: number;\n}\n\nconst BENCHMARK_URL = Symbol.for('overtake.benchmarkUrl');\n\nexport const createExecutor = <TContext, TInput, R extends ReportTypeList>(options: Required<ExecutorOptions<R>>) => {\n const { workers, warmupCycles, maxCycles, minCycles, absThreshold, relThreshold, gcObserver = true, reportTypes, onProgress, progressInterval = 100 } = options;\n const benchmarkUrl = (options as Record<symbol, unknown>)[BENCHMARK_URL];\n const resolvedBenchmarkUrl = typeof benchmarkUrl === 'string' ? benchmarkUrl : pathToFileURL(process.cwd()).href;\n\n const executor = queue<ExecutorRunOptions<TContext, TInput>>(async ({ id, setup, teardown, pre, run, post, data }) => {\n const setupCode = setup?.toString();\n const teardownCode = teardown?.toString();\n const preCode = pre?.toString();\n const runCode = run.toString()!;\n const postCode = post?.toString();\n\n if (setupCode) assertNoClosure(setupCode, 'setup');\n if (teardownCode) assertNoClosure(teardownCode, 'teardown');\n if (preCode) assertNoClosure(preCode, 'pre');\n assertNoClosure(runCode, 'run');\n if (postCode) assertNoClosure(postCode, 'post');\n\n const controlSAB = new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * CONTROL_SLOTS);\n const durationsSAB = new SharedArrayBuffer(BigUint64Array.BYTES_PER_ELEMENT * maxCycles);\n\n const workerFile = new URL('./worker.js', import.meta.url);\n const workerData: WorkerOptions = {\n benchmarkUrl: resolvedBenchmarkUrl,\n setupCode,\n teardownCode,\n preCode,\n runCode,\n postCode,\n data,\n\n warmupCycles,\n minCycles,\n absThreshold,\n relThreshold,\n gcObserver,\n\n controlSAB,\n durationsSAB,\n };\n\n const worker = new Worker(workerFile, {\n workerData,\n });\n\n const control = new Int32Array(controlSAB);\n let progressIntervalId: ReturnType<typeof setInterval> | undefined;\n if (onProgress && id) {\n progressIntervalId = setInterval(() => {\n const progress = control[Control.PROGRESS] / COMPLETE_VALUE;\n onProgress({ id, progress });\n }, progressInterval);\n }\n\n const WORKER_TIMEOUT_MS = 300_000;\n const exitPromise = once(worker, 'exit');\n const timeoutId = setTimeout(() => worker.terminate(), WORKER_TIMEOUT_MS);\n let workerError: string | undefined;\n try {\n const [exitCode] = await exitPromise;\n clearTimeout(timeoutId);\n if (progressIntervalId) clearInterval(progressIntervalId);\n if (exitCode !== 0) {\n workerError = `worker exited with code ${exitCode}`;\n }\n } catch (err) {\n clearTimeout(timeoutId);\n if (progressIntervalId) clearInterval(progressIntervalId);\n workerError = err instanceof Error ? err.message : String(err);\n }\n\n const count = control[Control.INDEX];\n const heapUsedKB = control[Control.HEAP_USED];\n const durations = new BigUint64Array(durationsSAB).slice(0, count).sort(cmp);\n\n const DCE_THRESHOLD_OPS = 5_000_000_000;\n let dceWarning = false;\n if (count > 0) {\n let sum = 0n;\n for (const d of durations) sum += d;\n const avgNs = Number(sum / BigInt(count)) / 1000;\n const opsPerSec = avgNs > 0 ? 1_000_000_000 / avgNs : Infinity;\n if (opsPerSec > DCE_THRESHOLD_OPS) {\n dceWarning = true;\n }\n }\n\n const report = reportTypes\n .map<[string, unknown]>((type) => [type, createReport(durations, type)] as [ReportType, Report])\n .concat([\n ['count', count],\n ['heapUsedKB', heapUsedKB],\n ['dceWarning', dceWarning],\n ['error', workerError],\n ]);\n return Object.fromEntries(report);\n }, workers);\n\n return executor;\n};\n"],"names":["Worker","once","queue","pathToFileURL","createReport","cmp","assertNoClosure","Control","CONTROL_SLOTS","COMPLETE_VALUE","BENCHMARK_URL","Symbol","for","createExecutor","options","workers","warmupCycles","maxCycles","minCycles","absThreshold","relThreshold","gcObserver","reportTypes","onProgress","progressInterval","benchmarkUrl","resolvedBenchmarkUrl","process","cwd","href","executor","id","setup","teardown","pre","run","post","data","setupCode","toString","teardownCode","preCode","runCode","postCode","controlSAB","SharedArrayBuffer","Int32Array","BYTES_PER_ELEMENT","durationsSAB","BigUint64Array","workerFile","URL","url","workerData","worker","control","progressIntervalId","setInterval","progress","PROGRESS","WORKER_TIMEOUT_MS","exitPromise","timeoutId","setTimeout","terminate","workerError","exitCode","clearTimeout","clearInterval","err","Error","message","String","count","INDEX","heapUsedKB","HEAP_USED","durations","slice","sort","DCE_THRESHOLD_OPS","dceWarning","sum","d","avgNs","Number","BigInt","opsPerSec","Infinity","report","map","type","concat","Object","fromEntries"],"mappings":"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"}
|
package/build/gc-watcher.cjs
DELETED
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", {
|
|
3
|
-
value: true
|
|
4
|
-
});
|
|
5
|
-
Object.defineProperty(exports, "GCWatcher", {
|
|
6
|
-
enumerable: true,
|
|
7
|
-
get: function() {
|
|
8
|
-
return GCWatcher;
|
|
9
|
-
}
|
|
10
|
-
});
|
|
11
|
-
class GCWatcher {
|
|
12
|
-
#registry = new FinalizationRegistry(()=>{});
|
|
13
|
-
start() {
|
|
14
|
-
const target = {};
|
|
15
|
-
const ref = new WeakRef(target);
|
|
16
|
-
this.#registry.register(target, null, ref);
|
|
17
|
-
return {
|
|
18
|
-
ref
|
|
19
|
-
};
|
|
20
|
-
}
|
|
21
|
-
seen(marker) {
|
|
22
|
-
const collected = marker.ref.deref() === undefined;
|
|
23
|
-
if (!collected) {
|
|
24
|
-
this.#registry.unregister(marker.ref);
|
|
25
|
-
}
|
|
26
|
-
return collected;
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
//# sourceMappingURL=gc-watcher.cjs.map
|
package/build/gc-watcher.cjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/gc-watcher.ts"],"sourcesContent":["export interface GCMarker {\n ref: WeakRef<object>;\n}\n\nexport class GCWatcher {\n #registry = new FinalizationRegistry(() => {});\n\n start(): GCMarker {\n const target = {};\n const ref = new WeakRef(target);\n this.#registry.register(target, null, ref);\n return { ref };\n }\n\n seen(marker: GCMarker): boolean {\n const collected = marker.ref.deref() === undefined;\n if (!collected) {\n this.#registry.unregister(marker.ref);\n }\n return collected;\n }\n}\n"],"names":["GCWatcher","FinalizationRegistry","start","target","ref","WeakRef","register","seen","marker","collected","deref","undefined","unregister"],"mappings":";;;;+BAIaA;;;eAAAA;;;AAAN,MAAMA;IACX,CAAA,QAAS,GAAG,IAAIC,qBAAqB,KAAO,GAAG;IAE/CC,QAAkB;QAChB,MAAMC,SAAS,CAAC;QAChB,MAAMC,MAAM,IAAIC,QAAQF;QACxB,IAAI,CAAC,CAAA,QAAS,CAACG,QAAQ,CAACH,QAAQ,MAAMC;QACtC,OAAO;YAAEA;QAAI;IACf;IAEAG,KAAKC,MAAgB,EAAW;QAC9B,MAAMC,YAAYD,OAAOJ,GAAG,CAACM,KAAK,OAAOC;QACzC,IAAI,CAACF,WAAW;YACd,IAAI,CAAC,CAAA,QAAS,CAACG,UAAU,CAACJ,OAAOJ,GAAG;QACtC;QACA,OAAOK;IACT;AACF"}
|
package/build/gc-watcher.js
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
export class GCWatcher {
|
|
2
|
-
#registry = new FinalizationRegistry(()=>{});
|
|
3
|
-
start() {
|
|
4
|
-
const target = {};
|
|
5
|
-
const ref = new WeakRef(target);
|
|
6
|
-
this.#registry.register(target, null, ref);
|
|
7
|
-
return {
|
|
8
|
-
ref
|
|
9
|
-
};
|
|
10
|
-
}
|
|
11
|
-
seen(marker) {
|
|
12
|
-
const collected = marker.ref.deref() === undefined;
|
|
13
|
-
if (!collected) {
|
|
14
|
-
this.#registry.unregister(marker.ref);
|
|
15
|
-
}
|
|
16
|
-
return collected;
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
//# sourceMappingURL=gc-watcher.js.map
|
package/build/gc-watcher.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/gc-watcher.ts"],"sourcesContent":["export interface GCMarker {\n ref: WeakRef<object>;\n}\n\nexport class GCWatcher {\n #registry = new FinalizationRegistry(() => {});\n\n start(): GCMarker {\n const target = {};\n const ref = new WeakRef(target);\n this.#registry.register(target, null, ref);\n return { ref };\n }\n\n seen(marker: GCMarker): boolean {\n const collected = marker.ref.deref() === undefined;\n if (!collected) {\n this.#registry.unregister(marker.ref);\n }\n return collected;\n }\n}\n"],"names":["GCWatcher","FinalizationRegistry","start","target","ref","WeakRef","register","seen","marker","collected","deref","undefined","unregister"],"mappings":"AAIA,OAAO,MAAMA;IACX,CAAA,QAAS,GAAG,IAAIC,qBAAqB,KAAO,GAAG;IAE/CC,QAAkB;QAChB,MAAMC,SAAS,CAAC;QAChB,MAAMC,MAAM,IAAIC,QAAQF;QACxB,IAAI,CAAC,CAAA,QAAS,CAACG,QAAQ,CAACH,QAAQ,MAAMC;QACtC,OAAO;YAAEA;QAAI;IACf;IAEAG,KAAKC,MAAgB,EAAW;QAC9B,MAAMC,YAAYD,OAAOJ,GAAG,CAACM,KAAK,OAAOC;QACzC,IAAI,CAACF,WAAW;YACd,IAAI,CAAC,CAAA,QAAS,CAACG,UAAU,CAACJ,OAAOJ,GAAG;QACtC;QACA,OAAOK;IACT;AACF"}
|