overtake 1.2.1 → 1.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +260 -45
- package/build/cli.cjs +37 -17
- package/build/cli.cjs.map +1 -1
- package/build/cli.js +39 -19
- package/build/cli.js.map +1 -1
- package/build/executor.cjs +20 -0
- package/build/executor.cjs.map +1 -1
- package/build/executor.d.ts +2 -0
- package/build/executor.js +20 -0
- package/build/executor.js.map +1 -1
- package/build/index.cjs +121 -2
- package/build/index.cjs.map +1 -1
- package/build/index.d.ts +9 -0
- package/build/index.js +109 -2
- package/build/index.js.map +1 -1
- package/build/reporter.cjs +63 -0
- package/build/reporter.cjs.map +1 -1
- package/build/reporter.js +63 -0
- package/build/reporter.js.map +1 -1
- package/build/runner.cjs +29 -5
- package/build/runner.cjs.map +1 -1
- package/build/runner.js +29 -5
- package/build/runner.js.map +1 -1
- package/build/types.cjs +6 -1
- package/build/types.cjs.map +1 -1
- package/build/types.d.ts +3 -2
- package/build/types.js +6 -1
- package/build/types.js.map +1 -1
- package/context7.json +4 -0
- package/package.json +1 -1
- package/src/cli.ts +53 -18
- package/src/executor.ts +25 -2
- package/src/index.ts +123 -3
- package/src/reporter.ts +63 -0
- package/src/runner.ts +33 -5
- package/src/types.ts +22 -1
package/build/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["import { cpus } from 'node:os';\nimport Progress from 'progress';\nimport { createExecutor, ExecutorOptions, ExecutorReport } from './executor.js';\nimport { MaybePromise, StepFn, SetupFn, TeardownFn, FeedFn, ReportType, ReportTypeList, DEFAULT_CYCLES, ProgressInfo } 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> & { progress?: boolean }): 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 progress = false,\n progressInterval = 100,\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 totalBenchmarks = this.#targets.reduce((acc, t) => acc + t.measures.length * this.#feeds.length, 0);\n const progressMap = new Map<string, number>();\n let completedBenchmarks = 0;\n let bar: Progress | null = null;\n\n if (progress && totalBenchmarks > 0) {\n bar = new Progress(' [:bar] :percent :current/:total :label', {\n total: totalBenchmarks * 100,\n width: 30,\n complete: '=',\n incomplete: ' ',\n });\n }\n\n const onProgress = progress\n ? (info: ProgressInfo) => {\n progressMap.set(info.id, info.progress);\n const totalProgress = (completedBenchmarks + [...progressMap.values()].reduce((a, b) => a + b, 0)) * 100;\n const label = info.id.length > 30 ? info.id.slice(0, 27) + '...' : info.id;\n bar?.update(totalProgress / (totalBenchmarks * 100), { label });\n }\n : undefined;\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 onProgress,\n progressInterval,\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 id = `${target.title}/${measure.title}/${feed.title}`;\n const data = await feed.fn?.();\n executor\n .push<ExecutorReport<R>>({\n id,\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 progressMap.delete(id);\n completedBenchmarks++;\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 if (bar) {\n bar.update(1, { label: 'done' });\n bar.terminate();\n }\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","Progress","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","progress","progressInterval","Error","benchmarkUrl","totalBenchmarks","reduce","acc","t","progressMap","Map","completedBenchmarks","bar","total","width","complete","incomplete","onProgress","info","set","id","totalProgress","values","a","b","label","slice","update","undefined","executor","reports","targetReport","measureReport","feeds","data","then","delete","drain","kill","terminate","printSimpleReports","report","console","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 Progress from 'progress';\nimport { createExecutor, ExecutorOptions, ExecutorReport } from './executor.js';\nimport { MaybePromise, StepFn, SetupFn, TeardownFn, FeedFn, ReportType, ReportTypeList, DEFAULT_CYCLES, ProgressInfo } 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> & { progress?: boolean }): 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 progress = false,\n progressInterval = 100,\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 totalBenchmarks = this.#targets.reduce((acc, t) => acc + t.measures.length * this.#feeds.length, 0);\n const progressMap = new Map<string, number>();\n let completedBenchmarks = 0;\n let bar: Progress | null = null;\n\n if (progress && totalBenchmarks > 0) {\n bar = new Progress(' [:bar] :percent :current/:total :label', {\n total: totalBenchmarks * 100,\n width: 30,\n complete: '=',\n incomplete: ' ',\n });\n }\n\n const onProgress = progress\n ? (info: ProgressInfo) => {\n progressMap.set(info.id, info.progress);\n const totalProgress = (completedBenchmarks + [...progressMap.values()].reduce((a, b) => a + b, 0)) * 100;\n const label = info.id.length > 30 ? info.id.slice(0, 27) + '...' : info.id;\n bar?.update(totalProgress / (totalBenchmarks * 100), { label });\n }\n : undefined;\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 onProgress,\n progressInterval,\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 id = `${target.title}/${measure.title}/${feed.title}`;\n const data = await feed.fn?.();\n executor\n .push<ExecutorReport<R>>({\n id,\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 progressMap.delete(id);\n completedBenchmarks++;\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 if (bar) {\n bar.update(1, { label: 'done' });\n bar.terminate();\n }\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 { count, heapUsedKB, dceWarning, ...metrics } = data as Record<string, unknown>;\n const output = Object.entries(metrics)\n .map(([key, report]) => `${key}: ${(report as { toString(): string }).toString()}`)\n .join('; ');\n const extras: string[] = [];\n if (heapUsedKB) extras.push(`heap: ${heapUsedKB}KB`);\n if (dceWarning) extras.push('\\x1b[33m[DCE warning]\\x1b[0m');\n const extrasStr = extras.length > 0 ? ` (${extras.join(', ')})` : '';\n console.log(feed, output + extrasStr);\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\nexport const printMarkdownReports = <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`);\n if (feeds.length === 0) continue;\n\n const keys = Object.keys(feeds[0].data).filter((k) => k !== 'count');\n const header = ['Feed', ...keys].join(' | ');\n const separator = ['---', ...keys.map(() => '---')].join(' | ');\n\n console.log(`| ${header} |`);\n console.log(`| ${separator} |`);\n\n for (const { feed, data } of feeds) {\n const values = keys.map((k) => (data as Record<string, { toString(): string }>)[k]?.toString() ?? '-');\n console.log(`| ${[feed, ...values].join(' | ')} |`);\n }\n }\n }\n};\n\nexport const printHistogramReports = <R extends ReportTypeList>(reports: TargetReport<R>[], width = 40) => {\n for (const report of reports) {\n for (const { measure, feeds } of report.measures) {\n console.log(`\\n${report.target} - ${measure}\\n`);\n\n const opsKey = 'ops';\n const values = feeds.map((f) => ({\n feed: f.feed,\n value: (f.data as Record<string, { valueOf(): number }>)[opsKey]?.valueOf() ?? 0,\n }));\n\n const maxValue = Math.max(...values.map((v) => v.value));\n const maxLabelLen = Math.max(...values.map((v) => v.feed.length));\n\n for (const { feed, value } of values) {\n const barLen = maxValue > 0 ? Math.round((value / maxValue) * width) : 0;\n const bar = '\\u2588'.repeat(barLen);\n const label = feed.padEnd(maxLabelLen);\n const formatted = value.toLocaleString('en-US', { maximumFractionDigits: 2 });\n console.log(` ${label} | ${bar} ${formatted} ops/s`);\n }\n }\n }\n};\n\nexport interface BaselineData {\n version: number;\n timestamp: string;\n results: Record<string, Record<string, number>>;\n}\n\nexport const reportsToBaseline = <R extends ReportTypeList>(reports: TargetReport<R>[]): BaselineData => {\n const results: Record<string, Record<string, number>> = {};\n for (const report of reports) {\n for (const { measure, feeds } of report.measures) {\n for (const { feed, data } of feeds) {\n const key = `${report.target}/${measure}/${feed}`;\n results[key] = {};\n for (const [metric, value] of Object.entries(data)) {\n if (metric !== 'count' && typeof (value as { valueOf(): number }).valueOf === 'function') {\n results[key][metric] = (value as { valueOf(): number }).valueOf();\n }\n }\n }\n }\n }\n return {\n version: 1,\n timestamp: new Date().toISOString(),\n results,\n };\n};\n\nexport const printComparisonReports = <R extends ReportTypeList>(reports: TargetReport<R>[], baseline: BaselineData, threshold = 5) => {\n for (const report of reports) {\n for (const { measure, feeds } of report.measures) {\n console.log(`\\n${report.target} - ${measure}\\n`);\n\n for (const { feed, data } of feeds) {\n const key = `${report.target}/${measure}/${feed}`;\n const baselineData = baseline.results[key];\n\n console.log(` ${feed}:`);\n\n for (const [metric, value] of Object.entries(data)) {\n if (metric === 'count') continue;\n const current = (value as { valueOf(): number }).valueOf();\n const baselineValue = baselineData?.[metric];\n\n if (baselineValue !== undefined && baselineValue !== 0) {\n const change = ((current - baselineValue) / baselineValue) * 100;\n const isOps = metric === 'ops';\n const improved = isOps ? change > threshold : change < -threshold;\n const regressed = isOps ? change < -threshold : change > threshold;\n\n let indicator = ' ';\n if (improved) indicator = '\\x1b[32m+\\x1b[0m';\n else if (regressed) indicator = '\\x1b[31m!\\x1b[0m';\n\n const changeStr = change >= 0 ? `+${change.toFixed(1)}%` : `${change.toFixed(1)}%`;\n const coloredChange = regressed ? `\\x1b[31m${changeStr}\\x1b[0m` : improved ? `\\x1b[32m${changeStr}\\x1b[0m` : changeStr;\n\n console.log(` ${indicator} ${metric}: ${(value as { toString(): string }).toString()} (${coloredChange})`);\n } else {\n console.log(` * ${metric}: ${(value as { toString(): string }).toString()} (new)`);\n }\n }\n }\n }\n }\n\n console.log(`\\nBaseline from: ${baseline.timestamp}`);\n};\n"],"names":["cpus","Progress","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","progress","progressInterval","Error","benchmarkUrl","totalBenchmarks","reduce","acc","t","progressMap","Map","completedBenchmarks","bar","total","width","complete","incomplete","onProgress","info","set","id","totalProgress","values","a","b","label","slice","update","undefined","executor","reports","targetReport","measureReport","feeds","data","then","delete","drain","kill","terminate","printSimpleReports","report","console","group","count","heapUsedKB","dceWarning","metrics","output","Object","entries","map","key","toString","join","extras","extrasStr","log","groupEnd","printTableReports","table","fromEntries","printJSONReports","padding","row","JSON","stringify","printMarkdownReports","keys","filter","k","header","separator","printHistogramReports","opsKey","f","value","valueOf","maxValue","Math","max","v","maxLabelLen","barLen","round","repeat","padEnd","formatted","toLocaleString","maximumFractionDigits","reportsToBaseline","results","metric","version","timestamp","Date","toISOString","printComparisonReports","baseline","threshold","baselineData","current","baselineValue","change","isOps","improved","regressed","indicator","changeStr","toFixed","coloredChange"],"mappings":"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"}
|
package/build/reporter.cjs
CHANGED
|
@@ -278,6 +278,69 @@ const createReport = (durations, type)=>{
|
|
|
278
278
|
const rmeScaled = BigInt(Math.round(rme * 100));
|
|
279
279
|
return new Report(type, rmeScaled, 0, 100n);
|
|
280
280
|
}
|
|
281
|
+
case 'mad':
|
|
282
|
+
{
|
|
283
|
+
const medianIdx = Math.floor(n / 2);
|
|
284
|
+
const median = n % 2 === 1 ? durations[medianIdx] : (durations[medianIdx - 1] + durations[medianIdx]) / 2n;
|
|
285
|
+
const deviations = new BigUint64Array(n);
|
|
286
|
+
for(let i = 0; i < n; i++){
|
|
287
|
+
const diff = durations[i] > median ? durations[i] - median : median - durations[i];
|
|
288
|
+
deviations[i] = diff;
|
|
289
|
+
}
|
|
290
|
+
deviations.sort();
|
|
291
|
+
const madIdx = Math.floor(n / 2);
|
|
292
|
+
const mad = n % 2 === 1 ? deviations[madIdx] : (deviations[madIdx - 1] + deviations[madIdx]) / 2n;
|
|
293
|
+
return new Report(type, mad, 0, _typescjs.DURATION_SCALE);
|
|
294
|
+
}
|
|
295
|
+
case 'iqr':
|
|
296
|
+
{
|
|
297
|
+
const q1Idx = Math.floor(n * 0.25);
|
|
298
|
+
const q3Idx = Math.floor(n * 0.75);
|
|
299
|
+
const q1 = durations[q1Idx];
|
|
300
|
+
const q3 = durations[q3Idx];
|
|
301
|
+
const iqr = q3 - q1;
|
|
302
|
+
return new Report(type, iqr, 0, _typescjs.DURATION_SCALE);
|
|
303
|
+
}
|
|
304
|
+
case 'ci_lower':
|
|
305
|
+
{
|
|
306
|
+
if (n < 2) return new Report(type, 0n, 0, _typescjs.DURATION_SCALE);
|
|
307
|
+
let sum = 0n;
|
|
308
|
+
for (const duration of durations){
|
|
309
|
+
sum += duration;
|
|
310
|
+
}
|
|
311
|
+
const mean = Number(sum) / n;
|
|
312
|
+
let sumSquaredDiff = 0;
|
|
313
|
+
for (const duration of durations){
|
|
314
|
+
const diff = Number(duration) - mean;
|
|
315
|
+
sumSquaredDiff += diff * diff;
|
|
316
|
+
}
|
|
317
|
+
const variance = sumSquaredDiff / (n - 1);
|
|
318
|
+
const sd = Math.sqrt(variance);
|
|
319
|
+
const sem = sd / Math.sqrt(n);
|
|
320
|
+
const moe = _typescjs.Z95 * sem;
|
|
321
|
+
const ciLower = Math.max(0, mean - moe);
|
|
322
|
+
return new Report(type, BigInt(Math.round(ciLower)), 0, _typescjs.DURATION_SCALE);
|
|
323
|
+
}
|
|
324
|
+
case 'ci_upper':
|
|
325
|
+
{
|
|
326
|
+
if (n < 2) return new Report(type, 0n, 0, _typescjs.DURATION_SCALE);
|
|
327
|
+
let sum = 0n;
|
|
328
|
+
for (const duration of durations){
|
|
329
|
+
sum += duration;
|
|
330
|
+
}
|
|
331
|
+
const mean = Number(sum) / n;
|
|
332
|
+
let sumSquaredDiff = 0;
|
|
333
|
+
for (const duration of durations){
|
|
334
|
+
const diff = Number(duration) - mean;
|
|
335
|
+
sumSquaredDiff += diff * diff;
|
|
336
|
+
}
|
|
337
|
+
const variance = sumSquaredDiff / (n - 1);
|
|
338
|
+
const sd = Math.sqrt(variance);
|
|
339
|
+
const sem = sd / Math.sqrt(n);
|
|
340
|
+
const moe = _typescjs.Z95 * sem;
|
|
341
|
+
const ciUpper = mean + moe;
|
|
342
|
+
return new Report(type, BigInt(Math.round(ciUpper)), 0, _typescjs.DURATION_SCALE);
|
|
343
|
+
}
|
|
281
344
|
default:
|
|
282
345
|
{
|
|
283
346
|
const p = Number(type.slice(1));
|
package/build/reporter.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/reporter.ts"],"sourcesContent":["import { div, max, divs } from './utils.js';\nimport { ReportType, DURATION_SCALE, Z95 } from './types.js';\n\nconst units = [\n { unit: 'ns', factor: 1 },\n { unit: 'µs', factor: 1e3 },\n { unit: 'ms', factor: 1e6 },\n { unit: 's', factor: 1e9 },\n { unit: 'm', factor: 60 * 1e9 },\n { unit: 'h', factor: 3600 * 1e9 },\n] as const;\n\nfunction smartFixed(n: number): string {\n return n.toLocaleString(undefined, {\n minimumFractionDigits: 0,\n maximumFractionDigits: 2,\n useGrouping: true,\n });\n}\nexport class Report {\n constructor(\n public readonly type: ReportType,\n public readonly value: bigint,\n public readonly uncertainty: number = 0,\n public readonly scale: bigint = 1n,\n ) {}\n valueOf() {\n return Number(div(this.value, this.scale));\n }\n toString() {\n const uncertainty = this.uncertainty ? ` ± ${smartFixed(this.uncertainty)}%` : '';\n\n const value = this.valueOf();\n if (this.type === 'ops') {\n return `${smartFixed(value)} ops/s${uncertainty}`;\n }\n if (this.type === 'rme') {\n return `${smartFixed(value)}%`;\n }\n if (this.type === 'variance') {\n let display = value;\n let unit = 'ns²';\n const varianceUnits = [\n { unit: 'ns²', factor: 1 },\n { unit: 'µs²', factor: 1e6 },\n { unit: 'ms²', factor: 1e12 },\n ];\n for (const { unit: u, factor } of varianceUnits) {\n const candidate = value / factor;\n if (candidate < 1000) {\n display = candidate;\n unit = u;\n break;\n }\n }\n return `${smartFixed(display)} ${unit}`;\n }\n let display = value;\n let unit = 'ns';\n\n for (const { unit: u, factor } of units) {\n const candidate = value / factor;\n if (candidate < 1000) {\n display = candidate;\n unit = u;\n break;\n }\n }\n return `${smartFixed(display)} ${unit}${uncertainty}`;\n }\n}\n\nexport const createReport = (durations: BigUint64Array, type: ReportType): Report => {\n const n = durations.length;\n if (n === 0) {\n return new Report(type, 0n);\n }\n switch (type) {\n case 'min': {\n return new Report(type, durations[0], 0, DURATION_SCALE);\n }\n case 'max': {\n return new Report(type, durations[n - 1], 0, DURATION_SCALE);\n }\n case 'median': {\n const mid = Math.floor(n / 2);\n const med = n % 2 === 0 ? (durations[mid - 1] + durations[mid]) / 2n : durations[mid];\n return new Report(type, med, 0, DURATION_SCALE);\n }\n\n case 'mode': {\n const freq = new Map<bigint, bigint>();\n let maxCount = 0n;\n let modeVal = durations[0];\n for (const d of durations) {\n const count = (freq.get(d) || 0n) + 1n;\n freq.set(d, count);\n if (count > maxCount) {\n maxCount = count;\n modeVal = d;\n }\n }\n let lower = modeVal;\n let upper = modeVal;\n const firstIdx = durations.indexOf(modeVal);\n const lastIdx = durations.lastIndexOf(modeVal);\n if (firstIdx > 0) lower = durations[firstIdx - 1];\n if (lastIdx < n - 1) upper = durations[lastIdx + 1];\n const gap = max(modeVal - lower, upper - modeVal);\n const uncertainty = modeVal > 0 ? Number(((gap / 2n) * 100n) / modeVal) : 0;\n return new Report(type, modeVal, uncertainty, DURATION_SCALE);\n }\n\n case 'ops': {\n let sum = 0n;\n for (const duration of durations) {\n sum += duration;\n }\n const avgScaled = sum / BigInt(n);\n const nsPerSecScaled = 1_000_000_000n * DURATION_SCALE;\n const raw = Number(nsPerSecScaled) / Number(avgScaled);\n const extra = raw < 1 ? Math.ceil(-Math.log10(raw)) : 0;\n\n const exp = raw > 100 ? 0 : 2 + extra;\n\n const scale = 10n ** BigInt(exp);\n\n const value = avgScaled > 0n ? (nsPerSecScaled * scale) / avgScaled : 0n;\n const deviation = durations[n - 1] - durations[0];\n const uncertainty = avgScaled > 0 ? Number(div(deviation * scale, 2n * avgScaled)) : 0;\n return new Report(type, value, uncertainty, scale);\n }\n case 'mean': {\n let sum = 0n;\n for (const duration of durations) {\n sum += duration;\n }\n const value = divs(sum, BigInt(n), 1n);\n return new Report(type, value, 0, DURATION_SCALE);\n }\n\n case 'variance': {\n if (n < 2) return new Report(type, 0n, 0, DURATION_SCALE * DURATION_SCALE);\n let sum = 0n;\n for (const duration of durations) {\n sum += duration;\n }\n const mean = sum / BigInt(n);\n let sumSquaredDiff = 0n;\n for (const duration of durations) {\n const diff = duration - mean;\n sumSquaredDiff += diff * diff;\n }\n const variance = sumSquaredDiff / BigInt(n - 1);\n return new Report(type, variance, 0, DURATION_SCALE * DURATION_SCALE);\n }\n\n case 'sd': {\n if (n < 2) return new Report(type, 0n, 0, DURATION_SCALE);\n let sum = 0n;\n for (const duration of durations) {\n sum += duration;\n }\n const mean = sum / BigInt(n);\n let sumSquaredDiff = 0n;\n for (const duration of durations) {\n const diff = duration - mean;\n sumSquaredDiff += diff * diff;\n }\n const variance = Number(sumSquaredDiff) / (n - 1);\n const sd = Math.sqrt(variance);\n const sdScaled = BigInt(Math.round(sd));\n return new Report(type, sdScaled, 0, DURATION_SCALE);\n }\n\n case 'sem': {\n if (n < 2) return new Report(type, 0n, 0, DURATION_SCALE);\n let sum = 0n;\n for (const duration of durations) {\n sum += duration;\n }\n const mean = sum / BigInt(n);\n let sumSquaredDiff = 0n;\n for (const duration of durations) {\n const diff = duration - mean;\n sumSquaredDiff += diff * diff;\n }\n const variance = Number(sumSquaredDiff) / (n - 1);\n const sd = Math.sqrt(variance);\n const sem = sd / Math.sqrt(n);\n const semScaled = BigInt(Math.round(sem));\n return new Report(type, semScaled, 0, DURATION_SCALE);\n }\n\n case 'moe': {\n if (n < 2) return new Report(type, 0n, 0, DURATION_SCALE);\n let sum = 0n;\n for (const duration of durations) {\n sum += duration;\n }\n const mean = sum / BigInt(n);\n let sumSquaredDiff = 0n;\n for (const duration of durations) {\n const diff = duration - mean;\n sumSquaredDiff += diff * diff;\n }\n const variance = Number(sumSquaredDiff) / (n - 1);\n const sd = Math.sqrt(variance);\n const sem = sd / Math.sqrt(n);\n const moe = Z95 * sem;\n const moeScaled = BigInt(Math.round(moe));\n return new Report(type, moeScaled, 0, DURATION_SCALE);\n }\n\n case 'rme': {\n if (n < 2) return new Report(type, 0n);\n let sum = 0n;\n for (const duration of durations) {\n sum += duration;\n }\n const mean = Number(sum) / n;\n if (mean === 0) return new Report(type, 0n);\n let sumSquaredDiff = 0;\n for (const duration of durations) {\n const diff = Number(duration) - mean;\n sumSquaredDiff += diff * diff;\n }\n const variance = sumSquaredDiff / (n - 1);\n const sd = Math.sqrt(variance);\n const sem = sd / Math.sqrt(n);\n const moe = Z95 * sem;\n const rme = (moe / mean) * 100;\n const rmeScaled = BigInt(Math.round(rme * 100));\n return new Report(type, rmeScaled, 0, 100n);\n }\n\n default: {\n const p = Number(type.slice(1));\n if (p === 0) {\n return new Report(type, durations[0], 0, DURATION_SCALE);\n }\n if (p === 100) {\n return new Report(type, durations[n - 1], 0, DURATION_SCALE);\n }\n const idx = Math.ceil((p / 100) * n) - 1;\n const value = durations[Math.min(Math.max(idx, 0), n - 1)];\n const prev = idx > 0 ? durations[idx - 1] : value;\n const next = idx < n - 1 ? durations[idx + 1] : value;\n const gap = max(value - prev, next - value);\n const uncertainty = value > 0 ? Number(div(divs(gap, 2n, 100_00n), value)) / 100 : 0;\n\n return new Report(type, value, uncertainty, DURATION_SCALE);\n }\n }\n};\n"],"names":["Report","createReport","units","unit","factor","smartFixed","n","toLocaleString","undefined","minimumFractionDigits","maximumFractionDigits","useGrouping","type","value","uncertainty","scale","valueOf","Number","div","toString","display","varianceUnits","u","candidate","durations","length","DURATION_SCALE","mid","Math","floor","med","freq","Map","maxCount","modeVal","d","count","get","set","lower","upper","firstIdx","indexOf","lastIdx","lastIndexOf","gap","max","sum","duration","avgScaled","BigInt","nsPerSecScaled","raw","extra","ceil","log10","exp","deviation","divs","mean","sumSquaredDiff","diff","variance","sd","sqrt","sdScaled","round","sem","semScaled","moe","Z95","moeScaled","rme","rmeScaled","p","slice","idx","min","prev","next"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../src/reporter.ts"],"sourcesContent":["import { div, max, divs } from './utils.js';\nimport { ReportType, DURATION_SCALE, Z95 } from './types.js';\n\nconst units = [\n { unit: 'ns', factor: 1 },\n { unit: 'µs', factor: 1e3 },\n { unit: 'ms', factor: 1e6 },\n { unit: 's', factor: 1e9 },\n { unit: 'm', factor: 60 * 1e9 },\n { unit: 'h', factor: 3600 * 1e9 },\n] as const;\n\nfunction smartFixed(n: number): string {\n return n.toLocaleString(undefined, {\n minimumFractionDigits: 0,\n maximumFractionDigits: 2,\n useGrouping: true,\n });\n}\nexport class Report {\n constructor(\n public readonly type: ReportType,\n public readonly value: bigint,\n public readonly uncertainty: number = 0,\n public readonly scale: bigint = 1n,\n ) {}\n valueOf() {\n return Number(div(this.value, this.scale));\n }\n toString() {\n const uncertainty = this.uncertainty ? ` ± ${smartFixed(this.uncertainty)}%` : '';\n\n const value = this.valueOf();\n if (this.type === 'ops') {\n return `${smartFixed(value)} ops/s${uncertainty}`;\n }\n if (this.type === 'rme') {\n return `${smartFixed(value)}%`;\n }\n if (this.type === 'variance') {\n let display = value;\n let unit = 'ns²';\n const varianceUnits = [\n { unit: 'ns²', factor: 1 },\n { unit: 'µs²', factor: 1e6 },\n { unit: 'ms²', factor: 1e12 },\n ];\n for (const { unit: u, factor } of varianceUnits) {\n const candidate = value / factor;\n if (candidate < 1000) {\n display = candidate;\n unit = u;\n break;\n }\n }\n return `${smartFixed(display)} ${unit}`;\n }\n let display = value;\n let unit = 'ns';\n\n for (const { unit: u, factor } of units) {\n const candidate = value / factor;\n if (candidate < 1000) {\n display = candidate;\n unit = u;\n break;\n }\n }\n return `${smartFixed(display)} ${unit}${uncertainty}`;\n }\n}\n\nexport const createReport = (durations: BigUint64Array, type: ReportType): Report => {\n const n = durations.length;\n if (n === 0) {\n return new Report(type, 0n);\n }\n switch (type) {\n case 'min': {\n return new Report(type, durations[0], 0, DURATION_SCALE);\n }\n case 'max': {\n return new Report(type, durations[n - 1], 0, DURATION_SCALE);\n }\n case 'median': {\n const mid = Math.floor(n / 2);\n const med = n % 2 === 0 ? (durations[mid - 1] + durations[mid]) / 2n : durations[mid];\n return new Report(type, med, 0, DURATION_SCALE);\n }\n\n case 'mode': {\n const freq = new Map<bigint, bigint>();\n let maxCount = 0n;\n let modeVal = durations[0];\n for (const d of durations) {\n const count = (freq.get(d) || 0n) + 1n;\n freq.set(d, count);\n if (count > maxCount) {\n maxCount = count;\n modeVal = d;\n }\n }\n let lower = modeVal;\n let upper = modeVal;\n const firstIdx = durations.indexOf(modeVal);\n const lastIdx = durations.lastIndexOf(modeVal);\n if (firstIdx > 0) lower = durations[firstIdx - 1];\n if (lastIdx < n - 1) upper = durations[lastIdx + 1];\n const gap = max(modeVal - lower, upper - modeVal);\n const uncertainty = modeVal > 0 ? Number(((gap / 2n) * 100n) / modeVal) : 0;\n return new Report(type, modeVal, uncertainty, DURATION_SCALE);\n }\n\n case 'ops': {\n let sum = 0n;\n for (const duration of durations) {\n sum += duration;\n }\n const avgScaled = sum / BigInt(n);\n const nsPerSecScaled = 1_000_000_000n * DURATION_SCALE;\n const raw = Number(nsPerSecScaled) / Number(avgScaled);\n const extra = raw < 1 ? Math.ceil(-Math.log10(raw)) : 0;\n\n const exp = raw > 100 ? 0 : 2 + extra;\n\n const scale = 10n ** BigInt(exp);\n\n const value = avgScaled > 0n ? (nsPerSecScaled * scale) / avgScaled : 0n;\n const deviation = durations[n - 1] - durations[0];\n const uncertainty = avgScaled > 0 ? Number(div(deviation * scale, 2n * avgScaled)) : 0;\n return new Report(type, value, uncertainty, scale);\n }\n case 'mean': {\n let sum = 0n;\n for (const duration of durations) {\n sum += duration;\n }\n const value = divs(sum, BigInt(n), 1n);\n return new Report(type, value, 0, DURATION_SCALE);\n }\n\n case 'variance': {\n if (n < 2) return new Report(type, 0n, 0, DURATION_SCALE * DURATION_SCALE);\n let sum = 0n;\n for (const duration of durations) {\n sum += duration;\n }\n const mean = sum / BigInt(n);\n let sumSquaredDiff = 0n;\n for (const duration of durations) {\n const diff = duration - mean;\n sumSquaredDiff += diff * diff;\n }\n const variance = sumSquaredDiff / BigInt(n - 1);\n return new Report(type, variance, 0, DURATION_SCALE * DURATION_SCALE);\n }\n\n case 'sd': {\n if (n < 2) return new Report(type, 0n, 0, DURATION_SCALE);\n let sum = 0n;\n for (const duration of durations) {\n sum += duration;\n }\n const mean = sum / BigInt(n);\n let sumSquaredDiff = 0n;\n for (const duration of durations) {\n const diff = duration - mean;\n sumSquaredDiff += diff * diff;\n }\n const variance = Number(sumSquaredDiff) / (n - 1);\n const sd = Math.sqrt(variance);\n const sdScaled = BigInt(Math.round(sd));\n return new Report(type, sdScaled, 0, DURATION_SCALE);\n }\n\n case 'sem': {\n if (n < 2) return new Report(type, 0n, 0, DURATION_SCALE);\n let sum = 0n;\n for (const duration of durations) {\n sum += duration;\n }\n const mean = sum / BigInt(n);\n let sumSquaredDiff = 0n;\n for (const duration of durations) {\n const diff = duration - mean;\n sumSquaredDiff += diff * diff;\n }\n const variance = Number(sumSquaredDiff) / (n - 1);\n const sd = Math.sqrt(variance);\n const sem = sd / Math.sqrt(n);\n const semScaled = BigInt(Math.round(sem));\n return new Report(type, semScaled, 0, DURATION_SCALE);\n }\n\n case 'moe': {\n if (n < 2) return new Report(type, 0n, 0, DURATION_SCALE);\n let sum = 0n;\n for (const duration of durations) {\n sum += duration;\n }\n const mean = sum / BigInt(n);\n let sumSquaredDiff = 0n;\n for (const duration of durations) {\n const diff = duration - mean;\n sumSquaredDiff += diff * diff;\n }\n const variance = Number(sumSquaredDiff) / (n - 1);\n const sd = Math.sqrt(variance);\n const sem = sd / Math.sqrt(n);\n const moe = Z95 * sem;\n const moeScaled = BigInt(Math.round(moe));\n return new Report(type, moeScaled, 0, DURATION_SCALE);\n }\n\n case 'rme': {\n if (n < 2) return new Report(type, 0n);\n let sum = 0n;\n for (const duration of durations) {\n sum += duration;\n }\n const mean = Number(sum) / n;\n if (mean === 0) return new Report(type, 0n);\n let sumSquaredDiff = 0;\n for (const duration of durations) {\n const diff = Number(duration) - mean;\n sumSquaredDiff += diff * diff;\n }\n const variance = sumSquaredDiff / (n - 1);\n const sd = Math.sqrt(variance);\n const sem = sd / Math.sqrt(n);\n const moe = Z95 * sem;\n const rme = (moe / mean) * 100;\n const rmeScaled = BigInt(Math.round(rme * 100));\n return new Report(type, rmeScaled, 0, 100n);\n }\n\n case 'mad': {\n const medianIdx = Math.floor(n / 2);\n const median = n % 2 === 1 ? durations[medianIdx] : (durations[medianIdx - 1] + durations[medianIdx]) / 2n;\n const deviations = new BigUint64Array(n);\n for (let i = 0; i < n; i++) {\n const diff = durations[i] > median ? durations[i] - median : median - durations[i];\n deviations[i] = diff;\n }\n deviations.sort();\n const madIdx = Math.floor(n / 2);\n const mad = n % 2 === 1 ? deviations[madIdx] : (deviations[madIdx - 1] + deviations[madIdx]) / 2n;\n return new Report(type, mad, 0, DURATION_SCALE);\n }\n\n case 'iqr': {\n const q1Idx = Math.floor(n * 0.25);\n const q3Idx = Math.floor(n * 0.75);\n const q1 = durations[q1Idx];\n const q3 = durations[q3Idx];\n const iqr = q3 - q1;\n return new Report(type, iqr, 0, DURATION_SCALE);\n }\n\n case 'ci_lower': {\n if (n < 2) return new Report(type, 0n, 0, DURATION_SCALE);\n let sum = 0n;\n for (const duration of durations) {\n sum += duration;\n }\n const mean = Number(sum) / n;\n let sumSquaredDiff = 0;\n for (const duration of durations) {\n const diff = Number(duration) - mean;\n sumSquaredDiff += diff * diff;\n }\n const variance = sumSquaredDiff / (n - 1);\n const sd = Math.sqrt(variance);\n const sem = sd / Math.sqrt(n);\n const moe = Z95 * sem;\n const ciLower = Math.max(0, mean - moe);\n return new Report(type, BigInt(Math.round(ciLower)), 0, DURATION_SCALE);\n }\n\n case 'ci_upper': {\n if (n < 2) return new Report(type, 0n, 0, DURATION_SCALE);\n let sum = 0n;\n for (const duration of durations) {\n sum += duration;\n }\n const mean = Number(sum) / n;\n let sumSquaredDiff = 0;\n for (const duration of durations) {\n const diff = Number(duration) - mean;\n sumSquaredDiff += diff * diff;\n }\n const variance = sumSquaredDiff / (n - 1);\n const sd = Math.sqrt(variance);\n const sem = sd / Math.sqrt(n);\n const moe = Z95 * sem;\n const ciUpper = mean + moe;\n return new Report(type, BigInt(Math.round(ciUpper)), 0, DURATION_SCALE);\n }\n\n default: {\n const p = Number(type.slice(1));\n if (p === 0) {\n return new Report(type, durations[0], 0, DURATION_SCALE);\n }\n if (p === 100) {\n return new Report(type, durations[n - 1], 0, DURATION_SCALE);\n }\n const idx = Math.ceil((p / 100) * n) - 1;\n const value = durations[Math.min(Math.max(idx, 0), n - 1)];\n const prev = idx > 0 ? durations[idx - 1] : value;\n const next = idx < n - 1 ? durations[idx + 1] : value;\n const gap = max(value - prev, next - value);\n const uncertainty = value > 0 ? Number(div(divs(gap, 2n, 100_00n), value)) / 100 : 0;\n\n return new Report(type, value, uncertainty, DURATION_SCALE);\n }\n }\n};\n"],"names":["Report","createReport","units","unit","factor","smartFixed","n","toLocaleString","undefined","minimumFractionDigits","maximumFractionDigits","useGrouping","type","value","uncertainty","scale","valueOf","Number","div","toString","display","varianceUnits","u","candidate","durations","length","DURATION_SCALE","mid","Math","floor","med","freq","Map","maxCount","modeVal","d","count","get","set","lower","upper","firstIdx","indexOf","lastIdx","lastIndexOf","gap","max","sum","duration","avgScaled","BigInt","nsPerSecScaled","raw","extra","ceil","log10","exp","deviation","divs","mean","sumSquaredDiff","diff","variance","sd","sqrt","sdScaled","round","sem","semScaled","moe","Z95","moeScaled","rme","rmeScaled","medianIdx","median","deviations","BigUint64Array","i","sort","madIdx","mad","q1Idx","q3Idx","q1","q3","iqr","ciLower","ciUpper","p","slice","idx","min","prev","next"],"mappings":"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"}
|
package/build/reporter.js
CHANGED
|
@@ -260,6 +260,69 @@ export const createReport = (durations, type)=>{
|
|
|
260
260
|
const rmeScaled = BigInt(Math.round(rme * 100));
|
|
261
261
|
return new Report(type, rmeScaled, 0, 100n);
|
|
262
262
|
}
|
|
263
|
+
case 'mad':
|
|
264
|
+
{
|
|
265
|
+
const medianIdx = Math.floor(n / 2);
|
|
266
|
+
const median = n % 2 === 1 ? durations[medianIdx] : (durations[medianIdx - 1] + durations[medianIdx]) / 2n;
|
|
267
|
+
const deviations = new BigUint64Array(n);
|
|
268
|
+
for(let i = 0; i < n; i++){
|
|
269
|
+
const diff = durations[i] > median ? durations[i] - median : median - durations[i];
|
|
270
|
+
deviations[i] = diff;
|
|
271
|
+
}
|
|
272
|
+
deviations.sort();
|
|
273
|
+
const madIdx = Math.floor(n / 2);
|
|
274
|
+
const mad = n % 2 === 1 ? deviations[madIdx] : (deviations[madIdx - 1] + deviations[madIdx]) / 2n;
|
|
275
|
+
return new Report(type, mad, 0, DURATION_SCALE);
|
|
276
|
+
}
|
|
277
|
+
case 'iqr':
|
|
278
|
+
{
|
|
279
|
+
const q1Idx = Math.floor(n * 0.25);
|
|
280
|
+
const q3Idx = Math.floor(n * 0.75);
|
|
281
|
+
const q1 = durations[q1Idx];
|
|
282
|
+
const q3 = durations[q3Idx];
|
|
283
|
+
const iqr = q3 - q1;
|
|
284
|
+
return new Report(type, iqr, 0, DURATION_SCALE);
|
|
285
|
+
}
|
|
286
|
+
case 'ci_lower':
|
|
287
|
+
{
|
|
288
|
+
if (n < 2) return new Report(type, 0n, 0, DURATION_SCALE);
|
|
289
|
+
let sum = 0n;
|
|
290
|
+
for (const duration of durations){
|
|
291
|
+
sum += duration;
|
|
292
|
+
}
|
|
293
|
+
const mean = Number(sum) / n;
|
|
294
|
+
let sumSquaredDiff = 0;
|
|
295
|
+
for (const duration of durations){
|
|
296
|
+
const diff = Number(duration) - mean;
|
|
297
|
+
sumSquaredDiff += diff * diff;
|
|
298
|
+
}
|
|
299
|
+
const variance = sumSquaredDiff / (n - 1);
|
|
300
|
+
const sd = Math.sqrt(variance);
|
|
301
|
+
const sem = sd / Math.sqrt(n);
|
|
302
|
+
const moe = Z95 * sem;
|
|
303
|
+
const ciLower = Math.max(0, mean - moe);
|
|
304
|
+
return new Report(type, BigInt(Math.round(ciLower)), 0, DURATION_SCALE);
|
|
305
|
+
}
|
|
306
|
+
case 'ci_upper':
|
|
307
|
+
{
|
|
308
|
+
if (n < 2) return new Report(type, 0n, 0, DURATION_SCALE);
|
|
309
|
+
let sum = 0n;
|
|
310
|
+
for (const duration of durations){
|
|
311
|
+
sum += duration;
|
|
312
|
+
}
|
|
313
|
+
const mean = Number(sum) / n;
|
|
314
|
+
let sumSquaredDiff = 0;
|
|
315
|
+
for (const duration of durations){
|
|
316
|
+
const diff = Number(duration) - mean;
|
|
317
|
+
sumSquaredDiff += diff * diff;
|
|
318
|
+
}
|
|
319
|
+
const variance = sumSquaredDiff / (n - 1);
|
|
320
|
+
const sd = Math.sqrt(variance);
|
|
321
|
+
const sem = sd / Math.sqrt(n);
|
|
322
|
+
const moe = Z95 * sem;
|
|
323
|
+
const ciUpper = mean + moe;
|
|
324
|
+
return new Report(type, BigInt(Math.round(ciUpper)), 0, DURATION_SCALE);
|
|
325
|
+
}
|
|
263
326
|
default:
|
|
264
327
|
{
|
|
265
328
|
const p = Number(type.slice(1));
|
package/build/reporter.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/reporter.ts"],"sourcesContent":["import { div, max, divs } from './utils.js';\nimport { ReportType, DURATION_SCALE, Z95 } from './types.js';\n\nconst units = [\n { unit: 'ns', factor: 1 },\n { unit: 'µs', factor: 1e3 },\n { unit: 'ms', factor: 1e6 },\n { unit: 's', factor: 1e9 },\n { unit: 'm', factor: 60 * 1e9 },\n { unit: 'h', factor: 3600 * 1e9 },\n] as const;\n\nfunction smartFixed(n: number): string {\n return n.toLocaleString(undefined, {\n minimumFractionDigits: 0,\n maximumFractionDigits: 2,\n useGrouping: true,\n });\n}\nexport class Report {\n constructor(\n public readonly type: ReportType,\n public readonly value: bigint,\n public readonly uncertainty: number = 0,\n public readonly scale: bigint = 1n,\n ) {}\n valueOf() {\n return Number(div(this.value, this.scale));\n }\n toString() {\n const uncertainty = this.uncertainty ? ` ± ${smartFixed(this.uncertainty)}%` : '';\n\n const value = this.valueOf();\n if (this.type === 'ops') {\n return `${smartFixed(value)} ops/s${uncertainty}`;\n }\n if (this.type === 'rme') {\n return `${smartFixed(value)}%`;\n }\n if (this.type === 'variance') {\n let display = value;\n let unit = 'ns²';\n const varianceUnits = [\n { unit: 'ns²', factor: 1 },\n { unit: 'µs²', factor: 1e6 },\n { unit: 'ms²', factor: 1e12 },\n ];\n for (const { unit: u, factor } of varianceUnits) {\n const candidate = value / factor;\n if (candidate < 1000) {\n display = candidate;\n unit = u;\n break;\n }\n }\n return `${smartFixed(display)} ${unit}`;\n }\n let display = value;\n let unit = 'ns';\n\n for (const { unit: u, factor } of units) {\n const candidate = value / factor;\n if (candidate < 1000) {\n display = candidate;\n unit = u;\n break;\n }\n }\n return `${smartFixed(display)} ${unit}${uncertainty}`;\n }\n}\n\nexport const createReport = (durations: BigUint64Array, type: ReportType): Report => {\n const n = durations.length;\n if (n === 0) {\n return new Report(type, 0n);\n }\n switch (type) {\n case 'min': {\n return new Report(type, durations[0], 0, DURATION_SCALE);\n }\n case 'max': {\n return new Report(type, durations[n - 1], 0, DURATION_SCALE);\n }\n case 'median': {\n const mid = Math.floor(n / 2);\n const med = n % 2 === 0 ? (durations[mid - 1] + durations[mid]) / 2n : durations[mid];\n return new Report(type, med, 0, DURATION_SCALE);\n }\n\n case 'mode': {\n const freq = new Map<bigint, bigint>();\n let maxCount = 0n;\n let modeVal = durations[0];\n for (const d of durations) {\n const count = (freq.get(d) || 0n) + 1n;\n freq.set(d, count);\n if (count > maxCount) {\n maxCount = count;\n modeVal = d;\n }\n }\n let lower = modeVal;\n let upper = modeVal;\n const firstIdx = durations.indexOf(modeVal);\n const lastIdx = durations.lastIndexOf(modeVal);\n if (firstIdx > 0) lower = durations[firstIdx - 1];\n if (lastIdx < n - 1) upper = durations[lastIdx + 1];\n const gap = max(modeVal - lower, upper - modeVal);\n const uncertainty = modeVal > 0 ? Number(((gap / 2n) * 100n) / modeVal) : 0;\n return new Report(type, modeVal, uncertainty, DURATION_SCALE);\n }\n\n case 'ops': {\n let sum = 0n;\n for (const duration of durations) {\n sum += duration;\n }\n const avgScaled = sum / BigInt(n);\n const nsPerSecScaled = 1_000_000_000n * DURATION_SCALE;\n const raw = Number(nsPerSecScaled) / Number(avgScaled);\n const extra = raw < 1 ? Math.ceil(-Math.log10(raw)) : 0;\n\n const exp = raw > 100 ? 0 : 2 + extra;\n\n const scale = 10n ** BigInt(exp);\n\n const value = avgScaled > 0n ? (nsPerSecScaled * scale) / avgScaled : 0n;\n const deviation = durations[n - 1] - durations[0];\n const uncertainty = avgScaled > 0 ? Number(div(deviation * scale, 2n * avgScaled)) : 0;\n return new Report(type, value, uncertainty, scale);\n }\n case 'mean': {\n let sum = 0n;\n for (const duration of durations) {\n sum += duration;\n }\n const value = divs(sum, BigInt(n), 1n);\n return new Report(type, value, 0, DURATION_SCALE);\n }\n\n case 'variance': {\n if (n < 2) return new Report(type, 0n, 0, DURATION_SCALE * DURATION_SCALE);\n let sum = 0n;\n for (const duration of durations) {\n sum += duration;\n }\n const mean = sum / BigInt(n);\n let sumSquaredDiff = 0n;\n for (const duration of durations) {\n const diff = duration - mean;\n sumSquaredDiff += diff * diff;\n }\n const variance = sumSquaredDiff / BigInt(n - 1);\n return new Report(type, variance, 0, DURATION_SCALE * DURATION_SCALE);\n }\n\n case 'sd': {\n if (n < 2) return new Report(type, 0n, 0, DURATION_SCALE);\n let sum = 0n;\n for (const duration of durations) {\n sum += duration;\n }\n const mean = sum / BigInt(n);\n let sumSquaredDiff = 0n;\n for (const duration of durations) {\n const diff = duration - mean;\n sumSquaredDiff += diff * diff;\n }\n const variance = Number(sumSquaredDiff) / (n - 1);\n const sd = Math.sqrt(variance);\n const sdScaled = BigInt(Math.round(sd));\n return new Report(type, sdScaled, 0, DURATION_SCALE);\n }\n\n case 'sem': {\n if (n < 2) return new Report(type, 0n, 0, DURATION_SCALE);\n let sum = 0n;\n for (const duration of durations) {\n sum += duration;\n }\n const mean = sum / BigInt(n);\n let sumSquaredDiff = 0n;\n for (const duration of durations) {\n const diff = duration - mean;\n sumSquaredDiff += diff * diff;\n }\n const variance = Number(sumSquaredDiff) / (n - 1);\n const sd = Math.sqrt(variance);\n const sem = sd / Math.sqrt(n);\n const semScaled = BigInt(Math.round(sem));\n return new Report(type, semScaled, 0, DURATION_SCALE);\n }\n\n case 'moe': {\n if (n < 2) return new Report(type, 0n, 0, DURATION_SCALE);\n let sum = 0n;\n for (const duration of durations) {\n sum += duration;\n }\n const mean = sum / BigInt(n);\n let sumSquaredDiff = 0n;\n for (const duration of durations) {\n const diff = duration - mean;\n sumSquaredDiff += diff * diff;\n }\n const variance = Number(sumSquaredDiff) / (n - 1);\n const sd = Math.sqrt(variance);\n const sem = sd / Math.sqrt(n);\n const moe = Z95 * sem;\n const moeScaled = BigInt(Math.round(moe));\n return new Report(type, moeScaled, 0, DURATION_SCALE);\n }\n\n case 'rme': {\n if (n < 2) return new Report(type, 0n);\n let sum = 0n;\n for (const duration of durations) {\n sum += duration;\n }\n const mean = Number(sum) / n;\n if (mean === 0) return new Report(type, 0n);\n let sumSquaredDiff = 0;\n for (const duration of durations) {\n const diff = Number(duration) - mean;\n sumSquaredDiff += diff * diff;\n }\n const variance = sumSquaredDiff / (n - 1);\n const sd = Math.sqrt(variance);\n const sem = sd / Math.sqrt(n);\n const moe = Z95 * sem;\n const rme = (moe / mean) * 100;\n const rmeScaled = BigInt(Math.round(rme * 100));\n return new Report(type, rmeScaled, 0, 100n);\n }\n\n default: {\n const p = Number(type.slice(1));\n if (p === 0) {\n return new Report(type, durations[0], 0, DURATION_SCALE);\n }\n if (p === 100) {\n return new Report(type, durations[n - 1], 0, DURATION_SCALE);\n }\n const idx = Math.ceil((p / 100) * n) - 1;\n const value = durations[Math.min(Math.max(idx, 0), n - 1)];\n const prev = idx > 0 ? durations[idx - 1] : value;\n const next = idx < n - 1 ? durations[idx + 1] : value;\n const gap = max(value - prev, next - value);\n const uncertainty = value > 0 ? Number(div(divs(gap, 2n, 100_00n), value)) / 100 : 0;\n\n return new Report(type, value, uncertainty, DURATION_SCALE);\n }\n }\n};\n"],"names":["div","max","divs","DURATION_SCALE","Z95","units","unit","factor","smartFixed","n","toLocaleString","undefined","minimumFractionDigits","maximumFractionDigits","useGrouping","Report","type","value","uncertainty","scale","valueOf","Number","toString","display","varianceUnits","u","candidate","createReport","durations","length","mid","Math","floor","med","freq","Map","maxCount","modeVal","d","count","get","set","lower","upper","firstIdx","indexOf","lastIdx","lastIndexOf","gap","sum","duration","avgScaled","BigInt","nsPerSecScaled","raw","extra","ceil","log10","exp","deviation","mean","sumSquaredDiff","diff","variance","sd","sqrt","sdScaled","round","sem","semScaled","moe","moeScaled","rme","rmeScaled","p","slice","idx","min","prev","next"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../src/reporter.ts"],"sourcesContent":["import { div, max, divs } from './utils.js';\nimport { ReportType, DURATION_SCALE, Z95 } from './types.js';\n\nconst units = [\n { unit: 'ns', factor: 1 },\n { unit: 'µs', factor: 1e3 },\n { unit: 'ms', factor: 1e6 },\n { unit: 's', factor: 1e9 },\n { unit: 'm', factor: 60 * 1e9 },\n { unit: 'h', factor: 3600 * 1e9 },\n] as const;\n\nfunction smartFixed(n: number): string {\n return n.toLocaleString(undefined, {\n minimumFractionDigits: 0,\n maximumFractionDigits: 2,\n useGrouping: true,\n });\n}\nexport class Report {\n constructor(\n public readonly type: ReportType,\n public readonly value: bigint,\n public readonly uncertainty: number = 0,\n public readonly scale: bigint = 1n,\n ) {}\n valueOf() {\n return Number(div(this.value, this.scale));\n }\n toString() {\n const uncertainty = this.uncertainty ? ` ± ${smartFixed(this.uncertainty)}%` : '';\n\n const value = this.valueOf();\n if (this.type === 'ops') {\n return `${smartFixed(value)} ops/s${uncertainty}`;\n }\n if (this.type === 'rme') {\n return `${smartFixed(value)}%`;\n }\n if (this.type === 'variance') {\n let display = value;\n let unit = 'ns²';\n const varianceUnits = [\n { unit: 'ns²', factor: 1 },\n { unit: 'µs²', factor: 1e6 },\n { unit: 'ms²', factor: 1e12 },\n ];\n for (const { unit: u, factor } of varianceUnits) {\n const candidate = value / factor;\n if (candidate < 1000) {\n display = candidate;\n unit = u;\n break;\n }\n }\n return `${smartFixed(display)} ${unit}`;\n }\n let display = value;\n let unit = 'ns';\n\n for (const { unit: u, factor } of units) {\n const candidate = value / factor;\n if (candidate < 1000) {\n display = candidate;\n unit = u;\n break;\n }\n }\n return `${smartFixed(display)} ${unit}${uncertainty}`;\n }\n}\n\nexport const createReport = (durations: BigUint64Array, type: ReportType): Report => {\n const n = durations.length;\n if (n === 0) {\n return new Report(type, 0n);\n }\n switch (type) {\n case 'min': {\n return new Report(type, durations[0], 0, DURATION_SCALE);\n }\n case 'max': {\n return new Report(type, durations[n - 1], 0, DURATION_SCALE);\n }\n case 'median': {\n const mid = Math.floor(n / 2);\n const med = n % 2 === 0 ? (durations[mid - 1] + durations[mid]) / 2n : durations[mid];\n return new Report(type, med, 0, DURATION_SCALE);\n }\n\n case 'mode': {\n const freq = new Map<bigint, bigint>();\n let maxCount = 0n;\n let modeVal = durations[0];\n for (const d of durations) {\n const count = (freq.get(d) || 0n) + 1n;\n freq.set(d, count);\n if (count > maxCount) {\n maxCount = count;\n modeVal = d;\n }\n }\n let lower = modeVal;\n let upper = modeVal;\n const firstIdx = durations.indexOf(modeVal);\n const lastIdx = durations.lastIndexOf(modeVal);\n if (firstIdx > 0) lower = durations[firstIdx - 1];\n if (lastIdx < n - 1) upper = durations[lastIdx + 1];\n const gap = max(modeVal - lower, upper - modeVal);\n const uncertainty = modeVal > 0 ? Number(((gap / 2n) * 100n) / modeVal) : 0;\n return new Report(type, modeVal, uncertainty, DURATION_SCALE);\n }\n\n case 'ops': {\n let sum = 0n;\n for (const duration of durations) {\n sum += duration;\n }\n const avgScaled = sum / BigInt(n);\n const nsPerSecScaled = 1_000_000_000n * DURATION_SCALE;\n const raw = Number(nsPerSecScaled) / Number(avgScaled);\n const extra = raw < 1 ? Math.ceil(-Math.log10(raw)) : 0;\n\n const exp = raw > 100 ? 0 : 2 + extra;\n\n const scale = 10n ** BigInt(exp);\n\n const value = avgScaled > 0n ? (nsPerSecScaled * scale) / avgScaled : 0n;\n const deviation = durations[n - 1] - durations[0];\n const uncertainty = avgScaled > 0 ? Number(div(deviation * scale, 2n * avgScaled)) : 0;\n return new Report(type, value, uncertainty, scale);\n }\n case 'mean': {\n let sum = 0n;\n for (const duration of durations) {\n sum += duration;\n }\n const value = divs(sum, BigInt(n), 1n);\n return new Report(type, value, 0, DURATION_SCALE);\n }\n\n case 'variance': {\n if (n < 2) return new Report(type, 0n, 0, DURATION_SCALE * DURATION_SCALE);\n let sum = 0n;\n for (const duration of durations) {\n sum += duration;\n }\n const mean = sum / BigInt(n);\n let sumSquaredDiff = 0n;\n for (const duration of durations) {\n const diff = duration - mean;\n sumSquaredDiff += diff * diff;\n }\n const variance = sumSquaredDiff / BigInt(n - 1);\n return new Report(type, variance, 0, DURATION_SCALE * DURATION_SCALE);\n }\n\n case 'sd': {\n if (n < 2) return new Report(type, 0n, 0, DURATION_SCALE);\n let sum = 0n;\n for (const duration of durations) {\n sum += duration;\n }\n const mean = sum / BigInt(n);\n let sumSquaredDiff = 0n;\n for (const duration of durations) {\n const diff = duration - mean;\n sumSquaredDiff += diff * diff;\n }\n const variance = Number(sumSquaredDiff) / (n - 1);\n const sd = Math.sqrt(variance);\n const sdScaled = BigInt(Math.round(sd));\n return new Report(type, sdScaled, 0, DURATION_SCALE);\n }\n\n case 'sem': {\n if (n < 2) return new Report(type, 0n, 0, DURATION_SCALE);\n let sum = 0n;\n for (const duration of durations) {\n sum += duration;\n }\n const mean = sum / BigInt(n);\n let sumSquaredDiff = 0n;\n for (const duration of durations) {\n const diff = duration - mean;\n sumSquaredDiff += diff * diff;\n }\n const variance = Number(sumSquaredDiff) / (n - 1);\n const sd = Math.sqrt(variance);\n const sem = sd / Math.sqrt(n);\n const semScaled = BigInt(Math.round(sem));\n return new Report(type, semScaled, 0, DURATION_SCALE);\n }\n\n case 'moe': {\n if (n < 2) return new Report(type, 0n, 0, DURATION_SCALE);\n let sum = 0n;\n for (const duration of durations) {\n sum += duration;\n }\n const mean = sum / BigInt(n);\n let sumSquaredDiff = 0n;\n for (const duration of durations) {\n const diff = duration - mean;\n sumSquaredDiff += diff * diff;\n }\n const variance = Number(sumSquaredDiff) / (n - 1);\n const sd = Math.sqrt(variance);\n const sem = sd / Math.sqrt(n);\n const moe = Z95 * sem;\n const moeScaled = BigInt(Math.round(moe));\n return new Report(type, moeScaled, 0, DURATION_SCALE);\n }\n\n case 'rme': {\n if (n < 2) return new Report(type, 0n);\n let sum = 0n;\n for (const duration of durations) {\n sum += duration;\n }\n const mean = Number(sum) / n;\n if (mean === 0) return new Report(type, 0n);\n let sumSquaredDiff = 0;\n for (const duration of durations) {\n const diff = Number(duration) - mean;\n sumSquaredDiff += diff * diff;\n }\n const variance = sumSquaredDiff / (n - 1);\n const sd = Math.sqrt(variance);\n const sem = sd / Math.sqrt(n);\n const moe = Z95 * sem;\n const rme = (moe / mean) * 100;\n const rmeScaled = BigInt(Math.round(rme * 100));\n return new Report(type, rmeScaled, 0, 100n);\n }\n\n case 'mad': {\n const medianIdx = Math.floor(n / 2);\n const median = n % 2 === 1 ? durations[medianIdx] : (durations[medianIdx - 1] + durations[medianIdx]) / 2n;\n const deviations = new BigUint64Array(n);\n for (let i = 0; i < n; i++) {\n const diff = durations[i] > median ? durations[i] - median : median - durations[i];\n deviations[i] = diff;\n }\n deviations.sort();\n const madIdx = Math.floor(n / 2);\n const mad = n % 2 === 1 ? deviations[madIdx] : (deviations[madIdx - 1] + deviations[madIdx]) / 2n;\n return new Report(type, mad, 0, DURATION_SCALE);\n }\n\n case 'iqr': {\n const q1Idx = Math.floor(n * 0.25);\n const q3Idx = Math.floor(n * 0.75);\n const q1 = durations[q1Idx];\n const q3 = durations[q3Idx];\n const iqr = q3 - q1;\n return new Report(type, iqr, 0, DURATION_SCALE);\n }\n\n case 'ci_lower': {\n if (n < 2) return new Report(type, 0n, 0, DURATION_SCALE);\n let sum = 0n;\n for (const duration of durations) {\n sum += duration;\n }\n const mean = Number(sum) / n;\n let sumSquaredDiff = 0;\n for (const duration of durations) {\n const diff = Number(duration) - mean;\n sumSquaredDiff += diff * diff;\n }\n const variance = sumSquaredDiff / (n - 1);\n const sd = Math.sqrt(variance);\n const sem = sd / Math.sqrt(n);\n const moe = Z95 * sem;\n const ciLower = Math.max(0, mean - moe);\n return new Report(type, BigInt(Math.round(ciLower)), 0, DURATION_SCALE);\n }\n\n case 'ci_upper': {\n if (n < 2) return new Report(type, 0n, 0, DURATION_SCALE);\n let sum = 0n;\n for (const duration of durations) {\n sum += duration;\n }\n const mean = Number(sum) / n;\n let sumSquaredDiff = 0;\n for (const duration of durations) {\n const diff = Number(duration) - mean;\n sumSquaredDiff += diff * diff;\n }\n const variance = sumSquaredDiff / (n - 1);\n const sd = Math.sqrt(variance);\n const sem = sd / Math.sqrt(n);\n const moe = Z95 * sem;\n const ciUpper = mean + moe;\n return new Report(type, BigInt(Math.round(ciUpper)), 0, DURATION_SCALE);\n }\n\n default: {\n const p = Number(type.slice(1));\n if (p === 0) {\n return new Report(type, durations[0], 0, DURATION_SCALE);\n }\n if (p === 100) {\n return new Report(type, durations[n - 1], 0, DURATION_SCALE);\n }\n const idx = Math.ceil((p / 100) * n) - 1;\n const value = durations[Math.min(Math.max(idx, 0), n - 1)];\n const prev = idx > 0 ? durations[idx - 1] : value;\n const next = idx < n - 1 ? durations[idx + 1] : value;\n const gap = max(value - prev, next - value);\n const uncertainty = value > 0 ? Number(div(divs(gap, 2n, 100_00n), value)) / 100 : 0;\n\n return new Report(type, value, uncertainty, DURATION_SCALE);\n }\n }\n};\n"],"names":["div","max","divs","DURATION_SCALE","Z95","units","unit","factor","smartFixed","n","toLocaleString","undefined","minimumFractionDigits","maximumFractionDigits","useGrouping","Report","type","value","uncertainty","scale","valueOf","Number","toString","display","varianceUnits","u","candidate","createReport","durations","length","mid","Math","floor","med","freq","Map","maxCount","modeVal","d","count","get","set","lower","upper","firstIdx","indexOf","lastIdx","lastIndexOf","gap","sum","duration","avgScaled","BigInt","nsPerSecScaled","raw","extra","ceil","log10","exp","deviation","mean","sumSquaredDiff","diff","variance","sd","sqrt","sdScaled","round","sem","semScaled","moe","moeScaled","rme","rmeScaled","medianIdx","median","deviations","BigUint64Array","i","sort","madIdx","mad","q1Idx","q3Idx","q1","q3","iqr","ciLower","ciUpper","p","slice","idx","min","prev","next"],"mappings":"AAAA,SAASA,GAAG,EAAEC,GAAG,EAAEC,IAAI,QAAQ,aAAa;AAC5C,SAAqBC,cAAc,EAAEC,GAAG,QAAQ,aAAa;AAE7D,MAAMC,QAAQ;IACZ;QAAEC,MAAM;QAAMC,QAAQ;IAAE;IACxB;QAAED,MAAM;QAAMC,QAAQ;IAAI;IAC1B;QAAED,MAAM;QAAMC,QAAQ;IAAI;IAC1B;QAAED,MAAM;QAAKC,QAAQ;IAAI;IACzB;QAAED,MAAM;QAAKC,QAAQ,KAAK;IAAI;IAC9B;QAAED,MAAM;QAAKC,QAAQ,OAAO;IAAI;CACjC;AAED,SAASC,WAAWC,CAAS;IAC3B,OAAOA,EAAEC,cAAc,CAACC,WAAW;QACjCC,uBAAuB;QACvBC,uBAAuB;QACvBC,aAAa;IACf;AACF;AACA,OAAO,MAAMC;;;;;IACX,YACE,AAAgBC,IAAgB,EAChC,AAAgBC,KAAa,EAC7B,AAAgBC,cAAsB,CAAC,EACvC,AAAgBC,QAAgB,EAAE,CAClC;aAJgBH,OAAAA;aACAC,QAAAA;aACAC,cAAAA;aACAC,QAAAA;IACf;IACHC,UAAU;QACR,OAAOC,OAAOrB,IAAI,IAAI,CAACiB,KAAK,EAAE,IAAI,CAACE,KAAK;IAC1C;IACAG,WAAW;QACT,MAAMJ,cAAc,IAAI,CAACA,WAAW,GAAG,CAAC,GAAG,EAAEV,WAAW,IAAI,CAACU,WAAW,EAAE,CAAC,CAAC,GAAG;QAE/E,MAAMD,QAAQ,IAAI,CAACG,OAAO;QAC1B,IAAI,IAAI,CAACJ,IAAI,KAAK,OAAO;YACvB,OAAO,GAAGR,WAAWS,OAAO,MAAM,EAAEC,aAAa;QACnD;QACA,IAAI,IAAI,CAACF,IAAI,KAAK,OAAO;YACvB,OAAO,GAAGR,WAAWS,OAAO,CAAC,CAAC;QAChC;QACA,IAAI,IAAI,CAACD,IAAI,KAAK,YAAY;YAC5B,IAAIO,UAAUN;YACd,IAAIX,OAAO;YACX,MAAMkB,gBAAgB;gBACpB;oBAAElB,MAAM;oBAAOC,QAAQ;gBAAE;gBACzB;oBAAED,MAAM;oBAAOC,QAAQ;gBAAI;gBAC3B;oBAAED,MAAM;oBAAOC,QAAQ;gBAAK;aAC7B;YACD,KAAK,MAAM,EAAED,MAAMmB,CAAC,EAAElB,MAAM,EAAE,IAAIiB,cAAe;gBAC/C,MAAME,YAAYT,QAAQV;gBAC1B,IAAImB,YAAY,MAAM;oBACpBH,UAAUG;oBACVpB,OAAOmB;oBACP;gBACF;YACF;YACA,OAAO,GAAGjB,WAAWe,SAAS,CAAC,EAAEjB,MAAM;QACzC;QACA,IAAIiB,UAAUN;QACd,IAAIX,OAAO;QAEX,KAAK,MAAM,EAAEA,MAAMmB,CAAC,EAAElB,MAAM,EAAE,IAAIF,MAAO;YACvC,MAAMqB,YAAYT,QAAQV;YAC1B,IAAImB,YAAY,MAAM;gBACpBH,UAAUG;gBACVpB,OAAOmB;gBACP;YACF;QACF;QACA,OAAO,GAAGjB,WAAWe,SAAS,CAAC,EAAEjB,OAAOY,aAAa;IACvD;AACF;AAEA,OAAO,MAAMS,eAAe,CAACC,WAA2BZ;IACtD,MAAMP,IAAImB,UAAUC,MAAM;IAC1B,IAAIpB,MAAM,GAAG;QACX,OAAO,IAAIM,OAAOC,MAAM,EAAE;IAC5B;IACA,OAAQA;QACN,KAAK;YAAO;gBACV,OAAO,IAAID,OAAOC,MAAMY,SAAS,CAAC,EAAE,EAAE,GAAGzB;YAC3C;QACA,KAAK;YAAO;gBACV,OAAO,IAAIY,OAAOC,MAAMY,SAAS,CAACnB,IAAI,EAAE,EAAE,GAAGN;YAC/C;QACA,KAAK;YAAU;gBACb,MAAM2B,MAAMC,KAAKC,KAAK,CAACvB,IAAI;gBAC3B,MAAMwB,MAAMxB,IAAI,MAAM,IAAI,AAACmB,CAAAA,SAAS,CAACE,MAAM,EAAE,GAAGF,SAAS,CAACE,IAAI,AAAD,IAAK,EAAE,GAAGF,SAAS,CAACE,IAAI;gBACrF,OAAO,IAAIf,OAAOC,MAAMiB,KAAK,GAAG9B;YAClC;QAEA,KAAK;YAAQ;gBACX,MAAM+B,OAAO,IAAIC;gBACjB,IAAIC,WAAW,EAAE;gBACjB,IAAIC,UAAUT,SAAS,CAAC,EAAE;gBAC1B,KAAK,MAAMU,KAAKV,UAAW;oBACzB,MAAMW,QAAQ,AAACL,CAAAA,KAAKM,GAAG,CAACF,MAAM,EAAE,AAAD,IAAK,EAAE;oBACtCJ,KAAKO,GAAG,CAACH,GAAGC;oBACZ,IAAIA,QAAQH,UAAU;wBACpBA,WAAWG;wBACXF,UAAUC;oBACZ;gBACF;gBACA,IAAII,QAAQL;gBACZ,IAAIM,QAAQN;gBACZ,MAAMO,WAAWhB,UAAUiB,OAAO,CAACR;gBACnC,MAAMS,UAAUlB,UAAUmB,WAAW,CAACV;gBACtC,IAAIO,WAAW,GAAGF,QAAQd,SAAS,CAACgB,WAAW,EAAE;gBACjD,IAAIE,UAAUrC,IAAI,GAAGkC,QAAQf,SAAS,CAACkB,UAAU,EAAE;gBACnD,MAAME,MAAM/C,IAAIoC,UAAUK,OAAOC,QAAQN;gBACzC,MAAMnB,cAAcmB,UAAU,IAAIhB,OAAO,AAAE2B,MAAM,EAAE,GAAI,IAAI,GAAIX,WAAW;gBAC1E,OAAO,IAAItB,OAAOC,MAAMqB,SAASnB,aAAaf;YAChD;QAEA,KAAK;YAAO;gBACV,IAAI8C,MAAM,EAAE;gBACZ,KAAK,MAAMC,YAAYtB,UAAW;oBAChCqB,OAAOC;gBACT;gBACA,MAAMC,YAAYF,MAAMG,OAAO3C;gBAC/B,MAAM4C,iBAAiB,cAAc,GAAGlD;gBACxC,MAAMmD,MAAMjC,OAAOgC,kBAAkBhC,OAAO8B;gBAC5C,MAAMI,QAAQD,MAAM,IAAIvB,KAAKyB,IAAI,CAAC,CAACzB,KAAK0B,KAAK,CAACH,QAAQ;gBAEtD,MAAMI,MAAMJ,MAAM,MAAM,IAAI,IAAIC;gBAEhC,MAAMpC,QAAQ,GAAG,IAAIiC,OAAOM;gBAE5B,MAAMzC,QAAQkC,YAAY,EAAE,GAAG,AAACE,iBAAiBlC,QAASgC,YAAY,EAAE;gBACxE,MAAMQ,YAAY/B,SAAS,CAACnB,IAAI,EAAE,GAAGmB,SAAS,CAAC,EAAE;gBACjD,MAAMV,cAAciC,YAAY,IAAI9B,OAAOrB,IAAI2D,YAAYxC,OAAO,EAAE,GAAGgC,cAAc;gBACrF,OAAO,IAAIpC,OAAOC,MAAMC,OAAOC,aAAaC;YAC9C;QACA,KAAK;YAAQ;gBACX,IAAI8B,MAAM,EAAE;gBACZ,KAAK,MAAMC,YAAYtB,UAAW;oBAChCqB,OAAOC;gBACT;gBACA,MAAMjC,QAAQf,KAAK+C,KAAKG,OAAO3C,IAAI,EAAE;gBACrC,OAAO,IAAIM,OAAOC,MAAMC,OAAO,GAAGd;YACpC;QAEA,KAAK;YAAY;gBACf,IAAIM,IAAI,GAAG,OAAO,IAAIM,OAAOC,MAAM,EAAE,EAAE,GAAGb,iBAAiBA;gBAC3D,IAAI8C,MAAM,EAAE;gBACZ,KAAK,MAAMC,YAAYtB,UAAW;oBAChCqB,OAAOC;gBACT;gBACA,MAAMU,OAAOX,MAAMG,OAAO3C;gBAC1B,IAAIoD,iBAAiB,EAAE;gBACvB,KAAK,MAAMX,YAAYtB,UAAW;oBAChC,MAAMkC,OAAOZ,WAAWU;oBACxBC,kBAAkBC,OAAOA;gBAC3B;gBACA,MAAMC,WAAWF,iBAAiBT,OAAO3C,IAAI;gBAC7C,OAAO,IAAIM,OAAOC,MAAM+C,UAAU,GAAG5D,iBAAiBA;YACxD;QAEA,KAAK;YAAM;gBACT,IAAIM,IAAI,GAAG,OAAO,IAAIM,OAAOC,MAAM,EAAE,EAAE,GAAGb;gBAC1C,IAAI8C,MAAM,EAAE;gBACZ,KAAK,MAAMC,YAAYtB,UAAW;oBAChCqB,OAAOC;gBACT;gBACA,MAAMU,OAAOX,MAAMG,OAAO3C;gBAC1B,IAAIoD,iBAAiB,EAAE;gBACvB,KAAK,MAAMX,YAAYtB,UAAW;oBAChC,MAAMkC,OAAOZ,WAAWU;oBACxBC,kBAAkBC,OAAOA;gBAC3B;gBACA,MAAMC,WAAW1C,OAAOwC,kBAAmBpD,CAAAA,IAAI,CAAA;gBAC/C,MAAMuD,KAAKjC,KAAKkC,IAAI,CAACF;gBACrB,MAAMG,WAAWd,OAAOrB,KAAKoC,KAAK,CAACH;gBACnC,OAAO,IAAIjD,OAAOC,MAAMkD,UAAU,GAAG/D;YACvC;QAEA,KAAK;YAAO;gBACV,IAAIM,IAAI,GAAG,OAAO,IAAIM,OAAOC,MAAM,EAAE,EAAE,GAAGb;gBAC1C,IAAI8C,MAAM,EAAE;gBACZ,KAAK,MAAMC,YAAYtB,UAAW;oBAChCqB,OAAOC;gBACT;gBACA,MAAMU,OAAOX,MAAMG,OAAO3C;gBAC1B,IAAIoD,iBAAiB,EAAE;gBACvB,KAAK,MAAMX,YAAYtB,UAAW;oBAChC,MAAMkC,OAAOZ,WAAWU;oBACxBC,kBAAkBC,OAAOA;gBAC3B;gBACA,MAAMC,WAAW1C,OAAOwC,kBAAmBpD,CAAAA,IAAI,CAAA;gBAC/C,MAAMuD,KAAKjC,KAAKkC,IAAI,CAACF;gBACrB,MAAMK,MAAMJ,KAAKjC,KAAKkC,IAAI,CAACxD;gBAC3B,MAAM4D,YAAYjB,OAAOrB,KAAKoC,KAAK,CAACC;gBACpC,OAAO,IAAIrD,OAAOC,MAAMqD,WAAW,GAAGlE;YACxC;QAEA,KAAK;YAAO;gBACV,IAAIM,IAAI,GAAG,OAAO,IAAIM,OAAOC,MAAM,EAAE,EAAE,GAAGb;gBAC1C,IAAI8C,MAAM,EAAE;gBACZ,KAAK,MAAMC,YAAYtB,UAAW;oBAChCqB,OAAOC;gBACT;gBACA,MAAMU,OAAOX,MAAMG,OAAO3C;gBAC1B,IAAIoD,iBAAiB,EAAE;gBACvB,KAAK,MAAMX,YAAYtB,UAAW;oBAChC,MAAMkC,OAAOZ,WAAWU;oBACxBC,kBAAkBC,OAAOA;gBAC3B;gBACA,MAAMC,WAAW1C,OAAOwC,kBAAmBpD,CAAAA,IAAI,CAAA;gBAC/C,MAAMuD,KAAKjC,KAAKkC,IAAI,CAACF;gBACrB,MAAMK,MAAMJ,KAAKjC,KAAKkC,IAAI,CAACxD;gBAC3B,MAAM6D,MAAMlE,MAAMgE;gBAClB,MAAMG,YAAYnB,OAAOrB,KAAKoC,KAAK,CAACG;gBACpC,OAAO,IAAIvD,OAAOC,MAAMuD,WAAW,GAAGpE;YACxC;QAEA,KAAK;YAAO;gBACV,IAAIM,IAAI,GAAG,OAAO,IAAIM,OAAOC,MAAM,EAAE;gBACrC,IAAIiC,MAAM,EAAE;gBACZ,KAAK,MAAMC,YAAYtB,UAAW;oBAChCqB,OAAOC;gBACT;gBACA,MAAMU,OAAOvC,OAAO4B,OAAOxC;gBAC3B,IAAImD,SAAS,GAAG,OAAO,IAAI7C,OAAOC,MAAM,EAAE;gBAC1C,IAAI6C,iBAAiB;gBACrB,KAAK,MAAMX,YAAYtB,UAAW;oBAChC,MAAMkC,OAAOzC,OAAO6B,YAAYU;oBAChCC,kBAAkBC,OAAOA;gBAC3B;gBACA,MAAMC,WAAWF,iBAAkBpD,CAAAA,IAAI,CAAA;gBACvC,MAAMuD,KAAKjC,KAAKkC,IAAI,CAACF;gBACrB,MAAMK,MAAMJ,KAAKjC,KAAKkC,IAAI,CAACxD;gBAC3B,MAAM6D,MAAMlE,MAAMgE;gBAClB,MAAMI,MAAM,AAACF,MAAMV,OAAQ;gBAC3B,MAAMa,YAAYrB,OAAOrB,KAAKoC,KAAK,CAACK,MAAM;gBAC1C,OAAO,IAAIzD,OAAOC,MAAMyD,WAAW,GAAG,IAAI;YAC5C;QAEA,KAAK;YAAO;gBACV,MAAMC,YAAY3C,KAAKC,KAAK,CAACvB,IAAI;gBACjC,MAAMkE,SAASlE,IAAI,MAAM,IAAImB,SAAS,CAAC8C,UAAU,GAAG,AAAC9C,CAAAA,SAAS,CAAC8C,YAAY,EAAE,GAAG9C,SAAS,CAAC8C,UAAU,AAAD,IAAK,EAAE;gBAC1G,MAAME,aAAa,IAAIC,eAAepE;gBACtC,IAAK,IAAIqE,IAAI,GAAGA,IAAIrE,GAAGqE,IAAK;oBAC1B,MAAMhB,OAAOlC,SAAS,CAACkD,EAAE,GAAGH,SAAS/C,SAAS,CAACkD,EAAE,GAAGH,SAASA,SAAS/C,SAAS,CAACkD,EAAE;oBAClFF,UAAU,CAACE,EAAE,GAAGhB;gBAClB;gBACAc,WAAWG,IAAI;gBACf,MAAMC,SAASjD,KAAKC,KAAK,CAACvB,IAAI;gBAC9B,MAAMwE,MAAMxE,IAAI,MAAM,IAAImE,UAAU,CAACI,OAAO,GAAG,AAACJ,CAAAA,UAAU,CAACI,SAAS,EAAE,GAAGJ,UAAU,CAACI,OAAO,AAAD,IAAK,EAAE;gBACjG,OAAO,IAAIjE,OAAOC,MAAMiE,KAAK,GAAG9E;YAClC;QAEA,KAAK;YAAO;gBACV,MAAM+E,QAAQnD,KAAKC,KAAK,CAACvB,IAAI;gBAC7B,MAAM0E,QAAQpD,KAAKC,KAAK,CAACvB,IAAI;gBAC7B,MAAM2E,KAAKxD,SAAS,CAACsD,MAAM;gBAC3B,MAAMG,KAAKzD,SAAS,CAACuD,MAAM;gBAC3B,MAAMG,MAAMD,KAAKD;gBACjB,OAAO,IAAIrE,OAAOC,MAAMsE,KAAK,GAAGnF;YAClC;QAEA,KAAK;YAAY;gBACf,IAAIM,IAAI,GAAG,OAAO,IAAIM,OAAOC,MAAM,EAAE,EAAE,GAAGb;gBAC1C,IAAI8C,MAAM,EAAE;gBACZ,KAAK,MAAMC,YAAYtB,UAAW;oBAChCqB,OAAOC;gBACT;gBACA,MAAMU,OAAOvC,OAAO4B,OAAOxC;gBAC3B,IAAIoD,iBAAiB;gBACrB,KAAK,MAAMX,YAAYtB,UAAW;oBAChC,MAAMkC,OAAOzC,OAAO6B,YAAYU;oBAChCC,kBAAkBC,OAAOA;gBAC3B;gBACA,MAAMC,WAAWF,iBAAkBpD,CAAAA,IAAI,CAAA;gBACvC,MAAMuD,KAAKjC,KAAKkC,IAAI,CAACF;gBACrB,MAAMK,MAAMJ,KAAKjC,KAAKkC,IAAI,CAACxD;gBAC3B,MAAM6D,MAAMlE,MAAMgE;gBAClB,MAAMmB,UAAUxD,KAAK9B,GAAG,CAAC,GAAG2D,OAAOU;gBACnC,OAAO,IAAIvD,OAAOC,MAAMoC,OAAOrB,KAAKoC,KAAK,CAACoB,WAAW,GAAGpF;YAC1D;QAEA,KAAK;YAAY;gBACf,IAAIM,IAAI,GAAG,OAAO,IAAIM,OAAOC,MAAM,EAAE,EAAE,GAAGb;gBAC1C,IAAI8C,MAAM,EAAE;gBACZ,KAAK,MAAMC,YAAYtB,UAAW;oBAChCqB,OAAOC;gBACT;gBACA,MAAMU,OAAOvC,OAAO4B,OAAOxC;gBAC3B,IAAIoD,iBAAiB;gBACrB,KAAK,MAAMX,YAAYtB,UAAW;oBAChC,MAAMkC,OAAOzC,OAAO6B,YAAYU;oBAChCC,kBAAkBC,OAAOA;gBAC3B;gBACA,MAAMC,WAAWF,iBAAkBpD,CAAAA,IAAI,CAAA;gBACvC,MAAMuD,KAAKjC,KAAKkC,IAAI,CAACF;gBACrB,MAAMK,MAAMJ,KAAKjC,KAAKkC,IAAI,CAACxD;gBAC3B,MAAM6D,MAAMlE,MAAMgE;gBAClB,MAAMoB,UAAU5B,OAAOU;gBACvB,OAAO,IAAIvD,OAAOC,MAAMoC,OAAOrB,KAAKoC,KAAK,CAACqB,WAAW,GAAGrF;YAC1D;QAEA;YAAS;gBACP,MAAMsF,IAAIpE,OAAOL,KAAK0E,KAAK,CAAC;gBAC5B,IAAID,MAAM,GAAG;oBACX,OAAO,IAAI1E,OAAOC,MAAMY,SAAS,CAAC,EAAE,EAAE,GAAGzB;gBAC3C;gBACA,IAAIsF,MAAM,KAAK;oBACb,OAAO,IAAI1E,OAAOC,MAAMY,SAAS,CAACnB,IAAI,EAAE,EAAE,GAAGN;gBAC/C;gBACA,MAAMwF,MAAM5D,KAAKyB,IAAI,CAAC,AAACiC,IAAI,MAAOhF,KAAK;gBACvC,MAAMQ,QAAQW,SAAS,CAACG,KAAK6D,GAAG,CAAC7D,KAAK9B,GAAG,CAAC0F,KAAK,IAAIlF,IAAI,GAAG;gBAC1D,MAAMoF,OAAOF,MAAM,IAAI/D,SAAS,CAAC+D,MAAM,EAAE,GAAG1E;gBAC5C,MAAM6E,OAAOH,MAAMlF,IAAI,IAAImB,SAAS,CAAC+D,MAAM,EAAE,GAAG1E;gBAChD,MAAM+B,MAAM/C,IAAIgB,QAAQ4E,MAAMC,OAAO7E;gBACrC,MAAMC,cAAcD,QAAQ,IAAII,OAAOrB,IAAIE,KAAK8C,KAAK,EAAE,EAAE,OAAO,GAAG/B,UAAU,MAAM;gBAEnF,OAAO,IAAIF,OAAOC,MAAMC,OAAOC,aAAaf;YAC9C;IACF;AACF,EAAE"}
|
package/build/runner.cjs
CHANGED
|
@@ -251,7 +251,9 @@ const benchmark = async ({ setup, teardown, pre, run: runRaw, post, data, warmup
|
|
|
251
251
|
control[_typescjs.Control.INDEX] = 0;
|
|
252
252
|
control[_typescjs.Control.PROGRESS] = 0;
|
|
253
253
|
control[_typescjs.Control.COMPLETE] = 255;
|
|
254
|
+
control[_typescjs.Control.HEAP_USED] = 0;
|
|
254
255
|
const context = await setup?.();
|
|
256
|
+
const heapBefore = process.memoryUsage().heapUsed;
|
|
255
257
|
const input = data;
|
|
256
258
|
const maxCycles = durations.length;
|
|
257
259
|
const gcWatcher = gcObserver ? new _gcwatchercjs.GCWatcher() : null;
|
|
@@ -292,18 +294,38 @@ const benchmark = async ({ setup, teardown, pre, run: runRaw, post, data, warmup
|
|
|
292
294
|
return nonce;
|
|
293
295
|
} : null;
|
|
294
296
|
if (!runIsAsync && !pre && !post) {
|
|
295
|
-
const
|
|
296
|
-
const
|
|
297
|
+
const PROBE_TIME_LIMIT_NS = 1_000_000_000n;
|
|
298
|
+
const INITIAL_PROBE_SIZE = 10;
|
|
299
|
+
const MAX_PROBE_SIZE = 10_000;
|
|
300
|
+
const initialStart = hr();
|
|
297
301
|
if (nextNonce) {
|
|
298
|
-
for(let i = 0; i <
|
|
302
|
+
for(let i = 0; i < INITIAL_PROBE_SIZE; i++){
|
|
299
303
|
consume(runRaw(context, input, nextNonce()));
|
|
300
304
|
}
|
|
301
305
|
} else {
|
|
302
|
-
for(let i = 0; i <
|
|
306
|
+
for(let i = 0; i < INITIAL_PROBE_SIZE; i++){
|
|
303
307
|
consume(runRaw(context, input));
|
|
304
308
|
}
|
|
305
309
|
}
|
|
306
|
-
|
|
310
|
+
const initialDuration = hr() - initialStart;
|
|
311
|
+
const estimatedPerOp = initialDuration / BigInt(INITIAL_PROBE_SIZE);
|
|
312
|
+
const remainingBudget = PROBE_TIME_LIMIT_NS - initialDuration;
|
|
313
|
+
const additionalIterations = estimatedPerOp > 0n ? Number(remainingBudget / estimatedPerOp) : MAX_PROBE_SIZE - INITIAL_PROBE_SIZE;
|
|
314
|
+
const cappedAdditional = Math.min(Math.max(0, additionalIterations), MAX_PROBE_SIZE - INITIAL_PROBE_SIZE);
|
|
315
|
+
let totalIterations = INITIAL_PROBE_SIZE;
|
|
316
|
+
if (cappedAdditional > 0) {
|
|
317
|
+
if (nextNonce) {
|
|
318
|
+
for(let i = 0; i < cappedAdditional; i++){
|
|
319
|
+
consume(runRaw(context, input, nextNonce()));
|
|
320
|
+
}
|
|
321
|
+
} else {
|
|
322
|
+
for(let i = 0; i < cappedAdditional; i++){
|
|
323
|
+
consume(runRaw(context, input));
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
totalIterations += cappedAdditional;
|
|
327
|
+
}
|
|
328
|
+
durationProbe = (hr() - initialStart) / BigInt(totalIterations);
|
|
307
329
|
}
|
|
308
330
|
const runTimedSync = runIsAsync ? null : runSync(runRaw, timerOverhead);
|
|
309
331
|
const runTimedAsync = runIsAsync ? runAsync(runRaw) : null;
|
|
@@ -486,6 +508,8 @@ const benchmark = async ({ setup, teardown, pre, run: runRaw, post, data, warmup
|
|
|
486
508
|
}
|
|
487
509
|
control[_typescjs.Control.INDEX] = i;
|
|
488
510
|
control[_typescjs.Control.COMPLETE] = 0;
|
|
511
|
+
const heapAfter = process.memoryUsage().heapUsed;
|
|
512
|
+
control[_typescjs.Control.HEAP_USED] = Math.max(0, Math.round((heapAfter - heapBefore) / 1024));
|
|
489
513
|
} catch (e) {
|
|
490
514
|
console.error(e && typeof e === 'object' && 'stack' in e ? e.stack : e);
|
|
491
515
|
control[_typescjs.Control.COMPLETE] = 1;
|