overtake 1.1.1 → 1.1.2

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/build/cli.cjs CHANGED
@@ -54,6 +54,7 @@ function _interop_require_wildcard(obj, nodeInterop) {
54
54
  }
55
55
  const require1 = (0, _nodemodule.createRequire)(require("url").pathToFileURL(__filename).toString());
56
56
  const { name, description, version } = require1('../package.json');
57
+ const BENCHMARK_URL = Symbol.for('overtake.benchmarkUrl');
57
58
  const commander = new _commander.Command();
58
59
  commander.name(name).description(description).version(version).argument('<paths...>', 'glob pattern to find benchmarks').addOption(new _commander.Option('-r, --report-types [reportTypes...]', 'statistic types to include in the report').choices(_typescjs.REPORT_TYPES).default(_indexcjs.DEFAULT_REPORT_TYPES)).addOption(new _commander.Option('-w, --workers [workers]', 'number of concurent workers').default(_indexcjs.DEFAULT_WORKERS).argParser(parseInt)).addOption(new _commander.Option('-f, --format [format]', 'output format').default('simple').choices([
59
60
  'simple',
@@ -127,7 +128,7 @@ commander.name(name).description(description).version(version).argument('<paths.
127
128
  if (instance) {
128
129
  const reports = await instance.execute({
129
130
  ...executeOptions,
130
- baseUrl: identifier
131
+ [BENCHMARK_URL]: identifier
131
132
  });
132
133
  switch(executeOptions.format){
133
134
  case 'json':
package/build/cli.cjs.map CHANGED
@@ -1 +1 @@
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 } from 'node:fs/promises';\nimport { Command, Option } from 'commander';\nimport { glob } from 'glob';\nimport { Benchmark, printTableReports, printJSONReports, printSimpleReports, DEFAULT_REPORT_TYPES, DEFAULT_WORKERS } 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');\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']))\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 .action(async (patterns: string[], executeOptions) => {\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 script = new SourceTextModule(code, {\n identifier,\n context: createContext({\n benchmark,\n Buffer,\n console,\n }),\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 baseUrl: identifier,\n });\n switch (executeOptions.format) {\n case 'json':\n {\n printJSONReports(reports);\n }\n break;\n case 'pjson':\n {\n printJSONReports(reports, 2);\n }\n break;\n case 'table':\n {\n printTableReports(reports);\n }\n break;\n default:\n printSimpleReports(reports);\n }\n }\n }\n }\n });\n\ncommander.parse(process.argv);\n"],"names":["require","createRequire","name","description","version","commander","Command","argument","addOption","Option","choices","REPORT_TYPES","default","DEFAULT_REPORT_TYPES","DEFAULT_WORKERS","argParser","parseInt","parseFloat","action","patterns","executeOptions","files","Set","Promise","all","map","pattern","matches","glob","absolute","cwd","process","catch","forEach","file","add","stats","stat","isFile","content","readFile","identifier","pathToFileURL","href","code","transpile","instance","benchmark","args","Error","Benchmark","create","script","SourceTextModule","context","createContext","Buffer","console","initializeImportMeta","meta","url","importModuleDynamically","specifier","referencingModule","Module","isBuiltin","baseIdentifier","resolveFrom","fileURLToPath","resolved","resolve","imports","Map","link","target","cached","get","mod","exportNames","Object","keys","imported","SyntheticModule","key","setExport","set","evaluate","reports","execute","baseUrl","format","printJSONReports","printTableReports","printSimpleReports","parse","argv"],"mappings":"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"}
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 } from 'node:fs/promises';\nimport { Command, Option } from 'commander';\nimport { glob } from 'glob';\nimport { Benchmark, printTableReports, printJSONReports, printSimpleReports, DEFAULT_REPORT_TYPES, DEFAULT_WORKERS } 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']))\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 .action(async (patterns: string[], executeOptions) => {\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 script = new SourceTextModule(code, {\n identifier,\n context: createContext({\n benchmark,\n Buffer,\n console,\n }),\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 switch (executeOptions.format) {\n case 'json':\n {\n printJSONReports(reports);\n }\n break;\n case 'pjson':\n {\n printJSONReports(reports, 2);\n }\n break;\n case 'table':\n {\n printTableReports(reports);\n }\n break;\n default:\n printSimpleReports(reports);\n }\n }\n }\n }\n });\n\ncommander.parse(process.argv);\n"],"names":["require","createRequire","name","description","version","BENCHMARK_URL","Symbol","for","commander","Command","argument","addOption","Option","choices","REPORT_TYPES","default","DEFAULT_REPORT_TYPES","DEFAULT_WORKERS","argParser","parseInt","parseFloat","action","patterns","executeOptions","files","Set","Promise","all","map","pattern","matches","glob","absolute","cwd","process","catch","forEach","file","add","stats","stat","isFile","content","readFile","identifier","pathToFileURL","href","code","transpile","instance","benchmark","args","Error","Benchmark","create","script","SourceTextModule","context","createContext","Buffer","console","initializeImportMeta","meta","url","importModuleDynamically","specifier","referencingModule","Module","isBuiltin","baseIdentifier","resolveFrom","fileURLToPath","resolved","resolve","imports","Map","link","target","cached","get","mod","exportNames","Object","keys","imported","SyntheticModule","key","setExport","set","evaluate","reports","execute","format","printJSONReports","printTableReports","printSimpleReports","parse","argv"],"mappings":"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"}
package/build/cli.js CHANGED
@@ -9,6 +9,7 @@ import { transpile } from "./utils.js";
9
9
  import { REPORT_TYPES } from "./types.js";
10
10
  const require = createRequire(import.meta.url);
11
11
  const { name, description, version } = require('../package.json');
12
+ const BENCHMARK_URL = Symbol.for('overtake.benchmarkUrl');
12
13
  const commander = new Command();
13
14
  commander.name(name).description(description).version(version).argument('<paths...>', 'glob pattern to find benchmarks').addOption(new Option('-r, --report-types [reportTypes...]', 'statistic types to include in the report').choices(REPORT_TYPES).default(DEFAULT_REPORT_TYPES)).addOption(new Option('-w, --workers [workers]', 'number of concurent workers').default(DEFAULT_WORKERS).argParser(parseInt)).addOption(new Option('-f, --format [format]', 'output format').default('simple').choices([
14
15
  'simple',
@@ -82,7 +83,7 @@ commander.name(name).description(description).version(version).argument('<paths.
82
83
  if (instance) {
83
84
  const reports = await instance.execute({
84
85
  ...executeOptions,
85
- baseUrl: identifier
86
+ [BENCHMARK_URL]: identifier
86
87
  });
87
88
  switch(executeOptions.format){
88
89
  case 'json':
package/build/cli.js.map CHANGED
@@ -1 +1 @@
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 } from 'node:fs/promises';\nimport { Command, Option } from 'commander';\nimport { glob } from 'glob';\nimport { Benchmark, printTableReports, printJSONReports, printSimpleReports, DEFAULT_REPORT_TYPES, DEFAULT_WORKERS } 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');\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']))\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 .action(async (patterns: string[], executeOptions) => {\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 script = new SourceTextModule(code, {\n identifier,\n context: createContext({\n benchmark,\n Buffer,\n console,\n }),\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 baseUrl: identifier,\n });\n switch (executeOptions.format) {\n case 'json':\n {\n printJSONReports(reports);\n }\n break;\n case 'pjson':\n {\n printJSONReports(reports, 2);\n }\n break;\n case 'table':\n {\n printTableReports(reports);\n }\n break;\n default:\n printSimpleReports(reports);\n }\n }\n }\n }\n });\n\ncommander.parse(process.argv);\n"],"names":["createRequire","Module","fileURLToPath","pathToFileURL","SyntheticModule","createContext","SourceTextModule","stat","readFile","Command","Option","glob","Benchmark","printTableReports","printJSONReports","printSimpleReports","DEFAULT_REPORT_TYPES","DEFAULT_WORKERS","transpile","REPORT_TYPES","require","url","name","description","version","commander","argument","addOption","choices","default","argParser","parseInt","parseFloat","action","patterns","executeOptions","files","Set","Promise","all","map","pattern","matches","absolute","cwd","process","catch","forEach","file","add","stats","isFile","content","identifier","href","code","instance","benchmark","args","Error","create","script","context","Buffer","console","initializeImportMeta","meta","importModuleDynamically","specifier","referencingModule","isBuiltin","baseIdentifier","resolveFrom","resolved","resolve","imports","Map","link","target","cached","get","mod","exportNames","Object","keys","imported","key","setExport","set","evaluate","reports","execute","baseUrl","format","parse","argv"],"mappings":"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"}
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 } from 'node:fs/promises';\nimport { Command, Option } from 'commander';\nimport { glob } from 'glob';\nimport { Benchmark, printTableReports, printJSONReports, printSimpleReports, DEFAULT_REPORT_TYPES, DEFAULT_WORKERS } 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']))\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 .action(async (patterns: string[], executeOptions) => {\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 script = new SourceTextModule(code, {\n identifier,\n context: createContext({\n benchmark,\n Buffer,\n console,\n }),\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 switch (executeOptions.format) {\n case 'json':\n {\n printJSONReports(reports);\n }\n break;\n case 'pjson':\n {\n printJSONReports(reports, 2);\n }\n break;\n case 'table':\n {\n printTableReports(reports);\n }\n break;\n default:\n printSimpleReports(reports);\n }\n }\n }\n }\n });\n\ncommander.parse(process.argv);\n"],"names":["createRequire","Module","fileURLToPath","pathToFileURL","SyntheticModule","createContext","SourceTextModule","stat","readFile","Command","Option","glob","Benchmark","printTableReports","printJSONReports","printSimpleReports","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","files","Set","Promise","all","map","pattern","matches","absolute","cwd","process","catch","forEach","file","add","stats","isFile","content","identifier","href","code","instance","benchmark","args","Error","create","script","context","Buffer","console","initializeImportMeta","meta","importModuleDynamically","specifier","referencingModule","isBuiltin","baseIdentifier","resolveFrom","resolved","resolve","imports","Map","link","target","cached","get","mod","exportNames","Object","keys","imported","key","setExport","set","evaluate","reports","execute","format","parse","argv"],"mappings":"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"}
@@ -15,8 +15,12 @@ const _nodeurl = require("node:url");
15
15
  const _reportercjs = require("./reporter.cjs");
16
16
  const _utilscjs = require("./utils.cjs");
17
17
  const _typescjs = require("./types.cjs");
