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.
Files changed (57) hide show
  1. package/README.md +4 -15
  2. package/bin/overtake.js +1 -1
  3. package/build/executor.d.ts +7 -3
  4. package/build/index.d.ts +10 -11
  5. package/build/reporter.d.ts +10 -2
  6. package/build/runner.d.ts +1 -1
  7. package/build/types.d.ts +6 -6
  8. package/build/utils.d.ts +1 -17
  9. package/package.json +8 -26
  10. package/src/__tests__/assert-no-closure.ts +135 -0
  11. package/src/__tests__/benchmark-execute.ts +48 -0
  12. package/src/cli.ts +139 -144
  13. package/src/executor.ts +48 -18
  14. package/src/index.ts +85 -57
  15. package/src/reporter.ts +27 -19
  16. package/src/runner.ts +2 -5
  17. package/src/types.ts +8 -8
  18. package/src/utils.ts +15 -54
  19. package/src/worker.ts +6 -3
  20. package/tsconfig.json +3 -1
  21. package/build/cli.cjs +0 -179
  22. package/build/cli.cjs.map +0 -1
  23. package/build/cli.js +0 -134
  24. package/build/cli.js.map +0 -1
  25. package/build/executor.cjs +0 -123
  26. package/build/executor.cjs.map +0 -1
  27. package/build/executor.js +0 -113
  28. package/build/executor.js.map +0 -1
  29. package/build/gc-watcher.cjs +0 -30
  30. package/build/gc-watcher.cjs.map +0 -1
  31. package/build/gc-watcher.js +0 -20
  32. package/build/gc-watcher.js.map +0 -1
  33. package/build/index.cjs +0 -442
  34. package/build/index.cjs.map +0 -1
  35. package/build/index.js +0 -377
  36. package/build/index.js.map +0 -1
  37. package/build/reporter.cjs +0 -311
  38. package/build/reporter.cjs.map +0 -1
  39. package/build/reporter.js +0 -293
  40. package/build/reporter.js.map +0 -1
  41. package/build/runner.cjs +0 -532
  42. package/build/runner.cjs.map +0 -1
  43. package/build/runner.js +0 -522
  44. package/build/runner.js.map +0 -1
  45. package/build/types.cjs +0 -66
  46. package/build/types.cjs.map +0 -1
  47. package/build/types.js +0 -33
  48. package/build/types.js.map +0 -1
  49. package/build/utils.cjs +0 -174
  50. package/build/utils.cjs.map +0 -1
  51. package/build/utils.js +0 -132
  52. package/build/utils.js.map +0 -1
  53. package/build/worker.cjs +0 -155
  54. package/build/worker.cjs.map +0 -1
  55. package/build/worker.js +0 -110
  56. package/build/worker.js.map +0 -1
  57. 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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"}
@@ -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
@@ -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
@@ -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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"}
@@ -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
@@ -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"}
@@ -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
@@ -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"}