18
- const createExecutor = ({ baseUrl = (0, _nodeurl.pathToFileURL)(process.cwd()).href, workers, warmupCycles, maxCycles, minCycles, absThreshold, relThreshold, gcObserver = true, reportTypes })=>{
19
- const executor = (0, _async.queue)(async ({ baseUrl: runBaseUrl = baseUrl, setup, teardown, pre, run, post, data })=>{
18
+ const BENCHMARK_URL = Symbol.for('overtake.benchmarkUrl');
19
+ const createExecutor = (options)=>{
20
+ const { workers, warmupCycles, maxCycles, minCycles, absThreshold, relThreshold, gcObserver = true, reportTypes } = 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 ({ setup, teardown, pre, run, post, data })=>{
20
24
  const setupCode = setup?.toString();
21
25
  const teardownCode = teardown?.toString();
22
26
  const preCode = pre?.toString();
@@ -26,7 +30,7 @@ const createExecutor = ({ baseUrl = (0, _nodeurl.pathToFileURL)(process.cwd()).h
26
30
  const durationsSAB = new SharedArrayBuffer(BigUint64Array.BYTES_PER_ELEMENT * maxCycles);
27
31
  const workerFile = new URL('./worker.js', require("url").pathToFileURL(__filename).toString());
28
32
  const workerData = {
29
- baseUrl: runBaseUrl,
33
+ benchmarkUrl: resolvedBenchmarkUrl,
30
34
  setupCode,
31
35
  teardownCode,
32
36
  preCode,
@@ -1 +1 @@
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 } from './utils.js';\nimport { RunOptions, ReportOptions, WorkerOptions, BenchmarkOptions, Control, ReportType, ReportTypeList, CONTROL_SLOTS } from './types.js';\n\nexport type ExecutorReport<R extends ReportTypeList> = Record<R[number], Report> & { count: number };\n\nexport interface ExecutorOptions<R extends ReportTypeList> extends BenchmarkOptions, ReportOptions<R> {\n baseUrl?: string;\n workers?: number;\n maxCycles?: number;\n}\n\nexport const createExecutor = <TContext, TInput, R extends ReportTypeList>({\n baseUrl = pathToFileURL(process.cwd()).href,\n workers,\n warmupCycles,\n maxCycles,\n minCycles,\n absThreshold,\n relThreshold,\n gcObserver = true,\n reportTypes,\n}: Required<ExecutorOptions<R>>) => {\n const executor = queue<RunOptions<TContext, TInput>>(async ({ baseUrl: runBaseUrl = baseUrl, 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 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 baseUrl: runBaseUrl,\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 const [exitCode] = await once(worker, 'exit');\n if (exitCode !== 0) {\n throw new Error(`worker exited with code ${exitCode}`);\n }\n\n const control = new Int32Array(controlSAB);\n const count = control[Control.INDEX];\n const durations = new BigUint64Array(durationsSAB).slice(0, count).sort(cmp);\n\n const report = reportTypes.map<[string, unknown]>((type) => [type, createReport(durations, type)] as [ReportType, Report]).concat([['count', count]]);\n return Object.fromEntries(report);\n }, workers);\n\n executor.error((err) => {\n console.error(err);\n });\n\n return executor;\n};\n"],"names":["createExecutor","baseUrl","pathToFileURL","process","cwd","href","workers","warmupCycles","maxCycles","minCycles","absThreshold","relThreshold","gcObserver","reportTypes","executor","queue","runBaseUrl","setup","teardown","pre","run","post","data","setupCode","toString","teardownCode","preCode","runCode","postCode","controlSAB","SharedArrayBuffer","Int32Array","BYTES_PER_ELEMENT","CONTROL_SLOTS","durationsSAB","BigUint64Array","workerFile","URL","workerData","worker","Worker","exitCode","once","Error","control","count","Control","INDEX","durations","slice","sort","cmp","report","map","type","createReport","concat","Object","fromEntries","error","err","console"],"mappings":";;;;+BAgBaA;;;eAAAA;;;oCAhBU;4BACF;uBACC;yBACQ;6BACO;0BACjB;0BAC2G;AAUxH,MAAMA,iBAAiB,CAA6C,EACzEC,UAAUC,IAAAA,sBAAa,EAACC,QAAQC,GAAG,IAAIC,IAAI,EAC3CC,OAAO,EACPC,YAAY,EACZC,SAAS,EACTC,SAAS,EACTC,YAAY,EACZC,YAAY,EACZC,aAAa,IAAI,EACjBC,WAAW,EACkB;IAC7B,MAAMC,WAAWC,IAAAA,YAAK,EAA+B,OAAO,EAAEd,SAASe,aAAaf,OAAO,EAAEgB,KAAK,EAAEC,QAAQ,EAAEC,GAAG,EAAEC,GAAG,EAAEC,IAAI,EAAEC,IAAI,EAAE;QAClI,MAAMC,YAAYN,OAAOO;QACzB,MAAMC,eAAeP,UAAUM;QAC/B,MAAME,UAAUP,KAAKK;QACrB,MAAMG,UAAUP,IAAII,QAAQ;QAC5B,MAAMI,WAAWP,MAAMG;QAEvB,MAAMK,aAAa,IAAIC,kBAAkBC,WAAWC,iBAAiB,GAAGC,uBAAa;QACrF,MAAMC,eAAe,IAAIJ,kBAAkBK,eAAeH,iBAAiB,GAAGxB;QAE9E,MAAM4B,aAAa,IAAIC,IAAI,eAAe;QAC1C,MAAMC,aAA4B;YAChCrC,SAASe;YACTO;YACAE;YACAC;YACAC;YACAC;YACAN;YAEAf;YACAE;YACAC;YACAC;YACAC;YAEAiB;YACAK;QACF;QAEA,MAAMK,SAAS,IAAIC,0BAAM,CAACJ,YAAY;YACpCE;QACF;QACA,MAAM,CAACG,SAAS,GAAG,MAAMC,IAAAA,gBAAI,EAACH,QAAQ;QACtC,IAAIE,aAAa,GAAG;YAClB,MAAM,IAAIE,MAAM,CAAC,wBAAwB,EAAEF,UAAU;QACvD;QAEA,MAAMG,UAAU,IAAIb,WAAWF;QAC/B,MAAMgB,QAAQD,OAAO,CAACE,iBAAO,CAACC,KAAK,CAAC;QACpC,MAAMC,YAAY,IAAIb,eAAeD,cAAce,KAAK,CAAC,GAAGJ,OAAOK,IAAI,CAACC,aAAG;QAE3E,MAAMC,SAASvC,YAAYwC,GAAG,CAAoB,CAACC,OAAS;gBAACA;gBAAMC,IAAAA,yBAAY,EAACP,WAAWM;aAAM,EAA0BE,MAAM,CAAC;YAAC;gBAAC;gBAASX;aAAM;SAAC;QACpJ,OAAOY,OAAOC,WAAW,CAACN;IAC5B,GAAG9C;IAEHQ,SAAS6C,KAAK,CAAC,CAACC;QACdC,QAAQF,KAAK,CAACC;IAChB;IAEA,OAAO9C;AACT"}
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 } from './utils.js';\nimport { RunOptions, ReportOptions, WorkerOptions, BenchmarkOptions, Control, ReportType, ReportTypeList, CONTROL_SLOTS } from './types.js';\n\nexport type ExecutorReport<R extends ReportTypeList> = Record<R[number], Report> & { count: number };\n\nexport interface ExecutorOptions<R extends ReportTypeList> extends BenchmarkOptions, ReportOptions<R> {\n workers?: number;\n maxCycles?: 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 } = 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<RunOptions<TContext, TInput>>(async ({ 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 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 const [exitCode] = await once(worker, 'exit');\n if (exitCode !== 0) {\n throw new Error(`worker exited with code ${exitCode}`);\n }\n\n const control = new Int32Array(controlSAB);\n const count = control[Control.INDEX];\n const durations = new BigUint64Array(durationsSAB).slice(0, count).sort(cmp);\n\n const report = reportTypes.map<[string, unknown]>((type) => [type, createReport(durations, type)] as [ReportType, Report]).concat([['count', count]]);\n return Object.fromEntries(report);\n }, workers);\n\n executor.error((err) => {\n console.error(err);\n });\n\n return executor;\n};\n"],"names":["createExecutor","BENCHMARK_URL","Symbol","for","options","workers","warmupCycles","maxCycles","minCycles","absThreshold","relThreshold","gcObserver","reportTypes","benchmarkUrl","resolvedBenchmarkUrl","pathToFileURL","process","cwd","href","executor","queue","setup","teardown","pre","run","post","data","setupCode","toString","teardownCode","preCode","runCode","postCode","controlSAB","SharedArrayBuffer","Int32Array","BYTES_PER_ELEMENT","CONTROL_SLOTS","durationsSAB","BigUint64Array","workerFile","URL","workerData","worker","Worker","exitCode","once","Error","control","count","Control","INDEX","durations","slice","sort","cmp","report","map","type","createReport","concat","Object","fromEntries","error","err","console"],"mappings":";;;;+BAiBaA;;;eAAAA;;;oCAjBU;4BACF;uBACC;yBACQ;6BACO;0BACjB;0BAC2G;AAS/H,MAAMC,gBAAgBC,OAAOC,GAAG,CAAC;AAE1B,MAAMH,iBAAiB,CAA6CI;IACzE,MAAM,EAAEC,OAAO,EAAEC,YAAY,EAAEC,SAAS,EAAEC,SAAS,EAAEC,YAAY,EAAEC,YAAY,EAAEC,aAAa,IAAI,EAAEC,WAAW,EAAE,GAAGR;IACpH,MAAMS,eAAe,AAACT,OAAmC,CAACH,cAAc;IACxE,MAAMa,uBAAuB,OAAOD,iBAAiB,WAAWA,eAAeE,IAAAA,sBAAa,EAACC,QAAQC,GAAG,IAAIC,IAAI;IAEhH,MAAMC,WAAWC,IAAAA,YAAK,EAA+B,OAAO,EAAEC,KAAK,EAAEC,QAAQ,EAAEC,GAAG,EAAEC,GAAG,EAAEC,IAAI,EAAEC,IAAI,EAAE;QACnG,MAAMC,YAAYN,OAAOO;QACzB,MAAMC,eAAeP,UAAUM;QAC/B,MAAME,UAAUP,KAAKK;QACrB,MAAMG,UAAUP,IAAII,QAAQ;QAC5B,MAAMI,WAAWP,MAAMG;QAEvB,MAAMK,aAAa,IAAIC,kBAAkBC,WAAWC,iBAAiB,GAAGC,uBAAa;QACrF,MAAMC,eAAe,IAAIJ,kBAAkBK,eAAeH,iBAAiB,GAAG7B;QAE9E,MAAMiC,aAAa,IAAIC,IAAI,eAAe;QAC1C,MAAMC,aAA4B;YAChC7B,cAAcC;YACda;YACAE;YACAC;YACAC;YACAC;YACAN;YAEApB;YACAE;YACAC;YACAC;YACAC;YAEAsB;YACAK;QACF;QAEA,MAAMK,SAAS,IAAIC,0BAAM,CAACJ,YAAY;YACpCE;QACF;QACA,MAAM,CAACG,SAAS,GAAG,MAAMC,IAAAA,gBAAI,EAACH,QAAQ;QACtC,IAAIE,aAAa,GAAG;YAClB,MAAM,IAAIE,MAAM,CAAC,wBAAwB,EAAEF,UAAU;QACvD;QAEA,MAAMG,UAAU,IAAIb,WAAWF;QAC/B,MAAMgB,QAAQD,OAAO,CAACE,iBAAO,CAACC,KAAK,CAAC;QACpC,MAAMC,YAAY,IAAIb,eAAeD,cAAce,KAAK,CAAC,GAAGJ,OAAOK,IAAI,CAACC,aAAG;QAE3E,MAAMC,SAAS5C,YAAY6C,GAAG,CAAoB,CAACC,OAAS;gBAACA;gBAAMC,IAAAA,yBAAY,EAACP,WAAWM;aAAM,EAA0BE,MAAM,CAAC;YAAC;gBAAC;gBAASX;aAAM;SAAC;QACpJ,OAAOY,OAAOC,WAAW,CAACN;IAC5B,GAAGnD;IAEHc,SAAS4C,KAAK,CAAC,CAACC;QACdC,QAAQF,KAAK,CAACC;IAChB;IAEA,OAAO7C;AACT"}
@@ -4,8 +4,7 @@ export type ExecutorReport<R extends ReportTypeList> = Record<R[number], Report>
4
4
  count: number;
5
5
  };
6
6
  export interface ExecutorOptions<R extends ReportTypeList> extends BenchmarkOptions, ReportOptions<R> {
7
- baseUrl?: string;
8
7
  workers?: number;
9
8
  maxCycles?: number;
10
9
  }
11
- export declare const createExecutor: <TContext, TInput, R extends ReportTypeList>({ baseUrl, workers, warmupCycles, maxCycles, minCycles, absThreshold, relThreshold, gcObserver, reportTypes, }: Required<ExecutorOptions<R>>) => import("async").QueueObject<RunOptions<TContext, TInput>>;
10
+ export declare const createExecutor: <TContext, TInput, R extends ReportTypeList>(options: Required<ExecutorOptions<R>>) => import("async").QueueObject<RunOptions<TContext, TInput>>;
package/build/executor.js CHANGED
@@ -5,8 +5,12 @@ import { pathToFileURL } from 'node:url';
5
5
  import { createReport } from "./reporter.js";
6
6
  import { cmp } from "./utils.js";
7
7
  import { Control, CONTROL_SLOTS } from "./types.js";
8
- export const createExecutor = ({ baseUrl = pathToFileURL(process.cwd()).href, workers, warmupCycles, maxCycles, minCycles, absThreshold, relThreshold, gcObserver = true, reportTypes })=>{
9
- const executor = queue(async ({ baseUrl: runBaseUrl = baseUrl, setup, teardown, pre, run, post, data })=>{
8
+ const BENCHMARK_URL = Symbol.for('overtake.benchmarkUrl');
9
+ export const createExecutor = (options)=>{
10
+ const { workers, warmupCycles, maxCycles, minCycles, absThreshold, relThreshold, gcObserver = true, reportTypes } = options;
11
+ const benchmarkUrl = options[BENCHMARK_URL];
12
+ const resolvedBenchmarkUrl = typeof benchmarkUrl === 'string' ? benchmarkUrl : pathToFileURL(process.cwd()).href;
13
+ const executor = queue(async ({ setup, teardown, pre, run, post, data })=>{
10
14
  const setupCode = setup?.toString();
11
15
  const teardownCode = teardown?.toString();
12
16
  const preCode = pre?.toString();
@@ -16,7 +20,7 @@ export const createExecutor = ({ baseUrl = pathToFileURL(process.cwd()).href, wo
16
20
  const durationsSAB = new SharedArrayBuffer(BigUint64Array.BYTES_PER_ELEMENT * maxCycles);
17
21
  const workerFile = new URL('./worker.js', import.meta.url);
18
22
  const workerData = {
19
- baseUrl: runBaseUrl,
23
+ benchmarkUrl: resolvedBenchmarkUrl,
20
24
  setupCode,
21
25
  teardownCode,
22
26
  preCode,
@@ -1 +1 @@
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 } from './utils.js';\nimport { RunOptions, ReportOptions, WorkerOptions, BenchmarkOptions, Control, ReportType, ReportTypeList, CONTROL_SLOTS } from './types.js';\n\nexport type ExecutorReport<R extends ReportTypeList> = Record<R[number], Report> & { count: number };\n\nexport interface ExecutorOptions<R extends ReportTypeList> extends BenchmarkOptions, ReportOptions<R> {\n baseUrl?: string;\n workers?: number;\n maxCycles?: number;\n}\n\nexport const createExecutor = <TContext, TInput, R extends ReportTypeList>({\n baseUrl = pathToFileURL(process.cwd()).href,\n workers,\n warmupCycles,\n maxCycles,\n minCycles,\n absThreshold,\n relThreshold,\n gcObserver = true,\n reportTypes,\n}: Required<ExecutorOptions<R>>) => {\n const executor = queue<RunOptions<TContext, TInput>>(async ({ baseUrl: runBaseUrl = baseUrl, 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 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 baseUrl: runBaseUrl,\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 const [exitCode] = await once(worker, 'exit');\n if (exitCode !== 0) {\n throw new Error(`worker exited with code ${exitCode}`);\n }\n\n const control = new Int32Array(controlSAB);\n const count = control[Control.INDEX];\n const durations = new BigUint64Array(durationsSAB).slice(0, count).sort(cmp);\n\n const report = reportTypes.map<[string, unknown]>((type) => [type, createReport(durations, type)] as [ReportType, Report]).concat([['count', count]]);\n return Object.fromEntries(report);\n }, workers);\n\n executor.error((err) => {\n console.error(err);\n });\n\n return executor;\n};\n"],"names":["Worker","once","queue","pathToFileURL","createReport","cmp","Control","CONTROL_SLOTS","createExecutor","baseUrl","process","cwd","href","workers","warmupCycles","maxCycles","minCycles","absThreshold","relThreshold","gcObserver","reportTypes","executor","runBaseUrl","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","exitCode","Error","control","count","INDEX","durations","slice","sort","report","map","type","concat","Object","fromEntries","error","err","console"],"mappings":"AAAA,SAASA,MAAM,QAAQ,sBAAsB;AAC7C,SAASC,IAAI,QAAQ,cAAc;AACnC,SAASC,KAAK,QAAQ,QAAQ;AAC9B,SAASC,aAAa,QAAQ,WAAW;AACzC,SAASC,YAAY,QAAgB,gBAAgB;AACrD,SAASC,GAAG,QAAQ,aAAa;AACjC,SAAqEC,OAAO,EAA8BC,aAAa,QAAQ,aAAa;AAU5I,OAAO,MAAMC,iBAAiB,CAA6C,EACzEC,UAAUN,cAAcO,QAAQC,GAAG,IAAIC,IAAI,EAC3CC,OAAO,EACPC,YAAY,EACZC,SAAS,EACTC,SAAS,EACTC,YAAY,EACZC,YAAY,EACZC,aAAa,IAAI,EACjBC,WAAW,EACkB;IAC7B,MAAMC,WAAWnB,MAAoC,OAAO,EAAEO,SAASa,aAAab,OAAO,EAAEc,KAAK,EAAEC,QAAQ,EAAEC,GAAG,EAAEC,GAAG,EAAEC,IAAI,EAAEC,IAAI,EAAE;QAClI,MAAMC,YAAYN,OAAOO;QACzB,MAAMC,eAAeP,UAAUM;QAC/B,MAAME,UAAUP,KAAKK;QACrB,MAAMG,UAAUP,IAAII,QAAQ;QAC5B,MAAMI,WAAWP,MAAMG;QAEvB,MAAMK,aAAa,IAAIC,kBAAkBC,WAAWC,iBAAiB,GAAG/B;QACxE,MAAMgC,eAAe,IAAIH,kBAAkBI,eAAeF,iBAAiB,GAAGvB;QAE9E,MAAM0B,aAAa,IAAIC,IAAI,eAAe,YAAYC,GAAG;QACzD,MAAMC,aAA4B;YAChCnC,SAASa;YACTO;YACAE;YACAC;YACAC;YACAC;YACAN;YAEAd;YACAE;YACAC;YACAC;YACAC;YAEAgB;YACAI;QACF;QAEA,MAAMM,SAAS,IAAI7C,OAAOyC,YAAY;YACpCG;QACF;QACA,MAAM,CAACE,SAAS,GAAG,MAAM7C,KAAK4C,QAAQ;QACtC,IAAIC,aAAa,GAAG;YAClB,MAAM,IAAIC,MAAM,CAAC,wBAAwB,EAAED,UAAU;QACvD;QAEA,MAAME,UAAU,IAAIX,WAAWF;QAC/B,MAAMc,QAAQD,OAAO,CAAC1C,QAAQ4C,KAAK,CAAC;QACpC,MAAMC,YAAY,IAAIX,eAAeD,cAAca,KAAK,CAAC,GAAGH,OAAOI,IAAI,CAAChD;QAExE,MAAMiD,SAASlC,YAAYmC,GAAG,CAAoB,CAACC,OAAS;gBAACA;gBAAMpD,aAAa+C,WAAWK;aAAM,EAA0BC,MAAM,CAAC;YAAC;gBAAC;gBAASR;aAAM;SAAC;QACpJ,OAAOS,OAAOC,WAAW,CAACL;IAC5B,GAAGzC;IAEHQ,SAASuC,KAAK,CAAC,CAACC;QACdC,QAAQF,KAAK,CAACC;IAChB;IAEA,OAAOxC;AACT,EAAE"}
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 } from './utils.js';\nimport { RunOptions, ReportOptions, WorkerOptions, BenchmarkOptions, Control, ReportType, ReportTypeList, CONTROL_SLOTS } from './types.js';\n\nexport type ExecutorReport<R extends ReportTypeList> = Record<R[number], Report> & { count: number };\n\nexport interface ExecutorOptions<R extends ReportTypeList> extends BenchmarkOptions, ReportOptions<R> {\n workers?: number;\n maxCycles?: 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 } = 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<RunOptions<TContext, TInput>>(async ({ 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 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 const [exitCode] = await once(worker, 'exit');\n if (exitCode !== 0) {\n throw new Error(`worker exited with code ${exitCode}`);\n }\n\n const control = new Int32Array(controlSAB);\n const count = control[Control.INDEX];\n const durations = new BigUint64Array(durationsSAB).slice(0, count).sort(cmp);\n\n const report = reportTypes.map<[string, unknown]>((type) => [type, createReport(durations, type)] as [ReportType, Report]).concat([['count', count]]);\n return Object.fromEntries(report);\n }, workers);\n\n executor.error((err) => {\n console.error(err);\n });\n\n return executor;\n};\n"],"names":["Worker","once","queue","pathToFileURL","createReport","cmp","Control","CONTROL_SLOTS","BENCHMARK_URL","Symbol","for","createExecutor","options","workers","warmupCycles","maxCycles","minCycles","absThreshold","relThreshold","gcObserver","reportTypes","benchmarkUrl","resolvedBenchmarkUrl","process","cwd","href","executor","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","exitCode","Error","control","count","INDEX","durations","slice","sort","report","map","type","concat","Object","fromEntries","error","err","console"],"mappings":"AAAA,SAASA,MAAM,QAAQ,sBAAsB;AAC7C,SAASC,IAAI,QAAQ,cAAc;AACnC,SAASC,KAAK,QAAQ,QAAQ;AAC9B,SAASC,aAAa,QAAQ,WAAW;AACzC,SAASC,YAAY,QAAgB,gBAAgB;AACrD,SAASC,GAAG,QAAQ,aAAa;AACjC,SAAqEC,OAAO,EAA8BC,aAAa,QAAQ,aAAa;AAS5I,MAAMC,gBAAgBC,OAAOC,GAAG,CAAC;AAEjC,OAAO,MAAMC,iBAAiB,CAA6CC;IACzE,MAAM,EAAEC,OAAO,EAAEC,YAAY,EAAEC,SAAS,EAAEC,SAAS,EAAEC,YAAY,EAAEC,YAAY,EAAEC,aAAa,IAAI,EAAEC,WAAW,EAAE,GAAGR;IACpH,MAAMS,eAAe,AAACT,OAAmC,CAACJ,cAAc;IACxE,MAAMc,uBAAuB,OAAOD,iBAAiB,WAAWA,eAAelB,cAAcoB,QAAQC,GAAG,IAAIC,IAAI;IAEhH,MAAMC,WAAWxB,MAAoC,OAAO,EAAEyB,KAAK,EAAEC,QAAQ,EAAEC,GAAG,EAAEC,GAAG,EAAEC,IAAI,EAAEC,IAAI,EAAE;QACnG,MAAMC,YAAYN,OAAOO;QACzB,MAAMC,eAAeP,UAAUM;QAC/B,MAAME,UAAUP,KAAKK;QACrB,MAAMG,UAAUP,IAAII,QAAQ;QAC5B,MAAMI,WAAWP,MAAMG;QAEvB,MAAMK,aAAa,IAAIC,kBAAkBC,WAAWC,iBAAiB,GAAGnC;QACxE,MAAMoC,eAAe,IAAIH,kBAAkBI,eAAeF,iBAAiB,GAAG3B;QAE9E,MAAM8B,aAAa,IAAIC,IAAI,eAAe,YAAYC,GAAG;QACzD,MAAMC,aAA4B;YAChC3B,cAAcC;YACdW;YACAE;YACAC;YACAC;YACAC;YACAN;YAEAlB;YACAE;YACAC;YACAC;YACAC;YAEAoB;YACAI;QACF;QAEA,MAAMM,SAAS,IAAIjD,OAAO6C,YAAY;YACpCG;QACF;QACA,MAAM,CAACE,SAAS,GAAG,MAAMjD,KAAKgD,QAAQ;QACtC,IAAIC,aAAa,GAAG;YAClB,MAAM,IAAIC,MAAM,CAAC,wBAAwB,EAAED,UAAU;QACvD;QAEA,MAAME,UAAU,IAAIX,WAAWF;QAC/B,MAAMc,QAAQD,OAAO,CAAC9C,QAAQgD,KAAK,CAAC;QACpC,MAAMC,YAAY,IAAIX,eAAeD,cAAca,KAAK,CAAC,GAAGH,OAAOI,IAAI,CAACpD;QAExE,MAAMqD,SAAStC,YAAYuC,GAAG,CAAoB,CAACC,OAAS;gBAACA;gBAAMxD,aAAamD,WAAWK;aAAM,EAA0BC,MAAM,CAAC;YAAC;gBAAC;gBAASR;aAAM;SAAC;QACpJ,OAAOS,OAAOC,WAAW,CAACL;IAC5B,GAAG7C;IAEHa,SAASsC,KAAK,CAAC,CAACC;QACdC,QAAQF,KAAK,CAACC;IAChB;IAEA,OAAOvC;AACT,EAAE"}
package/build/index.cjs CHANGED
@@ -47,11 +47,11 @@ _export(exports, {
47
47
  }
48
48
  });
49
49
  const _nodeos = require("node:os");
50
- const _nodeurl = require("node:url");
51
50
  const _executorcjs = require("./executor.cjs");
52
51
  const _typescjs = require("./types.cjs");
53
52
  const DEFAULT_WORKERS = (0, _nodeos.cpus)().length;
54
53
  const AsyncFunction = (async ()=>{}).constructor;
54
+ const BENCHMARK_URL = Symbol.for('overtake.benchmarkUrl');
55
55
  const DEFAULT_REPORT_TYPES = [
56
56
  'ops'
57
57
  ];
@@ -140,17 +140,14 @@ class Benchmark {
140
140
  this.#targets.push(target);
141
141
  return new Target(target);
142
142
  }
143
- async execute({ workers = DEFAULT_WORKERS, warmupCycles = 20, maxCycles = _typescjs.DEFAULT_CYCLES, minCycles = 50, absThreshold = 1_000, relThreshold = 0.02, gcObserver = true, reportTypes = DEFAULT_REPORT_TYPES, baseUrl }) {
143
+ async execute(options) {
144
+ const { workers = DEFAULT_WORKERS, warmupCycles = 20, maxCycles = _typescjs.DEFAULT_CYCLES, minCycles = 50, absThreshold = 1_000, relThreshold = 0.02, gcObserver = true, reportTypes = DEFAULT_REPORT_TYPES } = options;
144
145
  if (this.#executed) {
145
146
  throw new Error("Benchmark is executed and can't be reused");
146
147
  }
147
148
  this.#executed = true;
148
- const resolvedBaseUrl = baseUrl ?? (0, _nodeurl.pathToFileURL)(process.cwd()).href;
149
- if (!baseUrl) {
150
- console.warn("Overtake: baseUrl not provided; defaulting to process.cwd(). Pass the benchmark's import.meta.url so relative imports resolve correctly.");
151
- }
149
+ const benchmarkUrl = options[BENCHMARK_URL];
152
150
  const executor = (0, _executorcjs.createExecutor)({
153
- baseUrl: resolvedBaseUrl,
154
151
  workers,
155
152
  warmupCycles,
156
153
  maxCycles,
@@ -158,7 +155,8 @@ class Benchmark {
158
155
  absThreshold,
159
156
  relThreshold,
160
157
  gcObserver,
161
- reportTypes
158
+ reportTypes,
159
+ [BENCHMARK_URL]: benchmarkUrl
162
160
  });
163
161
  const reports = [];
164
162
  for (const target of this.#targets){
@@ -174,7 +172,6 @@ class Benchmark {
174
172
  for (const feed of this.#feeds){
175
173
  const data = await feed.fn?.();
176
174
  executor.push({
177
- baseUrl: resolvedBaseUrl,
178
175
  setup: target.setup,
179
176
  teardown: target.teardown,
180
177
  pre: measure.pre,
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"sourcesContent":["import { cpus } from 'node:os';\nimport { pathToFileURL } from 'node:url';\nimport { createExecutor, ExecutorOptions, ExecutorReport } from './executor.js';\nimport { MaybePromise, StepFn, SetupFn, TeardownFn, FeedFn, ReportType, ReportTypeList, DEFAULT_CYCLES } from './types.js';\n\ndeclare global {\n const benchmark: typeof Benchmark.create;\n}\n\nexport const DEFAULT_WORKERS = cpus().length;\n\nexport const AsyncFunction = (async () => {}).constructor;\n\nexport interface TargetReport<R extends ReportTypeList> {\n target: string;\n measures: MeasureReport<R>[];\n}\n\nexport interface MeasureReport<R extends ReportTypeList> {\n measure: string;\n feeds: FeedReport<R>[];\n}\n\nexport interface FeedReport<R extends ReportTypeList> {\n feed: string;\n data: ExecutorReport<R>;\n}\n\nexport const DEFAULT_REPORT_TYPES = ['ops'] as const;\nexport type DefaultReportTypes = (typeof DEFAULT_REPORT_TYPES)[number];\n\nexport class MeasureContext<TContext, TInput> {\n public pre?: StepFn<TContext, TInput>;\n public post?: StepFn<TContext, TInput>;\n\n constructor(\n public title: string,\n public run: StepFn<TContext, TInput>,\n ) {}\n}\n\nexport class Measure<TContext, TInput> {\n #ctx: MeasureContext<TContext, TInput>;\n\n constructor(ctx: MeasureContext<TContext, TInput>) {\n this.#ctx = ctx;\n }\n\n pre(fn: StepFn<TContext, TInput>): Measure<TContext, TInput> {\n this.#ctx.pre = fn;\n return this;\n }\n post(fn: StepFn<TContext, TInput>): Measure<TContext, TInput> {\n this.#ctx.post = fn;\n return this;\n }\n}\n\nexport class TargetContext<TContext, TInput> {\n public teardown?: TeardownFn<TContext>;\n public measures: MeasureContext<TContext, TInput>[] = [];\n\n constructor(\n readonly title: string,\n readonly setup?: SetupFn<MaybePromise<TContext>>,\n ) {}\n}\n\nexport class Target<TContext, TInput> {\n #ctx: TargetContext<TContext, TInput>;\n\n constructor(ctx: TargetContext<TContext, TInput>) {\n this.#ctx = ctx;\n }\n teardown(fn: TeardownFn<TContext>): Target<TContext, TInput> {\n this.#ctx.teardown = fn;\n\n return this;\n }\n measure(title: string, run: StepFn<TContext, TInput>): Measure<TContext, TInput> {\n const measure = new MeasureContext(title, run);\n this.#ctx.measures.push(measure);\n\n return new Measure(measure);\n }\n}\n\nexport class FeedContext<TInput> {\n constructor(\n readonly title: string,\n readonly fn?: FeedFn<TInput>,\n ) {}\n}\n\nexport class Benchmark<TInput> {\n #targets: TargetContext<unknown, TInput>[] = [];\n #feeds: FeedContext<TInput>[] = [];\n #executed = false;\n\n static create(title: string): Benchmark<void>;\n static create<I>(title: string, fn: FeedFn<I>): Benchmark<I>;\n static create<I>(title: string, fn?: FeedFn<I> | undefined): Benchmark<I> {\n if (fn) {\n return new Benchmark(title, fn);\n } else {\n return new Benchmark(title);\n }\n }\n\n constructor(title: string);\n constructor(title: string, fn: FeedFn<TInput>);\n constructor(title: string, fn?: FeedFn<TInput> | undefined) {\n if (fn) {\n this.feed(title, fn);\n } else {\n this.feed(title);\n }\n }\n\n feed(title: string): Benchmark<TInput | void>;\n feed<I>(title: string, fn: FeedFn<I>): Benchmark<TInput | I>;\n feed<I>(title: string, fn?: FeedFn<I> | undefined): Benchmark<TInput | I> {\n const self = this as Benchmark<TInput | I>;\n self.#feeds.push(fn ? new FeedContext(title, fn) : new FeedContext(title));\n\n return self;\n }\n\n target<TContext>(title: string): Target<void, TInput>;\n target<TContext>(title: string, setup: SetupFn<Awaited<TContext>>): Target<TContext, TInput>;\n target<TContext>(title: string, setup?: SetupFn<Awaited<TContext>> | undefined): Target<TContext, TInput> {\n const target = new TargetContext<TContext, TInput>(title, setup);\n this.#targets.push(target as TargetContext<unknown, TInput>);\n\n return new Target<TContext, TInput>(target);\n }\n\n async execute<R extends readonly ReportType[] = typeof DEFAULT_REPORT_TYPES>({\n workers = DEFAULT_WORKERS,\n warmupCycles = 20,\n maxCycles = DEFAULT_CYCLES,\n minCycles = 50,\n absThreshold = 1_000,\n relThreshold = 0.02,\n gcObserver = true,\n reportTypes = DEFAULT_REPORT_TYPES as unknown as R,\n baseUrl,\n }: ExecutorOptions<R>): Promise<TargetReport<R>[]> {\n if (this.#executed) {\n throw new Error(\"Benchmark is executed and can't be reused\");\n }\n this.#executed = true;\n\n const resolvedBaseUrl = baseUrl ?? pathToFileURL(process.cwd()).href;\n if (!baseUrl) {\n console.warn(\"Overtake: baseUrl not provided; defaulting to process.cwd(). Pass the benchmark's import.meta.url so relative imports resolve correctly.\");\n }\n\n const executor = createExecutor<unknown, TInput, R>({\n baseUrl: resolvedBaseUrl,\n workers,\n warmupCycles,\n maxCycles,\n minCycles,\n absThreshold,\n relThreshold,\n gcObserver,\n reportTypes,\n });\n\n const reports: TargetReport<R>[] = [];\n for (const target of this.#targets) {\n const targetReport: TargetReport<R> = { target: target.title, measures: [] };\n for (const measure of target.measures) {\n const measureReport: MeasureReport<R> = { measure: measure.title, feeds: [] };\n for (const feed of this.#feeds) {\n const data = await feed.fn?.();\n executor\n .push<ExecutorReport<R>>({\n baseUrl: resolvedBaseUrl,\n setup: target.setup,\n teardown: target.teardown,\n pre: measure.pre,\n run: measure.run,\n post: measure.post,\n data,\n })\n .then((data) => {\n measureReport.feeds.push({\n feed: feed.title,\n data,\n });\n });\n }\n targetReport.measures.push(measureReport);\n }\n reports.push(targetReport);\n }\n await executor.drain();\n executor.kill();\n\n return reports;\n }\n}\n\nexport const printSimpleReports = <R extends ReportTypeList>(reports: TargetReport<R>[]) => {\n for (const report of reports) {\n for (const { measure, feeds } of report.measures) {\n console.group('\\n', report.target, measure);\n for (const { feed, data } of feeds) {\n const output = Object.entries(data)\n .map(([key, report]) => `${key}: ${report.toString()}`)\n .join('; ');\n console.log(feed, output);\n }\n console.groupEnd();\n }\n }\n};\n\nexport const printTableReports = <R extends ReportTypeList>(reports: TargetReport<R>[]) => {\n for (const report of reports) {\n for (const { measure, feeds } of report.measures) {\n console.log('\\n', report.target, measure);\n const table: Record<string, unknown> = {};\n for (const { feed, data } of feeds) {\n table[feed] = Object.fromEntries(Object.entries(data).map(([key, report]) => [key, report.toString()]));\n }\n console.table(table);\n }\n }\n};\n\nexport const printJSONReports = <R extends ReportTypeList>(reports: TargetReport<R>[], padding?: number) => {\n const output = {} as Record<string, Record<string, Record<string, string>>>;\n for (const report of reports) {\n for (const { measure, feeds } of report.measures) {\n const row = {} as Record<string, Record<string, string>>;\n for (const { feed, data } of feeds) {\n row[feed] = Object.fromEntries(Object.entries(data).map(([key, report]) => [key, report.toString()]));\n }\n output[`${report.target} ${measure}`] = row;\n }\n }\n console.log(JSON.stringify(output, null, padding));\n};\n"],"names":["AsyncFunction","Benchmark","DEFAULT_REPORT_TYPES","DEFAULT_WORKERS","FeedContext","Measure","MeasureContext","Target","TargetContext","printJSONReports","printSimpleReports","printTableReports","cpus","length","pre","post","title","run","ctx","fn","teardown","measures","setup","measure","push","create","feed","self","target","execute","workers","warmupCycles","maxCycles","DEFAULT_CYCLES","minCycles","absThreshold","relThreshold","gcObserver","reportTypes","baseUrl","Error","resolvedBaseUrl","pathToFileURL","process","cwd","href","console","warn","executor","createExecutor","reports","targetReport","measureReport","feeds","data","then","drain","kill","report","group","output","Object","entries","map","key","toString","join","log","groupEnd","table","fromEntries","padding","row","JSON","stringify"],"mappings":";;;;;;;;;;;QAWaA;eAAAA;;QAmFAC;eAAAA;;QAlEAC;eAAAA;;QAnBAC;eAAAA;;QA8EAC;eAAAA;;QA9CAC;eAAAA;;QAVAC;eAAAA;;QAqCAC;eAAAA;;QAVAC;eAAAA;;QA+KAC;eAAAA;;QA5BAC;eAAAA;;QAeAC;eAAAA;;;wBA5NQ;yBACS;6BACkC;0BAC8C;AAMvG,MAAMR,kBAAkBS,IAAAA,YAAI,IAAGC,MAAM;AAErC,MAAMb,gBAAgB,AAAC,CAAA,WAAa,CAAA,EAAG,WAAW;AAiBlD,MAAME,uBAAuB;IAAC;CAAM;AAGpC,MAAMI;;;IACJQ,IAA+B;IAC/BC,KAAgC;IAEvC,YACE,AAAOC,KAAa,EACpB,AAAOC,GAA6B,CACpC;aAFOD,QAAAA;aACAC,MAAAA;IACN;AACL;AAEO,MAAMZ;IACX,CAAA,GAAI,CAAmC;IAEvC,YAAYa,GAAqC,CAAE;QACjD,IAAI,CAAC,CAAA,GAAI,GAAGA;IACd;IAEAJ,IAAIK,EAA4B,EAA6B;QAC3D,IAAI,CAAC,CAAA,GAAI,CAACL,GAAG,GAAGK;QAChB,OAAO,IAAI;IACb;IACAJ,KAAKI,EAA4B,EAA6B;QAC5D,IAAI,CAAC,CAAA,GAAI,CAACJ,IAAI,GAAGI;QACjB,OAAO,IAAI;IACb;AACF;AAEO,MAAMX;;;IACJY,SAAgC;IAChCC,WAA+C,EAAE,CAAC;IAEzD,YACE,AAASL,KAAa,EACtB,AAASM,KAAuC,CAChD;aAFSN,QAAAA;aACAM,QAAAA;IACR;AACL;AAEO,MAAMf;IACX,CAAA,GAAI,CAAkC;IAEtC,YAAYW,GAAoC,CAAE;QAChD,IAAI,CAAC,CAAA,GAAI,GAAGA;IACd;IACAE,SAASD,EAAwB,EAA4B;QAC3D,IAAI,CAAC,CAAA,GAAI,CAACC,QAAQ,GAAGD;QAErB,OAAO,IAAI;IACb;IACAI,QAAQP,KAAa,EAAEC,GAA6B,EAA6B;QAC/E,MAAMM,UAAU,IAAIjB,eAAeU,OAAOC;QAC1C,IAAI,CAAC,CAAA,GAAI,CAACI,QAAQ,CAACG,IAAI,CAACD;QAExB,OAAO,IAAIlB,QAAQkB;IACrB;AACF;AAEO,MAAMnB;;;IACX,YACE,AAASY,KAAa,EACtB,AAASG,EAAmB,CAC5B;aAFSH,QAAAA;aACAG,KAAAA;IACR;AACL;AAEO,MAAMlB;IACX,CAAA,OAAQ,GAAqC,EAAE,CAAC;IAChD,CAAA,KAAM,GAA0B,EAAE,CAAC;IACnC,CAAA,QAAS,GAAG,MAAM;IAIlB,OAAOwB,OAAUT,KAAa,EAAEG,EAA0B,EAAgB;QACxE,IAAIA,IAAI;YACN,OAAO,IAAIlB,UAAUe,OAAOG;QAC9B,OAAO;YACL,OAAO,IAAIlB,UAAUe;QACvB;IACF;IAIA,YAAYA,KAAa,EAAEG,EAA+B,CAAE;QAC1D,IAAIA,IAAI;YACN,IAAI,CAACO,IAAI,CAACV,OAAOG;QACnB,OAAO;YACL,IAAI,CAACO,IAAI,CAACV;QACZ;IACF;IAIAU,KAAQV,KAAa,EAAEG,EAA0B,EAAyB;QACxE,MAAMQ,OAAO,IAAI;QACjBA,KAAK,CAAA,KAAM,CAACH,IAAI,CAACL,KAAK,IAAIf,YAAYY,OAAOG,MAAM,IAAIf,YAAYY;QAEnE,OAAOW;IACT;IAIAC,OAAiBZ,KAAa,EAAEM,KAA8C,EAA4B;QACxG,MAAMM,SAAS,IAAIpB,cAAgCQ,OAAOM;QAC1D,IAAI,CAAC,CAAA,OAAQ,CAACE,IAAI,CAACI;QAEnB,OAAO,IAAIrB,OAAyBqB;IACtC;IAEA,MAAMC,QAAuE,EAC3EC,UAAU3B,eAAe,EACzB4B,eAAe,EAAE,EACjBC,YAAYC,wBAAc,EAC1BC,YAAY,EAAE,EACdC,eAAe,KAAK,EACpBC,eAAe,IAAI,EACnBC,aAAa,IAAI,EACjBC,cAAcpC,oBAAoC,EAClDqC,OAAO,EACY,EAA8B;QACjD,IAAI,IAAI,CAAC,CAAA,QAAS,EAAE;YAClB,MAAM,IAAIC,MAAM;QAClB;QACA,IAAI,CAAC,CAAA,QAAS,GAAG;QAEjB,MAAMC,kBAAkBF,WAAWG,IAAAA,sBAAa,EAACC,QAAQC,GAAG,IAAIC,IAAI;QACpE,IAAI,CAACN,SAAS;YACZO,QAAQC,IAAI,CAAC;QACf;QAEA,MAAMC,WAAWC,IAAAA,2BAAc,EAAqB;YAClDV,SAASE;YACTX;YACAC;YACAC;YACAE;YACAC;YACAC;YACAC;YACAC;QACF;QAEA,MAAMY,UAA6B,EAAE;QACrC,KAAK,MAAMtB,UAAU,IAAI,CAAC,CAAA,OAAQ,CAAE;YAClC,MAAMuB,eAAgC;gBAAEvB,QAAQA,OAAOZ,KAAK;gBAAEK,UAAU,EAAE;YAAC;YAC3E,KAAK,MAAME,WAAWK,OAAOP,QAAQ,CAAE;gBACrC,MAAM+B,gBAAkC;oBAAE7B,SAASA,QAAQP,KAAK;oBAAEqC,OAAO,EAAE;gBAAC;gBAC5E,KAAK,MAAM3B,QAAQ,IAAI,CAAC,CAAA,KAAM,CAAE;oBAC9B,MAAM4B,OAAO,MAAM5B,KAAKP,EAAE;oBAC1B6B,SACGxB,IAAI,CAAoB;wBACvBe,SAASE;wBACTnB,OAAOM,OAAON,KAAK;wBACnBF,UAAUQ,OAAOR,QAAQ;wBACzBN,KAAKS,QAAQT,GAAG;wBAChBG,KAAKM,QAAQN,GAAG;wBAChBF,MAAMQ,QAAQR,IAAI;wBAClBuC;oBACF,GACCC,IAAI,CAAC,CAACD;wBACLF,cAAcC,KAAK,CAAC7B,IAAI,CAAC;4BACvBE,MAAMA,KAAKV,KAAK;4BAChBsC;wBACF;oBACF;gBACJ;gBACAH,aAAa9B,QAAQ,CAACG,IAAI,CAAC4B;YAC7B;YACAF,QAAQ1B,IAAI,CAAC2B;QACf;QACA,MAAMH,SAASQ,KAAK;QACpBR,SAASS,IAAI;QAEb,OAAOP;IACT;AACF;AAEO,MAAMxC,qBAAqB,CAA2BwC;IAC3D,KAAK,MAAMQ,UAAUR,QAAS;QAC5B,KAAK,MAAM,EAAE3B,OAAO,EAAE8B,KAAK,EAAE,IAAIK,OAAOrC,QAAQ,CAAE;YAChDyB,QAAQa,KAAK,CAAC,MAAMD,OAAO9B,MAAM,EAAEL;YACnC,KAAK,MAAM,EAAEG,IAAI,EAAE4B,IAAI,EAAE,IAAID,MAAO;gBAClC,MAAMO,SAASC,OAAOC,OAAO,CAACR,MAC3BS,GAAG,CAAC,CAAC,CAACC,KAAKN,OAAO,GAAK,GAAGM,IAAI,EAAE,EAAEN,OAAOO,QAAQ,IAAI,EACrDC,IAAI,CAAC;gBACRpB,QAAQqB,GAAG,CAACzC,MAAMkC;YACpB;YACAd,QAAQsB,QAAQ;QAClB;IACF;AACF;AAEO,MAAMzD,oBAAoB,CAA2BuC;IAC1D,KAAK,MAAMQ,UAAUR,QAAS;QAC5B,KAAK,MAAM,EAAE3B,OAAO,EAAE8B,KAAK,EAAE,IAAIK,OAAOrC,QAAQ,CAAE;YAChDyB,QAAQqB,GAAG,CAAC,MAAMT,OAAO9B,MAAM,EAAEL;YACjC,MAAM8C,QAAiC,CAAC;YACxC,KAAK,MAAM,EAAE3C,IAAI,EAAE4B,IAAI,EAAE,IAAID,MAAO;gBAClCgB,KAAK,CAAC3C,KAAK,GAAGmC,OAAOS,WAAW,CAACT,OAAOC,OAAO,CAACR,MAAMS,GAAG,CAAC,CAAC,CAACC,KAAKN,OAAO,GAAK;wBAACM;wBAAKN,OAAOO,QAAQ;qBAAG;YACvG;YACAnB,QAAQuB,KAAK,CAACA;QAChB;IACF;AACF;AAEO,MAAM5D,mBAAmB,CAA2ByC,SAA4BqB;IACrF,MAAMX,SAAS,CAAC;IAChB,KAAK,MAAMF,UAAUR,QAAS;QAC5B,KAAK,MAAM,EAAE3B,OAAO,EAAE8B,KAAK,EAAE,IAAIK,OAAOrC,QAAQ,CAAE;YAChD,MAAMmD,MAAM,CAAC;YACb,KAAK,MAAM,EAAE9C,IAAI,EAAE4B,IAAI,EAAE,IAAID,MAAO;gBAClCmB,GAAG,CAAC9C,KAAK,GAAGmC,OAAOS,WAAW,CAACT,OAAOC,OAAO,CAACR,MAAMS,GAAG,CAAC,CAAC,CAACC,KAAKN,OAAO,GAAK;wBAACM;wBAAKN,OAAOO,QAAQ;qBAAG;YACrG;YACAL,MAAM,CAAC,GAAGF,OAAO9B,MAAM,CAAC,CAAC,EAAEL,SAAS,CAAC,GAAGiD;QAC1C;IACF;IACA1B,QAAQqB,GAAG,CAACM,KAAKC,SAAS,CAACd,QAAQ,MAAMW;AAC3C"}
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["import { cpus } from 'node:os';\nimport { createExecutor, ExecutorOptions, ExecutorReport } from './executor.js';\nimport { MaybePromise, StepFn, SetupFn, TeardownFn, FeedFn, ReportType, ReportTypeList, DEFAULT_CYCLES } from './types.js';\n\ndeclare global {\n const benchmark: typeof Benchmark.create;\n}\n\nexport const DEFAULT_WORKERS = cpus().length;\n\nexport const AsyncFunction = (async () => {}).constructor;\nconst BENCHMARK_URL = Symbol.for('overtake.benchmarkUrl');\n\nexport interface TargetReport<R extends ReportTypeList> {\n target: string;\n measures: MeasureReport<R>[];\n}\n\nexport interface MeasureReport<R extends ReportTypeList> {\n measure: string;\n feeds: FeedReport<R>[];\n}\n\nexport interface FeedReport<R extends ReportTypeList> {\n feed: string;\n data: ExecutorReport<R>;\n}\n\nexport const DEFAULT_REPORT_TYPES = ['ops'] as const;\nexport type DefaultReportTypes = (typeof DEFAULT_REPORT_TYPES)[number];\n\nexport class MeasureContext<TContext, TInput> {\n public pre?: StepFn<TContext, TInput>;\n public post?: StepFn<TContext, TInput>;\n\n constructor(\n public title: string,\n public run: StepFn<TContext, TInput>,\n ) {}\n}\n\nexport class Measure<TContext, TInput> {\n #ctx: MeasureContext<TContext, TInput>;\n\n constructor(ctx: MeasureContext<TContext, TInput>) {\n this.#ctx = ctx;\n }\n\n pre(fn: StepFn<TContext, TInput>): Measure<TContext, TInput> {\n this.#ctx.pre = fn;\n return this;\n }\n post(fn: StepFn<TContext, TInput>): Measure<TContext, TInput> {\n this.#ctx.post = fn;\n return this;\n }\n}\n\nexport class TargetContext<TContext, TInput> {\n public teardown?: TeardownFn<TContext>;\n public measures: MeasureContext<TContext, TInput>[] = [];\n\n constructor(\n readonly title: string,\n readonly setup?: SetupFn<MaybePromise<TContext>>,\n ) {}\n}\n\nexport class Target<TContext, TInput> {\n #ctx: TargetContext<TContext, TInput>;\n\n constructor(ctx: TargetContext<TContext, TInput>) {\n this.#ctx = ctx;\n }\n teardown(fn: TeardownFn<TContext>): Target<TContext, TInput> {\n this.#ctx.teardown = fn;\n\n return this;\n }\n measure(title: string, run: StepFn<TContext, TInput>): Measure<TContext, TInput> {\n const measure = new MeasureContext(title, run);\n this.#ctx.measures.push(measure);\n\n return new Measure(measure);\n }\n}\n\nexport class FeedContext<TInput> {\n constructor(\n readonly title: string,\n readonly fn?: FeedFn<TInput>,\n ) {}\n}\n\nexport class Benchmark<TInput> {\n #targets: TargetContext<unknown, TInput>[] = [];\n #feeds: FeedContext<TInput>[] = [];\n #executed = false;\n\n static create(title: string): Benchmark<void>;\n static create<I>(title: string, fn: FeedFn<I>): Benchmark<I>;\n static create<I>(title: string, fn?: FeedFn<I> | undefined): Benchmark<I> {\n if (fn) {\n return new Benchmark(title, fn);\n } else {\n return new Benchmark(title);\n }\n }\n\n constructor(title: string);\n constructor(title: string, fn: FeedFn<TInput>);\n constructor(title: string, fn?: FeedFn<TInput> | undefined) {\n if (fn) {\n this.feed(title, fn);\n } else {\n this.feed(title);\n }\n }\n\n feed(title: string): Benchmark<TInput | void>;\n feed<I>(title: string, fn: FeedFn<I>): Benchmark<TInput | I>;\n feed<I>(title: string, fn?: FeedFn<I> | undefined): Benchmark<TInput | I> {\n const self = this as Benchmark<TInput | I>;\n self.#feeds.push(fn ? new FeedContext(title, fn) : new FeedContext(title));\n\n return self;\n }\n\n target<TContext>(title: string): Target<void, TInput>;\n target<TContext>(title: string, setup: SetupFn<Awaited<TContext>>): Target<TContext, TInput>;\n target<TContext>(title: string, setup?: SetupFn<Awaited<TContext>> | undefined): Target<TContext, TInput> {\n const target = new TargetContext<TContext, TInput>(title, setup);\n this.#targets.push(target as TargetContext<unknown, TInput>);\n\n return new Target<TContext, TInput>(target);\n }\n\n async execute<R extends readonly ReportType[] = typeof DEFAULT_REPORT_TYPES>(options: ExecutorOptions<R>): Promise<TargetReport<R>[]> {\n const {\n workers = DEFAULT_WORKERS,\n warmupCycles = 20,\n maxCycles = DEFAULT_CYCLES,\n minCycles = 50,\n absThreshold = 1_000,\n relThreshold = 0.02,\n gcObserver = true,\n reportTypes = DEFAULT_REPORT_TYPES as unknown as R,\n } = options;\n if (this.#executed) {\n throw new Error(\"Benchmark is executed and can't be reused\");\n }\n this.#executed = true;\n const benchmarkUrl = (options as unknown as Record<symbol, unknown>)[BENCHMARK_URL];\n\n const executor = createExecutor<unknown, TInput, R>({\n workers,\n warmupCycles,\n maxCycles,\n minCycles,\n absThreshold,\n relThreshold,\n gcObserver,\n reportTypes,\n [BENCHMARK_URL]: benchmarkUrl,\n } as Required<ExecutorOptions<R>>);\n\n const reports: TargetReport<R>[] = [];\n for (const target of this.#targets) {\n const targetReport: TargetReport<R> = { target: target.title, measures: [] };\n for (const measure of target.measures) {\n const measureReport: MeasureReport<R> = { measure: measure.title, feeds: [] };\n for (const feed of this.#feeds) {\n const data = await feed.fn?.();\n executor\n .push<ExecutorReport<R>>({\n setup: target.setup,\n teardown: target.teardown,\n pre: measure.pre,\n run: measure.run,\n post: measure.post,\n data,\n })\n .then((data) => {\n measureReport.feeds.push({\n feed: feed.title,\n data,\n });\n });\n }\n targetReport.measures.push(measureReport);\n }\n reports.push(targetReport);\n }\n await executor.drain();\n executor.kill();\n\n return reports;\n }\n}\n\nexport const printSimpleReports = <R extends ReportTypeList>(reports: TargetReport<R>[]) => {\n for (const report of reports) {\n for (const { measure, feeds } of report.measures) {\n console.group('\\n', report.target, measure);\n for (const { feed, data } of feeds) {\n const output = Object.entries(data)\n .map(([key, report]) => `${key}: ${report.toString()}`)\n .join('; ');\n console.log(feed, output);\n }\n console.groupEnd();\n }\n }\n};\n\nexport const printTableReports = <R extends ReportTypeList>(reports: TargetReport<R>[]) => {\n for (const report of reports) {\n for (const { measure, feeds } of report.measures) {\n console.log('\\n', report.target, measure);\n const table: Record<string, unknown> = {};\n for (const { feed, data } of feeds) {\n table[feed] = Object.fromEntries(Object.entries(data).map(([key, report]) => [key, report.toString()]));\n }\n console.table(table);\n }\n }\n};\n\nexport const printJSONReports = <R extends ReportTypeList>(reports: TargetReport<R>[], padding?: number) => {\n const output = {} as Record<string, Record<string, Record<string, string>>>;\n for (const report of reports) {\n for (const { measure, feeds } of report.measures) {\n const row = {} as Record<string, Record<string, string>>;\n for (const { feed, data } of feeds) {\n row[feed] = Object.fromEntries(Object.entries(data).map(([key, report]) => [key, report.toString()]));\n }\n output[`${report.target} ${measure}`] = row;\n }\n }\n console.log(JSON.stringify(output, null, padding));\n};\n"],"names":["AsyncFunction","Benchmark","DEFAULT_REPORT_TYPES","DEFAULT_WORKERS","FeedContext","Measure","MeasureContext","Target","TargetContext","printJSONReports","printSimpleReports","printTableReports","cpus","length","BENCHMARK_URL","Symbol","for","pre","post","title","run","ctx","fn","teardown","measures","setup","measure","push","create","feed","self","target","execute","options","workers","warmupCycles","maxCycles","DEFAULT_CYCLES","minCycles","absThreshold","relThreshold","gcObserver","reportTypes","Error","benchmarkUrl","executor","createExecutor","reports","targetReport","measureReport","feeds","data","then","drain","kill","report","console","group","output","Object","entries","map","key","toString","join","log","groupEnd","table","fromEntries","padding","row","JSON","stringify"],"mappings":"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"}
package/build/index.d.ts CHANGED
@@ -60,7 +60,7 @@ export declare class Benchmark<TInput> {
60
60
  feed<I>(title: string, fn: FeedFn<I>): Benchmark<TInput | I>;
61
61
  target<TContext>(title: string): Target<void, TInput>;
62
62
  target<TContext>(title: string, setup: SetupFn<Awaited<TContext>>): Target<TContext, TInput>;
63
- execute<R extends readonly ReportType[] = typeof DEFAULT_REPORT_TYPES>({ workers, warmupCycles, maxCycles, minCycles, absThreshold, relThreshold, gcObserver, reportTypes, baseUrl, }: ExecutorOptions<R>): Promise<TargetReport<R>[]>;
63
+ execute<R extends readonly ReportType[] = typeof DEFAULT_REPORT_TYPES>(options: ExecutorOptions<R>): Promise<TargetReport<R>[]>;
64
64
  }
65
65
  export declare const printSimpleReports: <R extends ReportTypeList>(reports: TargetReport<R>[]) => void;
66
66
  export declare const printTableReports: <R extends ReportTypeList>(reports: TargetReport<R>[]) => void;
package/build/index.js CHANGED
@@ -1,9 +1,9 @@
1
1
  import { cpus } from 'node:os';
2
- import { pathToFileURL } from 'node:url';
3
2
  import { createExecutor } from "./executor.js";
4
3
  import { DEFAULT_CYCLES } from "./types.js";
5
4
  export const DEFAULT_WORKERS = cpus().length;
6
5
  export const AsyncFunction = (async ()=>{}).constructor;
6
+ const BENCHMARK_URL = Symbol.for('overtake.benchmarkUrl');
7
7
  export const DEFAULT_REPORT_TYPES = [
8
8
  'ops'
9
9
  ];
@@ -92,17 +92,14 @@ export class Benchmark {
92
92
  this.#targets.push(target);
93
93
  return new Target(target);
94
94
  }
95
- async execute({ workers = DEFAULT_WORKERS, warmupCycles = 20, maxCycles = DEFAULT_CYCLES, minCycles = 50, absThreshold = 1_000, relThreshold = 0.02, gcObserver = true, reportTypes = DEFAULT_REPORT_TYPES, baseUrl }) {
95
+ async execute(options) {
96
+ const { workers = DEFAULT_WORKERS, warmupCycles = 20, maxCycles = DEFAULT_CYCLES, minCycles = 50, absThreshold = 1_000, relThreshold = 0.02, gcObserver = true, reportTypes = DEFAULT_REPORT_TYPES } = options;
96
97
  if (this.#executed) {
97
98
  throw new Error("Benchmark is executed and can't be reused");
98
99
  }
99
100
  this.#executed = true;
100
- const resolvedBaseUrl = baseUrl ?? pathToFileURL(process.cwd()).href;
101
- if (!baseUrl) {
102
- console.warn("Overtake: baseUrl not provided; defaulting to process.cwd(). Pass the benchmark's import.meta.url so relative imports resolve correctly.");
103
- }
101
+ const benchmarkUrl = options[BENCHMARK_URL];
104
102
  const executor = createExecutor({
105
- baseUrl: resolvedBaseUrl,
106
103
  workers,
107
104
  warmupCycles,
108
105
  maxCycles,
@@ -110,7 +107,8 @@ export class Benchmark {
110
107
  absThreshold,
111
108
  relThreshold,
112
109
  gcObserver,
113
- reportTypes
110
+ reportTypes,
111
+ [BENCHMARK_URL]: benchmarkUrl
114
112
  });
115
113
  const reports = [];
116
114
  for (const target of this.#targets){
@@ -126,7 +124,6 @@ export class Benchmark {
126
124
  for (const feed of this.#feeds){
127
125
  const data = await feed.fn?.();
128
126
  executor.push({
129
- baseUrl: resolvedBaseUrl,
130
127
  setup: target.setup,
131
128
  teardown: target.teardown,
132
129
  pre: measure.pre,
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"sourcesContent":["import { cpus } from 'node:os';\nimport { pathToFileURL } from 'node:url';\nimport { createExecutor, ExecutorOptions, ExecutorReport } from './executor.js';\nimport { MaybePromise, StepFn, SetupFn, TeardownFn, FeedFn, ReportType, ReportTypeList, DEFAULT_CYCLES } from './types.js';\n\ndeclare global {\n const benchmark: typeof Benchmark.create;\n}\n\nexport const DEFAULT_WORKERS = cpus().length;\n\nexport const AsyncFunction = (async () => {}).constructor;\n\nexport interface TargetReport<R extends ReportTypeList> {\n target: string;\n measures: MeasureReport<R>[];\n}\n\nexport interface MeasureReport<R extends ReportTypeList> {\n measure: string;\n feeds: FeedReport<R>[];\n}\n\nexport interface FeedReport<R extends ReportTypeList> {\n feed: string;\n data: ExecutorReport<R>;\n}\n\nexport const DEFAULT_REPORT_TYPES = ['ops'] as const;\nexport type DefaultReportTypes = (typeof DEFAULT_REPORT_TYPES)[number];\n\nexport class MeasureContext<TContext, TInput> {\n public pre?: StepFn<TContext, TInput>;\n public post?: StepFn<TContext, TInput>;\n\n constructor(\n public title: string,\n public run: StepFn<TContext, TInput>,\n ) {}\n}\n\nexport class Measure<TContext, TInput> {\n #ctx: MeasureContext<TContext, TInput>;\n\n constructor(ctx: MeasureContext<TContext, TInput>) {\n this.#ctx = ctx;\n }\n\n pre(fn: StepFn<TContext, TInput>): Measure<TContext, TInput> {\n this.#ctx.pre = fn;\n return this;\n }\n post(fn: StepFn<TContext, TInput>): Measure<TContext, TInput> {\n this.#ctx.post = fn;\n return this;\n }\n}\n\nexport class TargetContext<TContext, TInput> {\n public teardown?: TeardownFn<TContext>;\n public measures: MeasureContext<TContext, TInput>[] = [];\n\n constructor(\n readonly title: string,\n readonly setup?: SetupFn<MaybePromise<TContext>>,\n ) {}\n}\n\nexport class Target<TContext, TInput> {\n #ctx: TargetContext<TContext, TInput>;\n\n constructor(ctx: TargetContext<TContext, TInput>) {\n this.#ctx = ctx;\n }\n teardown(fn: TeardownFn<TContext>): Target<TContext, TInput> {\n this.#ctx.teardown = fn;\n\n return this;\n }\n measure(title: string, run: StepFn<TContext, TInput>): Measure<TContext, TInput> {\n const measure = new MeasureContext(title, run);\n this.#ctx.measures.push(measure);\n\n return new Measure(measure);\n }\n}\n\nexport class FeedContext<TInput> {\n constructor(\n readonly title: string,\n readonly fn?: FeedFn<TInput>,\n ) {}\n}\n\nexport class Benchmark<TInput> {\n #targets: TargetContext<unknown, TInput>[] = [];\n #feeds: FeedContext<TInput>[] = [];\n #executed = false;\n\n static create(title: string): Benchmark<void>;\n static create<I>(title: string, fn: FeedFn<I>): Benchmark<I>;\n static create<I>(title: string, fn?: FeedFn<I> | undefined): Benchmark<I> {\n if (fn) {\n return new Benchmark(title, fn);\n } else {\n return new Benchmark(title);\n }\n }\n\n constructor(title: string);\n constructor(title: string, fn: FeedFn<TInput>);\n constructor(title: string, fn?: FeedFn<TInput> | undefined) {\n if (fn) {\n this.feed(title, fn);\n } else {\n this.feed(title);\n }\n }\n\n feed(title: string): Benchmark<TInput | void>;\n feed<I>(title: string, fn: FeedFn<I>): Benchmark<TInput | I>;\n feed<I>(title: string, fn?: FeedFn<I> | undefined): Benchmark<TInput | I> {\n const self = this as Benchmark<TInput | I>;\n self.#feeds.push(fn ? new FeedContext(title, fn) : new FeedContext(title));\n\n return self;\n }\n\n target<TContext>(title: string): Target<void, TInput>;\n target<TContext>(title: string, setup: SetupFn<Awaited<TContext>>): Target<TContext, TInput>;\n target<TContext>(title: string, setup?: SetupFn<Awaited<TContext>> | undefined): Target<TContext, TInput> {\n const target = new TargetContext<TContext, TInput>(title, setup);\n this.#targets.push(target as TargetContext<unknown, TInput>);\n\n return new Target<TContext, TInput>(target);\n }\n\n async execute<R extends readonly ReportType[] = typeof DEFAULT_REPORT_TYPES>({\n workers = DEFAULT_WORKERS,\n warmupCycles = 20,\n maxCycles = DEFAULT_CYCLES,\n minCycles = 50,\n absThreshold = 1_000,\n relThreshold = 0.02,\n gcObserver = true,\n reportTypes = DEFAULT_REPORT_TYPES as unknown as R,\n baseUrl,\n }: ExecutorOptions<R>): Promise<TargetReport<R>[]> {\n if (this.#executed) {\n throw new Error(\"Benchmark is executed and can't be reused\");\n }\n this.#executed = true;\n\n const resolvedBaseUrl = baseUrl ?? pathToFileURL(process.cwd()).href;\n if (!baseUrl) {\n console.warn(\"Overtake: baseUrl not provided; defaulting to process.cwd(). Pass the benchmark's import.meta.url so relative imports resolve correctly.\");\n }\n\n const executor = createExecutor<unknown, TInput, R>({\n baseUrl: resolvedBaseUrl,\n workers,\n warmupCycles,\n maxCycles,\n minCycles,\n absThreshold,\n relThreshold,\n gcObserver,\n reportTypes,\n });\n\n const reports: TargetReport<R>[] = [];\n for (const target of this.#targets) {\n const targetReport: TargetReport<R> = { target: target.title, measures: [] };\n for (const measure of target.measures) {\n const measureReport: MeasureReport<R> = { measure: measure.title, feeds: [] };\n for (const feed of this.#feeds) {\n const data = await feed.fn?.();\n executor\n .push<ExecutorReport<R>>({\n baseUrl: resolvedBaseUrl,\n setup: target.setup,\n teardown: target.teardown,\n pre: measure.pre,\n run: measure.run,\n post: measure.post,\n data,\n })\n .then((data) => {\n measureReport.feeds.push({\n feed: feed.title,\n data,\n });\n });\n }\n targetReport.measures.push(measureReport);\n }\n reports.push(targetReport);\n }\n await executor.drain();\n executor.kill();\n\n return reports;\n }\n}\n\nexport const printSimpleReports = <R extends ReportTypeList>(reports: TargetReport<R>[]) => {\n for (const report of reports) {\n for (const { measure, feeds } of report.measures) {\n console.group('\\n', report.target, measure);\n for (const { feed, data } of feeds) {\n const output = Object.entries(data)\n .map(([key, report]) => `${key}: ${report.toString()}`)\n .join('; ');\n console.log(feed, output);\n }\n console.groupEnd();\n }\n }\n};\n\nexport const printTableReports = <R extends ReportTypeList>(reports: TargetReport<R>[]) => {\n for (const report of reports) {\n for (const { measure, feeds } of report.measures) {\n console.log('\\n', report.target, measure);\n const table: Record<string, unknown> = {};\n for (const { feed, data } of feeds) {\n table[feed] = Object.fromEntries(Object.entries(data).map(([key, report]) => [key, report.toString()]));\n }\n console.table(table);\n }\n }\n};\n\nexport const printJSONReports = <R extends ReportTypeList>(reports: TargetReport<R>[], padding?: number) => {\n const output = {} as Record<string, Record<string, Record<string, string>>>;\n for (const report of reports) {\n for (const { measure, feeds } of report.measures) {\n const row = {} as Record<string, Record<string, string>>;\n for (const { feed, data } of feeds) {\n row[feed] = Object.fromEntries(Object.entries(data).map(([key, report]) => [key, report.toString()]));\n }\n output[`${report.target} ${measure}`] = row;\n }\n }\n console.log(JSON.stringify(output, null, padding));\n};\n"],"names":["cpus","pathToFileURL","createExecutor","DEFAULT_CYCLES","DEFAULT_WORKERS","length","AsyncFunction","DEFAULT_REPORT_TYPES","MeasureContext","pre","post","title","run","Measure","ctx","fn","TargetContext","teardown","measures","setup","Target","measure","push","FeedContext","Benchmark","create","feed","self","target","execute","workers","warmupCycles","maxCycles","minCycles","absThreshold","relThreshold","gcObserver","reportTypes","baseUrl","Error","resolvedBaseUrl","process","cwd","href","console","warn","executor","reports","targetReport","measureReport","feeds","data","then","drain","kill","printSimpleReports","report","group","output","Object","entries","map","key","toString","join","log","groupEnd","printTableReports","table","fromEntries","printJSONReports","padding","row","JSON","stringify"],"mappings":"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"}
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["import { cpus } from 'node:os';\nimport { createExecutor, ExecutorOptions, ExecutorReport } from './executor.js';\nimport { MaybePromise, StepFn, SetupFn, TeardownFn, FeedFn, ReportType, ReportTypeList, DEFAULT_CYCLES } from './types.js';\n\ndeclare global {\n const benchmark: typeof Benchmark.create;\n}\n\nexport const DEFAULT_WORKERS = cpus().length;\n\nexport const AsyncFunction = (async () => {}).constructor;\nconst BENCHMARK_URL = Symbol.for('overtake.benchmarkUrl');\n\nexport interface TargetReport<R extends ReportTypeList> {\n target: string;\n measures: MeasureReport<R>[];\n}\n\nexport interface MeasureReport<R extends ReportTypeList> {\n measure: string;\n feeds: FeedReport<R>[];\n}\n\nexport interface FeedReport<R extends ReportTypeList> {\n feed: string;\n data: ExecutorReport<R>;\n}\n\nexport const DEFAULT_REPORT_TYPES = ['ops'] as const;\nexport type DefaultReportTypes = (typeof DEFAULT_REPORT_TYPES)[number];\n\nexport class MeasureContext<TContext, TInput> {\n public pre?: StepFn<TContext, TInput>;\n public post?: StepFn<TContext, TInput>;\n\n constructor(\n public title: string,\n public run: StepFn<TContext, TInput>,\n ) {}\n}\n\nexport class Measure<TContext, TInput> {\n #ctx: MeasureContext<TContext, TInput>;\n\n constructor(ctx: MeasureContext<TContext, TInput>) {\n this.#ctx = ctx;\n }\n\n pre(fn: StepFn<TContext, TInput>): Measure<TContext, TInput> {\n this.#ctx.pre = fn;\n return this;\n }\n post(fn: StepFn<TContext, TInput>): Measure<TContext, TInput> {\n this.#ctx.post = fn;\n return this;\n }\n}\n\nexport class TargetContext<TContext, TInput> {\n public teardown?: TeardownFn<TContext>;\n public measures: MeasureContext<TContext, TInput>[] = [];\n\n constructor(\n readonly title: string,\n readonly setup?: SetupFn<MaybePromise<TContext>>,\n ) {}\n}\n\nexport class Target<TContext, TInput> {\n #ctx: TargetContext<TContext, TInput>;\n\n constructor(ctx: TargetContext<TContext, TInput>) {\n this.#ctx = ctx;\n }\n teardown(fn: TeardownFn<TContext>): Target<TContext, TInput> {\n this.#ctx.teardown = fn;\n\n return this;\n }\n measure(title: string, run: StepFn<TContext, TInput>): Measure<TContext, TInput> {\n const measure = new MeasureContext(title, run);\n this.#ctx.measures.push(measure);\n\n return new Measure(measure);\n }\n}\n\nexport class FeedContext<TInput> {\n constructor(\n readonly title: string,\n readonly fn?: FeedFn<TInput>,\n ) {}\n}\n\nexport class Benchmark<TInput> {\n #targets: TargetContext<unknown, TInput>[] = [];\n #feeds: FeedContext<TInput>[] = [];\n #executed = false;\n\n static create(title: string): Benchmark<void>;\n static create<I>(title: string, fn: FeedFn<I>): Benchmark<I>;\n static create<I>(title: string, fn?: FeedFn<I> | undefined): Benchmark<I> {\n if (fn) {\n return new Benchmark(title, fn);\n } else {\n return new Benchmark(title);\n }\n }\n\n constructor(title: string);\n constructor(title: string, fn: FeedFn<TInput>);\n constructor(title: string, fn?: FeedFn<TInput> | undefined) {\n if (fn) {\n this.feed(title, fn);\n } else {\n this.feed(title);\n }\n }\n\n feed(title: string): Benchmark<TInput | void>;\n feed<I>(title: string, fn: FeedFn<I>): Benchmark<TInput | I>;\n feed<I>(title: string, fn?: FeedFn<I> | undefined): Benchmark<TInput | I> {\n const self = this as Benchmark<TInput | I>;\n self.#feeds.push(fn ? new FeedContext(title, fn) : new FeedContext(title));\n\n return self;\n }\n\n target<TContext>(title: string): Target<void, TInput>;\n target<TContext>(title: string, setup: SetupFn<Awaited<TContext>>): Target<TContext, TInput>;\n target<TContext>(title: string, setup?: SetupFn<Awaited<TContext>> | undefined): Target<TContext, TInput> {\n const target = new TargetContext<TContext, TInput>(title, setup);\n this.#targets.push(target as TargetContext<unknown, TInput>);\n\n return new Target<TContext, TInput>(target);\n }\n\n async execute<R extends readonly ReportType[] = typeof DEFAULT_REPORT_TYPES>(options: ExecutorOptions<R>): Promise<TargetReport<R>[]> {\n const {\n workers = DEFAULT_WORKERS,\n warmupCycles = 20,\n maxCycles = DEFAULT_CYCLES,\n minCycles = 50,\n absThreshold = 1_000,\n relThreshold = 0.02,\n gcObserver = true,\n reportTypes = DEFAULT_REPORT_TYPES as unknown as R,\n } = options;\n if (this.#executed) {\n throw new Error(\"Benchmark is executed and can't be reused\");\n }\n this.#executed = true;\n const benchmarkUrl = (options as unknown as Record<symbol, unknown>)[BENCHMARK_URL];\n\n const executor = createExecutor<unknown, TInput, R>({\n workers,\n warmupCycles,\n maxCycles,\n minCycles,\n absThreshold,\n relThreshold,\n gcObserver,\n reportTypes,\n [BENCHMARK_URL]: benchmarkUrl,\n } as Required<ExecutorOptions<R>>);\n\n const reports: TargetReport<R>[] = [];\n for (const target of this.#targets) {\n const targetReport: TargetReport<R> = { target: target.title, measures: [] };\n for (const measure of target.measures) {\n const measureReport: MeasureReport<R> = { measure: measure.title, feeds: [] };\n for (const feed of this.#feeds) {\n const data = await feed.fn?.();\n executor\n .push<ExecutorReport<R>>({\n setup: target.setup,\n teardown: target.teardown,\n pre: measure.pre,\n run: measure.run,\n post: measure.post,\n data,\n })\n .then((data) => {\n measureReport.feeds.push({\n feed: feed.title,\n data,\n });\n });\n }\n targetReport.measures.push(measureReport);\n }\n reports.push(targetReport);\n }\n await executor.drain();\n executor.kill();\n\n return reports;\n }\n}\n\nexport const printSimpleReports = <R extends ReportTypeList>(reports: TargetReport<R>[]) => {\n for (const report of reports) {\n for (const { measure, feeds } of report.measures) {\n console.group('\\n', report.target, measure);\n for (const { feed, data } of feeds) {\n const output = Object.entries(data)\n .map(([key, report]) => `${key}: ${report.toString()}`)\n .join('; ');\n console.log(feed, output);\n }\n console.groupEnd();\n }\n }\n};\n\nexport const printTableReports = <R extends ReportTypeList>(reports: TargetReport<R>[]) => {\n for (const report of reports) {\n for (const { measure, feeds } of report.measures) {\n console.log('\\n', report.target, measure);\n const table: Record<string, unknown> = {};\n for (const { feed, data } of feeds) {\n table[feed] = Object.fromEntries(Object.entries(data).map(([key, report]) => [key, report.toString()]));\n }\n console.table(table);\n }\n }\n};\n\nexport const printJSONReports = <R extends ReportTypeList>(reports: TargetReport<R>[], padding?: number) => {\n const output = {} as Record<string, Record<string, Record<string, string>>>;\n for (const report of reports) {\n for (const { measure, feeds } of report.measures) {\n const row = {} as Record<string, Record<string, string>>;\n for (const { feed, data } of feeds) {\n row[feed] = Object.fromEntries(Object.entries(data).map(([key, report]) => [key, report.toString()]));\n }\n output[`${report.target} ${measure}`] = row;\n }\n }\n console.log(JSON.stringify(output, null, padding));\n};\n"],"names":["cpus","createExecutor","DEFAULT_CYCLES","DEFAULT_WORKERS","length","AsyncFunction","BENCHMARK_URL","Symbol","for","DEFAULT_REPORT_TYPES","MeasureContext","pre","post","title","run","Measure","ctx","fn","TargetContext","teardown","measures","setup","Target","measure","push","FeedContext","Benchmark","create","feed","self","target","execute","options","workers","warmupCycles","maxCycles","minCycles","absThreshold","relThreshold","gcObserver","reportTypes","Error","benchmarkUrl","executor","reports","targetReport","measureReport","feeds","data","then","drain","kill","printSimpleReports","report","console","group","output","Object","entries","map","key","toString","join","log","groupEnd","printTableReports","table","fromEntries","printJSONReports","padding","row","JSON","stringify"],"mappings":"AAAA,SAASA,IAAI,QAAQ,UAAU;AAC/B,SAASC,cAAc,QAAyC,gBAAgB;AAChF,SAAwFC,cAAc,QAAQ,aAAa;AAM3H,OAAO,MAAMC,kBAAkBH,OAAOI,MAAM,CAAC;AAE7C,OAAO,MAAMC,gBAAgB,AAAC,CAAA,WAAa,CAAA,EAAG,WAAW,CAAC;AAC1D,MAAMC,gBAAgBC,OAAOC,GAAG,CAAC;AAiBjC,OAAO,MAAMC,uBAAuB;IAAC;CAAM,CAAU;AAGrD,OAAO,MAAMC;;;IACJC,IAA+B;IAC/BC,KAAgC;IAEvC,YACE,AAAOC,KAAa,EACpB,AAAOC,GAA6B,CACpC;aAFOD,QAAAA;aACAC,MAAAA;IACN;AACL;AAEA,OAAO,MAAMC;IACX,CAAA,GAAI,CAAmC;IAEvC,YAAYC,GAAqC,CAAE;QACjD,IAAI,CAAC,CAAA,GAAI,GAAGA;IACd;IAEAL,IAAIM,EAA4B,EAA6B;QAC3D,IAAI,CAAC,CAAA,GAAI,CAACN,GAAG,GAAGM;QAChB,OAAO,IAAI;IACb;IACAL,KAAKK,EAA4B,EAA6B;QAC5D,IAAI,CAAC,CAAA,GAAI,CAACL,IAAI,GAAGK;QACjB,OAAO,IAAI;IACb;AACF;AAEA,OAAO,MAAMC;;;IACJC,SAAgC;IAChCC,WAA+C,EAAE,CAAC;IAEzD,YACE,AAASP,KAAa,EACtB,AAASQ,KAAuC,CAChD;aAFSR,QAAAA;aACAQ,QAAAA;IACR;AACL;AAEA,OAAO,MAAMC;IACX,CAAA,GAAI,CAAkC;IAEtC,YAAYN,GAAoC,CAAE;QAChD,IAAI,CAAC,CAAA,GAAI,GAAGA;IACd;IACAG,SAASF,EAAwB,EAA4B;QAC3D,IAAI,CAAC,CAAA,GAAI,CAACE,QAAQ,GAAGF;QAErB,OAAO,IAAI;IACb;IACAM,QAAQV,KAAa,EAAEC,GAA6B,EAA6B;QAC/E,MAAMS,UAAU,IAAIb,eAAeG,OAAOC;QAC1C,IAAI,CAAC,CAAA,GAAI,CAACM,QAAQ,CAACI,IAAI,CAACD;QAExB,OAAO,IAAIR,QAAQQ;IACrB;AACF;AAEA,OAAO,MAAME;;;IACX,YACE,AAASZ,KAAa,EACtB,AAASI,EAAmB,CAC5B;aAFSJ,QAAAA;aACAI,KAAAA;IACR;AACL;AAEA,OAAO,MAAMS;IACX,CAAA,OAAQ,GAAqC,EAAE,CAAC;IAChD,CAAA,KAAM,GAA0B,EAAE,CAAC;IACnC,CAAA,QAAS,GAAG,MAAM;IAIlB,OAAOC,OAAUd,KAAa,EAAEI,EAA0B,EAAgB;QACxE,IAAIA,IAAI;YACN,OAAO,IAAIS,UAAUb,OAAOI;QAC9B,OAAO;YACL,OAAO,IAAIS,UAAUb;QACvB;IACF;IAIA,YAAYA,KAAa,EAAEI,EAA+B,CAAE;QAC1D,IAAIA,IAAI;YACN,IAAI,CAACW,IAAI,CAACf,OAAOI;QACnB,OAAO;YACL,IAAI,CAACW,IAAI,CAACf;QACZ;IACF;IAIAe,KAAQf,KAAa,EAAEI,EAA0B,EAAyB;QACxE,MAAMY,OAAO,IAAI;QACjBA,KAAK,CAAA,KAAM,CAACL,IAAI,CAACP,KAAK,IAAIQ,YAAYZ,OAAOI,MAAM,IAAIQ,YAAYZ;QAEnE,OAAOgB;IACT;IAIAC,OAAiBjB,KAAa,EAAEQ,KAA8C,EAA4B;QACxG,MAAMS,SAAS,IAAIZ,cAAgCL,OAAOQ;QAC1D,IAAI,CAAC,CAAA,OAAQ,CAACG,IAAI,CAACM;QAEnB,OAAO,IAAIR,OAAyBQ;IACtC;IAEA,MAAMC,QAAuEC,OAA2B,EAA8B;QACpI,MAAM,EACJC,UAAU9B,eAAe,EACzB+B,eAAe,EAAE,EACjBC,YAAYjC,cAAc,EAC1BkC,YAAY,EAAE,EACdC,eAAe,KAAK,EACpBC,eAAe,IAAI,EACnBC,aAAa,IAAI,EACjBC,cAAc/B,oBAAoC,EACnD,GAAGuB;QACJ,IAAI,IAAI,CAAC,CAAA,QAAS,EAAE;YAClB,MAAM,IAAIS,MAAM;QAClB;QACA,IAAI,CAAC,CAAA,QAAS,GAAG;QACjB,MAAMC,eAAe,AAACV,OAA8C,CAAC1B,cAAc;QAEnF,MAAMqC,WAAW1C,eAAmC;YAClDgC;YACAC;YACAC;YACAC;YACAC;YACAC;YACAC;YACAC;YACA,CAAClC,cAAc,EAAEoC;QACnB;QAEA,MAAME,UAA6B,EAAE;QACrC,KAAK,MAAMd,UAAU,IAAI,CAAC,CAAA,OAAQ,CAAE;YAClC,MAAMe,eAAgC;gBAAEf,QAAQA,OAAOjB,KAAK;gBAAEO,UAAU,EAAE;YAAC;YAC3E,KAAK,MAAMG,WAAWO,OAAOV,QAAQ,CAAE;gBACrC,MAAM0B,gBAAkC;oBAAEvB,SAASA,QAAQV,KAAK;oBAAEkC,OAAO,EAAE;gBAAC;gBAC5E,KAAK,MAAMnB,QAAQ,IAAI,CAAC,CAAA,KAAM,CAAE;oBAC9B,MAAMoB,OAAO,MAAMpB,KAAKX,EAAE;oBAC1B0B,SACGnB,IAAI,CAAoB;wBACvBH,OAAOS,OAAOT,KAAK;wBACnBF,UAAUW,OAAOX,QAAQ;wBACzBR,KAAKY,QAAQZ,GAAG;wBAChBG,KAAKS,QAAQT,GAAG;wBAChBF,MAAMW,QAAQX,IAAI;wBAClBoC;oBACF,GACCC,IAAI,CAAC,CAACD;wBACLF,cAAcC,KAAK,CAACvB,IAAI,CAAC;4BACvBI,MAAMA,KAAKf,KAAK;4BAChBmC;wBACF;oBACF;gBACJ;gBACAH,aAAazB,QAAQ,CAACI,IAAI,CAACsB;YAC7B;YACAF,QAAQpB,IAAI,CAACqB;QACf;QACA,MAAMF,SAASO,KAAK;QACpBP,SAASQ,IAAI;QAEb,OAAOP;IACT;AACF;AAEA,OAAO,MAAMQ,qBAAqB,CAA2BR;IAC3D,KAAK,MAAMS,UAAUT,QAAS;QAC5B,KAAK,MAAM,EAAErB,OAAO,EAAEwB,KAAK,EAAE,IAAIM,OAAOjC,QAAQ,CAAE;YAChDkC,QAAQC,KAAK,CAAC,MAAMF,OAAOvB,MAAM,EAAEP;YACnC,KAAK,MAAM,EAAEK,IAAI,EAAEoB,IAAI,EAAE,IAAID,MAAO;gBAClC,MAAMS,SAASC,OAAOC,OAAO,CAACV,MAC3BW,GAAG,CAAC,CAAC,CAACC,KAAKP,OAAO,GAAK,GAAGO,IAAI,EAAE,EAAEP,OAAOQ,QAAQ,IAAI,EACrDC,IAAI,CAAC;gBACRR,QAAQS,GAAG,CAACnC,MAAM4B;YACpB;YACAF,QAAQU,QAAQ;QAClB;IACF;AACF,EAAE;AAEF,OAAO,MAAMC,oBAAoB,CAA2BrB;IAC1D,KAAK,MAAMS,UAAUT,QAAS;QAC5B,KAAK,MAAM,EAAErB,OAAO,EAAEwB,KAAK,EAAE,IAAIM,OAAOjC,QAAQ,CAAE;YAChDkC,QAAQS,GAAG,CAAC,MAAMV,OAAOvB,MAAM,EAAEP;YACjC,MAAM2C,QAAiC,CAAC;YACxC,KAAK,MAAM,EAAEtC,IAAI,EAAEoB,IAAI,EAAE,IAAID,MAAO;gBAClCmB,KAAK,CAACtC,KAAK,GAAG6B,OAAOU,WAAW,CAACV,OAAOC,OAAO,CAACV,MAAMW,GAAG,CAAC,CAAC,CAACC,KAAKP,OAAO,GAAK;wBAACO;wBAAKP,OAAOQ,QAAQ;qBAAG;YACvG;YACAP,QAAQY,KAAK,CAACA;QAChB;IACF;AACF,EAAE;AAEF,OAAO,MAAME,mBAAmB,CAA2BxB,SAA4ByB;IACrF,MAAMb,SAAS,CAAC;IAChB,KAAK,MAAMH,UAAUT,QAAS;QAC5B,KAAK,MAAM,EAAErB,OAAO,EAAEwB,KAAK,EAAE,IAAIM,OAAOjC,QAAQ,CAAE;YAChD,MAAMkD,MAAM,CAAC;YACb,KAAK,MAAM,EAAE1C,IAAI,EAAEoB,IAAI,EAAE,IAAID,MAAO;gBAClCuB,GAAG,CAAC1C,KAAK,GAAG6B,OAAOU,WAAW,CAACV,OAAOC,OAAO,CAACV,MAAMW,GAAG,CAAC,CAAC,CAACC,KAAKP,OAAO,GAAK;wBAACO;wBAAKP,OAAOQ,QAAQ;qBAAG;YACrG;YACAL,MAAM,CAAC,GAAGH,OAAOvB,MAAM,CAAC,CAAC,EAAEP,SAAS,CAAC,GAAG+C;QAC1C;IACF;IACAhB,QAAQS,GAAG,CAACQ,KAAKC,SAAS,CAAChB,QAAQ,MAAMa;AAC3C,EAAE"}
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/types.ts"],"sourcesContent":["export type MaybePromise<T> = Promise<T> | PromiseLike<T> | T;\n\nexport interface SetupFn<TContext> {\n (): MaybePromise<TContext>;\n}\n\nexport interface TeardownFn<TContext> {\n (ctx: TContext): MaybePromise<void>;\n}\n\nexport interface StepFn<TContext, TInput> {\n (ctx: TContext, input: TInput): MaybePromise<void>;\n}\n\nexport interface FeedFn<TInput> {\n (): MaybePromise<TInput>;\n}\n\ntype _Sequence<To extends number, R extends unknown[]> = R['length'] extends To ? R[number] : _Sequence<To, [R['length'], ...R]>;\nexport type Sequence<To extends number> = number extends To ? number : _Sequence<To, []>;\nexport type Between<From extends number, To extends number> = Exclude<Sequence<To>, Sequence<From>>;\n\nexport type ReportType = 'ops' | 'min' | 'max' | 'mean' | 'median' | 'mode' | `p${Between<1, 100>}`;\nexport type ReportTypeList = readonly ReportType[];\nexport const REPORT_TYPES: ReportTypeList = Array.from({ length: 99 }, (_, idx) => `p${idx + 1}` as ReportType).concat(['ops', 'mean', 'min', 'max', 'median', 'mode']);\n\nexport interface ReportOptions<R extends ReportTypeList> {\n reportTypes: R;\n}\n\nexport interface BenchmarkOptions {\n warmupCycles?: number;\n minCycles?: number;\n absThreshold?: number; // ns\n relThreshold?: number; // %\n gcObserver?: boolean;\n baseUrl?: string;\n}\n\nexport interface RunOptions<TContext, TInput> {\n baseUrl?: string;\n setup?: SetupFn<TContext>;\n teardown?: TeardownFn<TContext>;\n pre?: StepFn<TContext, TInput>;\n run: StepFn<TContext, TInput>;\n post?: StepFn<TContext, TInput>;\n data?: TInput;\n}\n\nexport interface WorkerOptions extends Required<BenchmarkOptions> {\n baseUrl: string;\n setupCode?: string;\n teardownCode?: string;\n preCode?: string;\n runCode: string;\n postCode?: string;\n data?: unknown;\n\n durationsSAB: SharedArrayBuffer;\n controlSAB: SharedArrayBuffer;\n}\n\nexport interface Options<TContext, TInput> extends RunOptions<TContext, TInput>, BenchmarkOptions {\n durationsSAB: SharedArrayBuffer;\n controlSAB: SharedArrayBuffer;\n}\n\nexport enum Control {\n INDEX,\n PROGRESS,\n COMPLETE,\n}\n\nexport const CONTROL_SLOTS = Object.values(Control).length / 2;\nexport const DEFAULT_CYCLES = 1_000;\nexport const Z95 = 1.96;\n"],"names":["CONTROL_SLOTS","Control","DEFAULT_CYCLES","REPORT_TYPES","Z95","Array","from","length","_","idx","concat","Object","values"],"mappings":";;;;;;;;;;;QAyEaA;eAAAA;;QANDC;eAAAA;;QAOCC;eAAAA;;QAlDAC;eAAAA;;QAmDAC;eAAAA;;;AAnDN,MAAMD,eAA+BE,MAAMC,IAAI,CAAC;IAAEC,QAAQ;AAAG,GAAG,CAACC,GAAGC,MAAQ,CAAC,CAAC,EAAEA,MAAM,GAAG,EAAgBC,MAAM,CAAC;IAAC;IAAO;IAAQ;IAAO;IAAO;IAAU;CAAO;AA2C/J,IAAA,AAAKT,iCAAAA;;;;WAAAA;;AAML,MAAMD,gBAAgBW,OAAOC,MAAM,CAACX,SAASM,MAAM,GAAG;AACtD,MAAML,iBAAiB;AACvB,MAAME,MAAM"}
1
+ {"version":3,"sources":["../src/types.ts"],"sourcesContent":["export type MaybePromise<T> = Promise<T> | PromiseLike<T> | T;\n\nexport interface SetupFn<TContext> {\n (): MaybePromise<TContext>;\n}\n\nexport interface TeardownFn<TContext> {\n (ctx: TContext): MaybePromise<void>;\n}\n\nexport interface StepFn<TContext, TInput> {\n (ctx: TContext, input: TInput): MaybePromise<void>;\n}\n\nexport interface FeedFn<TInput> {\n (): MaybePromise<TInput>;\n}\n\ntype _Sequence<To extends number, R extends unknown[]> = R['length'] extends To ? R[number] : _Sequence<To, [R['length'], ...R]>;\nexport type Sequence<To extends number> = number extends To ? number : _Sequence<To, []>;\nexport type Between<From extends number, To extends number> = Exclude<Sequence<To>, Sequence<From>>;\n\nexport type ReportType = 'ops' | 'min' | 'max' | 'mean' | 'median' | 'mode' | `p${Between<1, 100>}`;\nexport type ReportTypeList = readonly ReportType[];\nexport const REPORT_TYPES: ReportTypeList = Array.from({ length: 99 }, (_, idx) => `p${idx + 1}` as ReportType).concat(['ops', 'mean', 'min', 'max', 'median', 'mode']);\n\nexport interface ReportOptions<R extends ReportTypeList> {\n reportTypes: R;\n}\n\nexport interface BenchmarkOptions {\n warmupCycles?: number;\n minCycles?: number;\n absThreshold?: number; // ns\n relThreshold?: number; // %\n gcObserver?: boolean;\n}\n\nexport interface RunOptions<TContext, TInput> {\n setup?: SetupFn<TContext>;\n teardown?: TeardownFn<TContext>;\n pre?: StepFn<TContext, TInput>;\n run: StepFn<TContext, TInput>;\n post?: StepFn<TContext, TInput>;\n data?: TInput;\n}\n\nexport interface WorkerOptions extends Required<BenchmarkOptions> {\n benchmarkUrl?: string;\n setupCode?: string;\n teardownCode?: string;\n preCode?: string;\n runCode: string;\n postCode?: string;\n data?: unknown;\n\n durationsSAB: SharedArrayBuffer;\n controlSAB: SharedArrayBuffer;\n}\n\nexport interface Options<TContext, TInput> extends RunOptions<TContext, TInput>, BenchmarkOptions {\n durationsSAB: SharedArrayBuffer;\n controlSAB: SharedArrayBuffer;\n}\n\nexport enum Control {\n INDEX,\n PROGRESS,\n COMPLETE,\n}\n\nexport const CONTROL_SLOTS = Object.values(Control).length / 2;\nexport const DEFAULT_CYCLES = 1_000;\nexport const Z95 = 1.96;\n"],"names":["CONTROL_SLOTS","Control","DEFAULT_CYCLES","REPORT_TYPES","Z95","Array","from","length","_","idx","concat","Object","values"],"mappings":";;;;;;;;;;;QAuEaA;eAAAA;;QANDC;eAAAA;;QAOCC;eAAAA;;QAhDAC;eAAAA;;QAiDAC;eAAAA;;;AAjDN,MAAMD,eAA+BE,MAAMC,IAAI,CAAC;IAAEC,QAAQ;AAAG,GAAG,CAACC,GAAGC,MAAQ,CAAC,CAAC,EAAEA,MAAM,GAAG,EAAgBC,MAAM,CAAC;IAAC;IAAO;IAAQ;IAAO;IAAO;IAAU;CAAO;AAyC/J,IAAA,AAAKT,iCAAAA;;;;WAAAA;;AAML,MAAMD,gBAAgBW,OAAOC,MAAM,CAACX,SAASM,MAAM,GAAG;AACtD,MAAML,iBAAiB;AACvB,MAAME,MAAM"}
package/build/types.d.ts CHANGED
@@ -26,10 +26,8 @@ export interface BenchmarkOptions {
26
26
  absThreshold?: number;
27
27
  relThreshold?: number;
28
28
  gcObserver?: boolean;
29
- baseUrl?: string;
30
29
  }
31
30
  export interface RunOptions<TContext, TInput> {
32
- baseUrl?: string;
33
31
  setup?: SetupFn<TContext>;
34
32
  teardown?: TeardownFn<TContext>;
35
33
  pre?: StepFn<TContext, TInput>;
@@ -38,7 +36,7 @@ export interface RunOptions<TContext, TInput> {
38
36
  data?: TInput;
39
37
  }
40
38
  export interface WorkerOptions extends Required<BenchmarkOptions> {
41
- baseUrl: string;
39
+ benchmarkUrl?: string;
42
40
  setupCode?: string;
43
41
  teardownCode?: string;
44
42
  preCode?: string;
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/types.ts"],"sourcesContent":["export type MaybePromise<T> = Promise<T> | PromiseLike<T> | T;\n\nexport interface SetupFn<TContext> {\n (): MaybePromise<TContext>;\n}\n\nexport interface TeardownFn<TContext> {\n (ctx: TContext): MaybePromise<void>;\n}\n\nexport interface StepFn<TContext, TInput> {\n (ctx: TContext, input: TInput): MaybePromise<void>;\n}\n\nexport interface FeedFn<TInput> {\n (): MaybePromise<TInput>;\n}\n\ntype _Sequence<To extends number, R extends unknown[]> = R['length'] extends To ? R[number] : _Sequence<To, [R['length'], ...R]>;\nexport type Sequence<To extends number> = number extends To ? number : _Sequence<To, []>;\nexport type Between<From extends number, To extends number> = Exclude<Sequence<To>, Sequence<From>>;\n\nexport type ReportType = 'ops' | 'min' | 'max' | 'mean' | 'median' | 'mode' | `p${Between<1, 100>}`;\nexport type ReportTypeList = readonly ReportType[];\nexport const REPORT_TYPES: ReportTypeList = Array.from({ length: 99 }, (_, idx) => `p${idx + 1}` as ReportType).concat(['ops', 'mean', 'min', 'max', 'median', 'mode']);\n\nexport interface ReportOptions<R extends ReportTypeList> {\n reportTypes: R;\n}\n\nexport interface BenchmarkOptions {\n warmupCycles?: number;\n minCycles?: number;\n absThreshold?: number; // ns\n relThreshold?: number; // %\n gcObserver?: boolean;\n baseUrl?: string;\n}\n\nexport interface RunOptions<TContext, TInput> {\n baseUrl?: string;\n setup?: SetupFn<TContext>;\n teardown?: TeardownFn<TContext>;\n pre?: StepFn<TContext, TInput>;\n run: StepFn<TContext, TInput>;\n post?: StepFn<TContext, TInput>;\n data?: TInput;\n}\n\nexport interface WorkerOptions extends Required<BenchmarkOptions> {\n baseUrl: string;\n setupCode?: string;\n teardownCode?: string;\n preCode?: string;\n runCode: string;\n postCode?: string;\n data?: unknown;\n\n durationsSAB: SharedArrayBuffer;\n controlSAB: SharedArrayBuffer;\n}\n\nexport interface Options<TContext, TInput> extends RunOptions<TContext, TInput>, BenchmarkOptions {\n durationsSAB: SharedArrayBuffer;\n controlSAB: SharedArrayBuffer;\n}\n\nexport enum Control {\n INDEX,\n PROGRESS,\n COMPLETE,\n}\n\nexport const CONTROL_SLOTS = Object.values(Control).length / 2;\nexport const DEFAULT_CYCLES = 1_000;\nexport const Z95 = 1.96;\n"],"names":["REPORT_TYPES","Array","from","length","_","idx","concat","Control","CONTROL_SLOTS","Object","values","DEFAULT_CYCLES","Z95"],"mappings":"AAwBA,OAAO,MAAMA,eAA+BC,MAAMC,IAAI,CAAC;IAAEC,QAAQ;AAAG,GAAG,CAACC,GAAGC,MAAQ,CAAC,CAAC,EAAEA,MAAM,GAAG,EAAgBC,MAAM,CAAC;IAAC;IAAO;IAAQ;IAAO;IAAO;IAAU;CAAO,EAAE;AA2CxK,OAAO,IAAA,AAAKC,iCAAAA;;;;WAAAA;MAIX;AAED,OAAO,MAAMC,gBAAgBC,OAAOC,MAAM,CAACH,SAASJ,MAAM,GAAG,EAAE;AAC/D,OAAO,MAAMQ,iBAAiB,MAAM;AACpC,OAAO,MAAMC,MAAM,KAAK"}
1
+ {"version":3,"sources":["../src/types.ts"],"sourcesContent":["export type MaybePromise<T> = Promise<T> | PromiseLike<T> | T;\n\nexport interface SetupFn<TContext> {\n (): MaybePromise<TContext>;\n}\n\nexport interface TeardownFn<TContext> {\n (ctx: TContext): MaybePromise<void>;\n}\n\nexport interface StepFn<TContext, TInput> {\n (ctx: TContext, input: TInput): MaybePromise<void>;\n}\n\nexport interface FeedFn<TInput> {\n (): MaybePromise<TInput>;\n}\n\ntype _Sequence<To extends number, R extends unknown[]> = R['length'] extends To ? R[number] : _Sequence<To, [R['length'], ...R]>;\nexport type Sequence<To extends number> = number extends To ? number : _Sequence<To, []>;\nexport type Between<From extends number, To extends number> = Exclude<Sequence<To>, Sequence<From>>;\n\nexport type ReportType = 'ops' | 'min' | 'max' | 'mean' | 'median' | 'mode' | `p${Between<1, 100>}`;\nexport type ReportTypeList = readonly ReportType[];\nexport const REPORT_TYPES: ReportTypeList = Array.from({ length: 99 }, (_, idx) => `p${idx + 1}` as ReportType).concat(['ops', 'mean', 'min', 'max', 'median', 'mode']);\n\nexport interface ReportOptions<R extends ReportTypeList> {\n reportTypes: R;\n}\n\nexport interface BenchmarkOptions {\n warmupCycles?: number;\n minCycles?: number;\n absThreshold?: number; // ns\n relThreshold?: number; // %\n gcObserver?: boolean;\n}\n\nexport interface RunOptions<TContext, TInput> {\n setup?: SetupFn<TContext>;\n teardown?: TeardownFn<TContext>;\n pre?: StepFn<TContext, TInput>;\n run: StepFn<TContext, TInput>;\n post?: StepFn<TContext, TInput>;\n data?: TInput;\n}\n\nexport interface WorkerOptions extends Required<BenchmarkOptions> {\n benchmarkUrl?: string;\n setupCode?: string;\n teardownCode?: string;\n preCode?: string;\n runCode: string;\n postCode?: string;\n data?: unknown;\n\n durationsSAB: SharedArrayBuffer;\n controlSAB: SharedArrayBuffer;\n}\n\nexport interface Options<TContext, TInput> extends RunOptions<TContext, TInput>, BenchmarkOptions {\n durationsSAB: SharedArrayBuffer;\n controlSAB: SharedArrayBuffer;\n}\n\nexport enum Control {\n INDEX,\n PROGRESS,\n COMPLETE,\n}\n\nexport const CONTROL_SLOTS = Object.values(Control).length / 2;\nexport const DEFAULT_CYCLES = 1_000;\nexport const Z95 = 1.96;\n"],"names":["REPORT_TYPES","Array","from","length","_","idx","concat","Control","CONTROL_SLOTS","Object","values","DEFAULT_CYCLES","Z95"],"mappings":"AAwBA,OAAO,MAAMA,eAA+BC,MAAMC,IAAI,CAAC;IAAEC,QAAQ;AAAG,GAAG,CAACC,GAAGC,MAAQ,CAAC,CAAC,EAAEA,MAAM,GAAG,EAAgBC,MAAM,CAAC;IAAC;IAAO;IAAQ;IAAO;IAAO;IAAU;CAAO,EAAE;AAyCxK,OAAO,IAAA,AAAKC,iCAAAA;;;;WAAAA;MAIX;AAED,OAAO,MAAMC,gBAAgBC,OAAOC,MAAM,CAACH,SAASJ,MAAM,GAAG,EAAE;AAC/D,OAAO,MAAMQ,iBAAiB,MAAM;AACpC,OAAO,MAAMC,MAAM,KAAK"}