overtake 1.3.1 → 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/README.md +8 -0
  2. package/build/cli.cjs +6 -5
  3. package/build/cli.cjs.map +1 -1
  4. package/build/cli.js +6 -5
  5. package/build/cli.js.map +1 -1
  6. package/build/executor.cjs +12 -5
  7. package/build/executor.cjs.map +1 -1
  8. package/build/executor.d.ts +1 -0
  9. package/build/executor.js +13 -6
  10. package/build/executor.js.map +1 -1
  11. package/build/index.cjs +58 -16
  12. package/build/index.cjs.map +1 -1
  13. package/build/index.js +58 -16
  14. package/build/index.js.map +1 -1
  15. package/build/reporter.cjs +63 -116
  16. package/build/reporter.cjs.map +1 -1
  17. package/build/reporter.js +65 -118
  18. package/build/reporter.js.map +1 -1
  19. package/build/runner.cjs +23 -19
  20. package/build/runner.cjs.map +1 -1
  21. package/build/runner.js +23 -19
  22. package/build/runner.js.map +1 -1
  23. package/build/types.cjs +1 -1
  24. package/build/types.cjs.map +1 -1
  25. package/build/types.d.ts +1 -1
  26. package/build/types.js +1 -1
  27. package/build/types.js.map +1 -1
  28. package/build/utils.cjs +53 -0
  29. package/build/utils.cjs.map +1 -1
  30. package/build/utils.d.ts +2 -0
  31. package/build/utils.js +48 -1
  32. package/build/utils.js.map +1 -1
  33. package/build/worker.cjs +6 -8
  34. package/build/worker.cjs.map +1 -1
  35. package/build/worker.js +7 -9
  36. package/build/worker.js.map +1 -1
  37. package/package.json +8 -8
  38. package/src/__tests__/assert-no-closure.js +134 -0
  39. package/src/cli.ts +6 -5
  40. package/src/executor.ts +12 -7
  41. package/src/index.ts +50 -11
  42. package/src/reporter.ts +62 -118
  43. package/src/runner.ts +26 -20
  44. package/src/types.ts +1 -1
  45. package/src/utils.ts +56 -1
  46. package/src/worker.ts +7 -5
@@ -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 { 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":["AsyncFunction","Benchmark","DEFAULT_REPORT_TYPES","DEFAULT_WORKERS","FeedContext","Measure","MeasureContext","Target","TargetContext","printComparisonReports","printHistogramReports","printJSONReports","printMarkdownReports","printSimpleReports","printTableReports","reportsToBaseline","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","progress","progressInterval","Error","benchmarkUrl","totalBenchmarks","reduce","acc","t","progressMap","Map","completedBenchmarks","bar","Progress","total","width","complete","incomplete","onProgress","info","set","id","totalProgress","values","a","b","label","slice","update","undefined","executor","createExecutor","reports","targetReport","measureReport","feeds","data","then","delete","drain","kill","terminate","report","console","group","count","heapUsedKB","dceWarning","metrics","output","Object","entries","map","key","toString","join","extras","extrasStr","log","groupEnd","table","fromEntries","padding","row","JSON","stringify","keys","filter","k","header","separator","opsKey","f","value","valueOf","maxValue","Math","max","v","maxLabelLen","barLen","round","repeat","padEnd","formatted","toLocaleString","maximumFractionDigits","results","metric","version","timestamp","Date","toISOString","baseline","threshold","baselineData","current","baselineValue","change","isOps","improved","regressed","indicator","changeStr","toFixed","coloredChange"],"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 = Math.max(1, Math.ceil(cpus().length / 4));\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, error: benchError, ...metrics } = data as Record<string, unknown>;\n if (benchError) {\n console.log(feed, `\\x1b[31m[error: ${benchError}]\\x1b[0m`);\n continue;\n }\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 const { error: benchError } = data as Record<string, unknown>;\n if (benchError) {\n table[feed] = { error: benchError };\n } else {\n table[feed] = Object.fromEntries(Object.entries(data).map(([key, report]) => [key, report.toString()]));\n }\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 const { error: benchError } = data as Record<string, unknown>;\n if (benchError) {\n row[feed] = { error: String(benchError) };\n } else {\n row[feed] = Object.fromEntries(Object.entries(data).map(([key, report]) => [key, report.toString()]));\n }\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 firstValid = feeds.find((f) => !(f.data as Record<string, unknown>).error);\n if (!firstValid) {\n for (const { feed, data } of feeds) {\n console.log(`| ${feed} | error: ${(data as Record<string, unknown>).error} |`);\n }\n continue;\n }\n const keys = Object.keys(firstValid.data).filter((k) => k !== 'count' && k !== 'error');\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 if ((data as Record<string, unknown>).error) {\n console.log(`| ${feed} | error: ${(data as Record<string, unknown>).error} |`);\n continue;\n }\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 const { error: benchError } = f.data as Record<string, unknown>;\n return {\n feed: f.feed,\n value: benchError ? 0 : ((f.data as Record<string, { valueOf(): number }>)[opsKey]?.valueOf() ?? 0),\n error: benchError as string | undefined,\n };\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, error } of values) {\n const label = feed.padEnd(maxLabelLen);\n if (error) {\n console.log(` ${label} | \\x1b[31m[error: ${error}]\\x1b[0m`);\n continue;\n }\n const barLen = maxValue > 0 ? Math.round((value / maxValue) * width) : 0;\n const bar = '\\u2588'.repeat(barLen);\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 if ((data as Record<string, unknown>).error) continue;\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 if ((data as Record<string, unknown>).error) {\n console.log(` \\x1b[31m[error: ${(data as Record<string, unknown>).error}]\\x1b[0m`);\n continue;\n }\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":["AsyncFunction","Benchmark","DEFAULT_REPORT_TYPES","DEFAULT_WORKERS","FeedContext","Measure","MeasureContext","Target","TargetContext","printComparisonReports","printHistogramReports","printJSONReports","printMarkdownReports","printSimpleReports","printTableReports","reportsToBaseline","Math","max","ceil","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","progress","progressInterval","Error","benchmarkUrl","totalBenchmarks","reduce","acc","t","progressMap","Map","completedBenchmarks","bar","Progress","total","width","complete","incomplete","onProgress","info","set","id","totalProgress","values","a","b","label","slice","update","undefined","executor","createExecutor","reports","targetReport","measureReport","feeds","data","then","delete","drain","kill","terminate","report","console","group","count","heapUsedKB","dceWarning","error","benchError","metrics","log","output","Object","entries","map","key","toString","join","extras","extrasStr","groupEnd","table","fromEntries","padding","row","String","JSON","stringify","firstValid","find","f","keys","filter","k","header","separator","opsKey","value","valueOf","maxValue","v","maxLabelLen","padEnd","barLen","round","repeat","formatted","toLocaleString","maximumFractionDigits","results","metric","version","timestamp","Date","toISOString","baseline","threshold","baselineData","current","baselineValue","change","isOps","improved","regressed","indicator","changeStr","toFixed","coloredChange"],"mappings":"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"}
package/build/index.js CHANGED
@@ -2,7 +2,7 @@ import { cpus } from 'node:os';
2
2
  import Progress from 'progress';
3
3
  import { createExecutor } from "./executor.js";
4
4
  import { DEFAULT_CYCLES } from "./types.js";
5
- export const DEFAULT_WORKERS = cpus().length;
5
+ export const DEFAULT_WORKERS = Math.max(1, Math.ceil(cpus().length / 4));
6
6
  export const AsyncFunction = (async ()=>{}).constructor;
7
7
  const BENCHMARK_URL = Symbol.for('overtake.benchmarkUrl');
8
8
  export const DEFAULT_REPORT_TYPES = [
@@ -186,7 +186,11 @@ export const printSimpleReports = (reports)=>{
186
186
  for (const { measure, feeds } of report.measures){
187
187
  console.group('\n', report.target, measure);
188
188
  for (const { feed, data } of feeds){
189
- const { count, heapUsedKB, dceWarning, ...metrics } = data;
189
+ const { count, heapUsedKB, dceWarning, error: benchError, ...metrics } = data;
190
+ if (benchError) {
191
+ console.log(feed, `\x1b[31m[error: ${benchError}]\x1b[0m`);
192
+ continue;
193
+ }
190
194
  const output = Object.entries(metrics).map(([key, report])=>`${key}: ${report.toString()}`).join('; ');
191
195
  const extras = [];
192
196
  if (heapUsedKB) extras.push(`heap: ${heapUsedKB}KB`);
@@ -204,10 +208,17 @@ export const printTableReports = (reports)=>{
204
208
  console.log('\n', report.target, measure);
205
209
  const table = {};
206
210
  for (const { feed, data } of feeds){
207
- table[feed] = Object.fromEntries(Object.entries(data).map(([key, report])=>[
208
- key,
209
- report.toString()
210
- ]));
211
+ const { error: benchError } = data;
212
+ if (benchError) {
213
+ table[feed] = {
214
+ error: benchError
215
+ };
216
+ } else {
217
+ table[feed] = Object.fromEntries(Object.entries(data).map(([key, report])=>[
218
+ key,
219
+ report.toString()
220
+ ]));
221
+ }
211
222
  }
212
223
  console.table(table);
213
224
  }
@@ -219,10 +230,17 @@ export const printJSONReports = (reports, padding)=>{
219
230
  for (const { measure, feeds } of report.measures){
220
231
  const row = {};
221
232
  for (const { feed, data } of feeds){
222
- row[feed] = Object.fromEntries(Object.entries(data).map(([key, report])=>[
223
- key,
224
- report.toString()
225
- ]));
233
+ const { error: benchError } = data;
234
+ if (benchError) {
235
+ row[feed] = {
236
+ error: String(benchError)
237
+ };
238
+ } else {
239
+ row[feed] = Object.fromEntries(Object.entries(data).map(([key, report])=>[
240
+ key,
241
+ report.toString()
242
+ ]));
243
+ }
226
244
  }
227
245
  output[`${report.target} ${measure}`] = row;
228
246
  }
@@ -234,7 +252,14 @@ export const printMarkdownReports = (reports)=>{
234
252
  for (const { measure, feeds } of report.measures){
235
253
  console.log(`\n## ${report.target} - ${measure}\n`);
236
254
  if (feeds.length === 0) continue;
237
- const keys = Object.keys(feeds[0].data).filter((k)=>k !== 'count');
255
+ const firstValid = feeds.find((f)=>!f.data.error);
256
+ if (!firstValid) {
257
+ for (const { feed, data } of feeds){
258
+ console.log(`| ${feed} | error: ${data.error} |`);
259
+ }
260
+ continue;
261
+ }
262
+ const keys = Object.keys(firstValid.data).filter((k)=>k !== 'count' && k !== 'error');
238
263
  const header = [
239
264
  'Feed',
240
265
  ...keys
@@ -246,6 +271,10 @@ export const printMarkdownReports = (reports)=>{
246
271
  console.log(`| ${header} |`);
247
272
  console.log(`| ${separator} |`);
248
273
  for (const { feed, data } of feeds){
274
+ if (data.error) {
275
+ console.log(`| ${feed} | error: ${data.error} |`);
276
+ continue;
277
+ }
249
278
  const values = keys.map((k)=>data[k]?.toString() ?? '-');
250
279
  console.log(`| ${[
251
280
  feed,
@@ -260,16 +289,24 @@ export const printHistogramReports = (reports, width = 40)=>{
260
289
  for (const { measure, feeds } of report.measures){
261
290
  console.log(`\n${report.target} - ${measure}\n`);
262
291
  const opsKey = 'ops';
263
- const values = feeds.map((f)=>({
292
+ const values = feeds.map((f)=>{
293
+ const { error: benchError } = f.data;
294
+ return {
264
295
  feed: f.feed,
265
- value: f.data[opsKey]?.valueOf() ?? 0
266
- }));
296
+ value: benchError ? 0 : f.data[opsKey]?.valueOf() ?? 0,
297
+ error: benchError
298
+ };
299
+ });
267
300
  const maxValue = Math.max(...values.map((v)=>v.value));
268
301
  const maxLabelLen = Math.max(...values.map((v)=>v.feed.length));
269
- for (const { feed, value } of values){
302
+ for (const { feed, value, error } of values){
303
+ const label = feed.padEnd(maxLabelLen);
304
+ if (error) {
305
+ console.log(` ${label} | \x1b[31m[error: ${error}]\x1b[0m`);
306
+ continue;
307
+ }
270
308
  const barLen = maxValue > 0 ? Math.round(value / maxValue * width) : 0;
271
309
  const bar = '\u2588'.repeat(barLen);
272
- const label = feed.padEnd(maxLabelLen);
273
310
  const formatted = value.toLocaleString('en-US', {
274
311
  maximumFractionDigits: 2
275
312
  });
@@ -283,6 +320,7 @@ export const reportsToBaseline = (reports)=>{
283
320
  for (const report of reports){
284
321
  for (const { measure, feeds } of report.measures){
285
322
  for (const { feed, data } of feeds){
323
+ if (data.error) continue;
286
324
  const key = `${report.target}/${measure}/${feed}`;
287
325
  results[key] = {};
288
326
  for (const [metric, value] of Object.entries(data)){
@@ -307,6 +345,10 @@ export const printComparisonReports = (reports, baseline, threshold = 5)=>{
307
345
  const key = `${report.target}/${measure}/${feed}`;
308
346
  const baselineData = baseline.results[key];
309
347
  console.log(` ${feed}:`);
348
+ if (data.error) {
349
+ console.log(` \x1b[31m[error: ${data.error}]\x1b[0m`);
350
+ continue;
351
+ }
310
352
  for (const [metric, value] of Object.entries(data)){
311
353
  if (metric === 'count') continue;
312
354
  const current = value.valueOf();
@@ -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 { 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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"}
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 = Math.max(1, Math.ceil(cpus().length / 4));\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, error: benchError, ...metrics } = data as Record<string, unknown>;\n if (benchError) {\n console.log(feed, `\\x1b[31m[error: ${benchError}]\\x1b[0m`);\n continue;\n }\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 const { error: benchError } = data as Record<string, unknown>;\n if (benchError) {\n table[feed] = { error: benchError };\n } else {\n table[feed] = Object.fromEntries(Object.entries(data).map(([key, report]) => [key, report.toString()]));\n }\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 const { error: benchError } = data as Record<string, unknown>;\n if (benchError) {\n row[feed] = { error: String(benchError) };\n } else {\n row[feed] = Object.fromEntries(Object.entries(data).map(([key, report]) => [key, report.toString()]));\n }\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 firstValid = feeds.find((f) => !(f.data as Record<string, unknown>).error);\n if (!firstValid) {\n for (const { feed, data } of feeds) {\n console.log(`| ${feed} | error: ${(data as Record<string, unknown>).error} |`);\n }\n continue;\n }\n const keys = Object.keys(firstValid.data).filter((k) => k !== 'count' && k !== 'error');\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 if ((data as Record<string, unknown>).error) {\n console.log(`| ${feed} | error: ${(data as Record<string, unknown>).error} |`);\n continue;\n }\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 const { error: benchError } = f.data as Record<string, unknown>;\n return {\n feed: f.feed,\n value: benchError ? 0 : ((f.data as Record<string, { valueOf(): number }>)[opsKey]?.valueOf() ?? 0),\n error: benchError as string | undefined,\n };\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, error } of values) {\n const label = feed.padEnd(maxLabelLen);\n if (error) {\n console.log(` ${label} | \\x1b[31m[error: ${error}]\\x1b[0m`);\n continue;\n }\n const barLen = maxValue > 0 ? Math.round((value / maxValue) * width) : 0;\n const bar = '\\u2588'.repeat(barLen);\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 if ((data as Record<string, unknown>).error) continue;\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 if ((data as Record<string, unknown>).error) {\n console.log(` \\x1b[31m[error: ${(data as Record<string, unknown>).error}]\\x1b[0m`);\n continue;\n }\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","Math","max","ceil","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","error","benchError","metrics","log","output","Object","entries","map","key","toString","join","extras","extrasStr","groupEnd","printTableReports","table","fromEntries","printJSONReports","padding","row","String","JSON","stringify","printMarkdownReports","firstValid","find","f","keys","filter","k","header","separator","printHistogramReports","opsKey","value","valueOf","maxValue","v","maxLabelLen","padEnd","barLen","round","repeat","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":"AAAA,SAASA,IAAI,QAAQ,UAAU;AAC/B,OAAOC,cAAc,WAAW;AAChC,SAASC,cAAc,QAAyC,gBAAgB;AAChF,SAAwFC,cAAc,QAAsB,aAAa;AAMzI,OAAO,MAAMC,kBAAkBC,KAAKC,GAAG,CAAC,GAAGD,KAAKE,IAAI,CAACP,OAAOQ,MAAM,GAAG,IAAI;AAEzE,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,OAAoD,EAA8B;QAC7J,MAAM,EACJC,UAAUjC,eAAe,EACzBkC,eAAe,EAAE,EACjBC,YAAYpC,cAAc,EAC1BqC,YAAY,EAAE,EACdC,eAAe,KAAK,EACpBC,eAAe,IAAI,EACnBC,aAAa,IAAI,EACjBC,cAAc/B,oBAAoC,EAClDgC,WAAW,KAAK,EAChBC,mBAAmB,GAAG,EACvB,GAAGV;QACJ,IAAI,IAAI,CAAC,CAAA,QAAS,EAAE;YAClB,MAAM,IAAIW,MAAM;QAClB;QACA,IAAI,CAAC,CAAA,QAAS,GAAG;QACjB,MAAMC,eAAe,AAACZ,OAA8C,CAAC1B,cAAc;QAEnF,MAAMuC,kBAAkB,IAAI,CAAC,CAAA,OAAQ,CAACC,MAAM,CAAC,CAACC,KAAKC,IAAMD,MAAMC,EAAE5B,QAAQ,CAAChB,MAAM,GAAG,IAAI,CAAC,CAAA,KAAM,CAACA,MAAM,EAAE;QACvG,MAAM6C,cAAc,IAAIC;QACxB,IAAIC,sBAAsB;QAC1B,IAAIC,MAAuB;QAE3B,IAAIX,YAAYI,kBAAkB,GAAG;YACnCO,MAAM,IAAIvD,SAAS,4CAA4C;gBAC7DwD,OAAOR,kBAAkB;gBACzBS,OAAO;gBACPC,UAAU;gBACVC,YAAY;YACd;QACF;QAEA,MAAMC,aAAahB,WACf,CAACiB;YACCT,YAAYU,GAAG,CAACD,KAAKE,EAAE,EAAEF,KAAKjB,QAAQ;YACtC,MAAMoB,gBAAgB,AAACV,CAAAA,sBAAsB;mBAAIF,YAAYa,MAAM;aAAG,CAAChB,MAAM,CAAC,CAACiB,GAAGC,IAAMD,IAAIC,GAAG,EAAC,IAAK;YACrG,MAAMC,QAAQP,KAAKE,EAAE,CAACxD,MAAM,GAAG,KAAKsD,KAAKE,EAAE,CAACM,KAAK,CAAC,GAAG,MAAM,QAAQR,KAAKE,EAAE;YAC1ER,KAAKe,OAAON,gBAAiBhB,CAAAA,kBAAkB,GAAE,GAAI;gBAAEoB;YAAM;QAC/D,IACAG;QAEJ,MAAMC,WAAWvE,eAAmC;YAClDmC;YACAC;YACAC;YACAC;YACAC;YACAC;YACAC;YACAC;YACAiB;YACAf;YACA,CAACpC,cAAc,EAAEsC;QACnB;QAEA,MAAM0B,UAA6B,EAAE;QACrC,KAAK,MAAMxC,UAAU,IAAI,CAAC,CAAA,OAAQ,CAAE;YAClC,MAAMyC,eAAgC;gBAAEzC,QAAQA,OAAOjB,KAAK;gBAAEO,UAAU,EAAE;YAAC;YAC3E,KAAK,MAAMG,WAAWO,OAAOV,QAAQ,CAAE;gBACrC,MAAMoD,gBAAkC;oBAAEjD,SAASA,QAAQV,KAAK;oBAAE4D,OAAO,EAAE;gBAAC;gBAC5E,KAAK,MAAM7C,QAAQ,IAAI,CAAC,CAAA,KAAM,CAAE;oBAC9B,MAAMgC,KAAK,GAAG9B,OAAOjB,KAAK,CAAC,CAAC,EAAEU,QAAQV,KAAK,CAAC,CAAC,EAAEe,KAAKf,KAAK,EAAE;oBAC3D,MAAM6D,OAAO,MAAM9C,KAAKX,EAAE;oBAC1BoD,SACG7C,IAAI,CAAoB;wBACvBoC;wBACAvC,OAAOS,OAAOT,KAAK;wBACnBF,UAAUW,OAAOX,QAAQ;wBACzBR,KAAKY,QAAQZ,GAAG;wBAChBG,KAAKS,QAAQT,GAAG;wBAChBF,MAAMW,QAAQX,IAAI;wBAClB8D;oBACF,GACCC,IAAI,CAAC,CAACD;wBACLzB,YAAY2B,MAAM,CAAChB;wBACnBT;wBACAqB,cAAcC,KAAK,CAACjD,IAAI,CAAC;4BACvBI,MAAMA,KAAKf,KAAK;4BAChB6D;wBACF;oBACF;gBACJ;gBACAH,aAAanD,QAAQ,CAACI,IAAI,CAACgD;YAC7B;YACAF,QAAQ9C,IAAI,CAAC+C;QACf;QACA,MAAMF,SAASQ,KAAK;QACpBR,SAASS,IAAI;QAEb,IAAI1B,KAAK;YACPA,IAAIe,MAAM,CAAC,GAAG;gBAAEF,OAAO;YAAO;YAC9Bb,IAAI2B,SAAS;QACf;QAEA,OAAOT;IACT;AACF;AAEA,OAAO,MAAMU,qBAAqB,CAA2BV;IAC3D,KAAK,MAAMW,UAAUX,QAAS;QAC5B,KAAK,MAAM,EAAE/C,OAAO,EAAEkD,KAAK,EAAE,IAAIQ,OAAO7D,QAAQ,CAAE;YAChD8D,QAAQC,KAAK,CAAC,MAAMF,OAAOnD,MAAM,EAAEP;YACnC,KAAK,MAAM,EAAEK,IAAI,EAAE8C,IAAI,EAAE,IAAID,MAAO;gBAClC,MAAM,EAAEW,KAAK,EAAEC,UAAU,EAAEC,UAAU,EAAEC,OAAOC,UAAU,EAAE,GAAGC,SAAS,GAAGf;gBACzE,IAAIc,YAAY;oBACdN,QAAQQ,GAAG,CAAC9D,MAAM,CAAC,gBAAgB,EAAE4D,WAAW,QAAQ,CAAC;oBACzD;gBACF;gBACA,MAAMG,SAASC,OAAOC,OAAO,CAACJ,SAC3BK,GAAG,CAAC,CAAC,CAACC,KAAKd,OAAO,GAAK,GAAGc,IAAI,EAAE,EAAE,AAACd,OAAkCe,QAAQ,IAAI,EACjFC,IAAI,CAAC;gBACR,MAAMC,SAAmB,EAAE;gBAC3B,IAAIb,YAAYa,OAAO1E,IAAI,CAAC,CAAC,MAAM,EAAE6D,WAAW,EAAE,CAAC;gBACnD,IAAIC,YAAYY,OAAO1E,IAAI,CAAC;gBAC5B,MAAM2E,YAAYD,OAAO9F,MAAM,GAAG,IAAI,CAAC,EAAE,EAAE8F,OAAOD,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG;gBAClEf,QAAQQ,GAAG,CAAC9D,MAAM+D,SAASQ;YAC7B;YACAjB,QAAQkB,QAAQ;QAClB;IACF;AACF,EAAE;AAEF,OAAO,MAAMC,oBAAoB,CAA2B/B;IAC1D,KAAK,MAAMW,UAAUX,QAAS;QAC5B,KAAK,MAAM,EAAE/C,OAAO,EAAEkD,KAAK,EAAE,IAAIQ,OAAO7D,QAAQ,CAAE;YAChD8D,QAAQQ,GAAG,CAAC,MAAMT,OAAOnD,MAAM,EAAEP;YACjC,MAAM+E,QAAiC,CAAC;YACxC,KAAK,MAAM,EAAE1E,IAAI,EAAE8C,IAAI,EAAE,IAAID,MAAO;gBAClC,MAAM,EAAEc,OAAOC,UAAU,EAAE,GAAGd;gBAC9B,IAAIc,YAAY;oBACdc,KAAK,CAAC1E,KAAK,GAAG;wBAAE2D,OAAOC;oBAAW;gBACpC,OAAO;oBACLc,KAAK,CAAC1E,KAAK,GAAGgE,OAAOW,WAAW,CAACX,OAAOC,OAAO,CAACnB,MAAMoB,GAAG,CAAC,CAAC,CAACC,KAAKd,OAAO,GAAK;4BAACc;4BAAKd,OAAOe,QAAQ;yBAAG;gBACvG;YACF;YACAd,QAAQoB,KAAK,CAACA;QAChB;IACF;AACF,EAAE;AAEF,OAAO,MAAME,mBAAmB,CAA2BlC,SAA4BmC;IACrF,MAAMd,SAAS,CAAC;IAChB,KAAK,MAAMV,UAAUX,QAAS;QAC5B,KAAK,MAAM,EAAE/C,OAAO,EAAEkD,KAAK,EAAE,IAAIQ,OAAO7D,QAAQ,CAAE;YAChD,MAAMsF,MAAM,CAAC;YACb,KAAK,MAAM,EAAE9E,IAAI,EAAE8C,IAAI,EAAE,IAAID,MAAO;gBAClC,MAAM,EAAEc,OAAOC,UAAU,EAAE,GAAGd;gBAC9B,IAAIc,YAAY;oBACdkB,GAAG,CAAC9E,KAAK,GAAG;wBAAE2D,OAAOoB,OAAOnB;oBAAY;gBAC1C,OAAO;oBACLkB,GAAG,CAAC9E,KAAK,GAAGgE,OAAOW,WAAW,CAACX,OAAOC,OAAO,CAACnB,MAAMoB,GAAG,CAAC,CAAC,CAACC,KAAKd,OAAO,GAAK;4BAACc;4BAAKd,OAAOe,QAAQ;yBAAG;gBACrG;YACF;YACAL,MAAM,CAAC,GAAGV,OAAOnD,MAAM,CAAC,CAAC,EAAEP,SAAS,CAAC,GAAGmF;QAC1C;IACF;IACAxB,QAAQQ,GAAG,CAACkB,KAAKC,SAAS,CAAClB,QAAQ,MAAMc;AAC3C,EAAE;AAEF,OAAO,MAAMK,uBAAuB,CAA2BxC;IAC7D,KAAK,MAAMW,UAAUX,QAAS;QAC5B,KAAK,MAAM,EAAE/C,OAAO,EAAEkD,KAAK,EAAE,IAAIQ,OAAO7D,QAAQ,CAAE;YAChD8D,QAAQQ,GAAG,CAAC,CAAC,KAAK,EAAET,OAAOnD,MAAM,CAAC,GAAG,EAAEP,QAAQ,EAAE,CAAC;YAClD,IAAIkD,MAAMrE,MAAM,KAAK,GAAG;YAExB,MAAM2G,aAAatC,MAAMuC,IAAI,CAAC,CAACC,IAAM,CAAC,AAACA,EAAEvC,IAAI,CAA6Ba,KAAK;YAC/E,IAAI,CAACwB,YAAY;gBACf,KAAK,MAAM,EAAEnF,IAAI,EAAE8C,IAAI,EAAE,IAAID,MAAO;oBAClCS,QAAQQ,GAAG,CAAC,CAAC,EAAE,EAAE9D,KAAK,UAAU,EAAE,AAAC8C,KAAiCa,KAAK,CAAC,EAAE,CAAC;gBAC/E;gBACA;YACF;YACA,MAAM2B,OAAOtB,OAAOsB,IAAI,CAACH,WAAWrC,IAAI,EAAEyC,MAAM,CAAC,CAACC,IAAMA,MAAM,WAAWA,MAAM;YAC/E,MAAMC,SAAS;gBAAC;mBAAWH;aAAK,CAACjB,IAAI,CAAC;YACtC,MAAMqB,YAAY;gBAAC;mBAAUJ,KAAKpB,GAAG,CAAC,IAAM;aAAO,CAACG,IAAI,CAAC;YAEzDf,QAAQQ,GAAG,CAAC,CAAC,EAAE,EAAE2B,OAAO,EAAE,CAAC;YAC3BnC,QAAQQ,GAAG,CAAC,CAAC,EAAE,EAAE4B,UAAU,EAAE,CAAC;YAE9B,KAAK,MAAM,EAAE1F,IAAI,EAAE8C,IAAI,EAAE,IAAID,MAAO;gBAClC,IAAI,AAACC,KAAiCa,KAAK,EAAE;oBAC3CL,QAAQQ,GAAG,CAAC,CAAC,EAAE,EAAE9D,KAAK,UAAU,EAAE,AAAC8C,KAAiCa,KAAK,CAAC,EAAE,CAAC;oBAC7E;gBACF;gBACA,MAAMzB,SAASoD,KAAKpB,GAAG,CAAC,CAACsB,IAAM,AAAC1C,IAA+C,CAAC0C,EAAE,EAAEpB,cAAc;gBAClGd,QAAQQ,GAAG,CAAC,CAAC,EAAE,EAAE;oBAAC9D;uBAASkC;iBAAO,CAACmC,IAAI,CAAC,OAAO,EAAE,CAAC;YACpD;QACF;IACF;AACF,EAAE;AAEF,OAAO,MAAMsB,wBAAwB,CAA2BjD,SAA4BhB,QAAQ,EAAE;IACpG,KAAK,MAAM2B,UAAUX,QAAS;QAC5B,KAAK,MAAM,EAAE/C,OAAO,EAAEkD,KAAK,EAAE,IAAIQ,OAAO7D,QAAQ,CAAE;YAChD8D,QAAQQ,GAAG,CAAC,CAAC,EAAE,EAAET,OAAOnD,MAAM,CAAC,GAAG,EAAEP,QAAQ,EAAE,CAAC;YAE/C,MAAMiG,SAAS;YACf,MAAM1D,SAASW,MAAMqB,GAAG,CAAC,CAACmB;gBACxB,MAAM,EAAE1B,OAAOC,UAAU,EAAE,GAAGyB,EAAEvC,IAAI;gBACpC,OAAO;oBACL9C,MAAMqF,EAAErF,IAAI;oBACZ6F,OAAOjC,aAAa,IAAK,AAACyB,EAAEvC,IAAI,AAA0C,CAAC8C,OAAO,EAAEE,aAAa;oBACjGnC,OAAOC;gBACT;YACF;YAEA,MAAMmC,WAAW1H,KAAKC,GAAG,IAAI4D,OAAOgC,GAAG,CAAC,CAAC8B,IAAMA,EAAEH,KAAK;YACtD,MAAMI,cAAc5H,KAAKC,GAAG,IAAI4D,OAAOgC,GAAG,CAAC,CAAC8B,IAAMA,EAAEhG,IAAI,CAACxB,MAAM;YAE/D,KAAK,MAAM,EAAEwB,IAAI,EAAE6F,KAAK,EAAElC,KAAK,EAAE,IAAIzB,OAAQ;gBAC3C,MAAMG,QAAQrC,KAAKkG,MAAM,CAACD;gBAC1B,IAAItC,OAAO;oBACTL,QAAQQ,GAAG,CAAC,CAAC,EAAE,EAAEzB,MAAM,mBAAmB,EAAEsB,MAAM,QAAQ,CAAC;oBAC3D;gBACF;gBACA,MAAMwC,SAASJ,WAAW,IAAI1H,KAAK+H,KAAK,CAAC,AAACP,QAAQE,WAAYrE,SAAS;gBACvE,MAAMF,MAAM,SAAS6E,MAAM,CAACF;gBAC5B,MAAMG,YAAYT,MAAMU,cAAc,CAAC,SAAS;oBAAEC,uBAAuB;gBAAE;gBAC3ElD,QAAQQ,GAAG,CAAC,CAAC,EAAE,EAAEzB,MAAM,GAAG,EAAEb,IAAI,CAAC,EAAE8E,UAAU,MAAM,CAAC;YACtD;QACF;IACF;AACF,EAAE;AAQF,OAAO,MAAMG,oBAAoB,CAA2B/D;IAC1D,MAAMgE,UAAkD,CAAC;IACzD,KAAK,MAAMrD,UAAUX,QAAS;QAC5B,KAAK,MAAM,EAAE/C,OAAO,EAAEkD,KAAK,EAAE,IAAIQ,OAAO7D,QAAQ,CAAE;YAChD,KAAK,MAAM,EAAEQ,IAAI,EAAE8C,IAAI,EAAE,IAAID,MAAO;gBAClC,IAAI,AAACC,KAAiCa,KAAK,EAAE;gBAC7C,MAAMQ,MAAM,GAAGd,OAAOnD,MAAM,CAAC,CAAC,EAAEP,QAAQ,CAAC,EAAEK,MAAM;gBACjD0G,OAAO,CAACvC,IAAI,GAAG,CAAC;gBAChB,KAAK,MAAM,CAACwC,QAAQd,MAAM,IAAI7B,OAAOC,OAAO,CAACnB,MAAO;oBAClD,IAAI6D,WAAW,WAAW,OAAO,AAACd,MAAgCC,OAAO,KAAK,YAAY;wBACxFY,OAAO,CAACvC,IAAI,CAACwC,OAAO,GAAG,AAACd,MAAgCC,OAAO;oBACjE;gBACF;YACF;QACF;IACF;IACA,OAAO;QACLc,SAAS;QACTC,WAAW,IAAIC,OAAOC,WAAW;QACjCL;IACF;AACF,EAAE;AAEF,OAAO,MAAMM,yBAAyB,CAA2BtE,SAA4BuE,UAAwBC,YAAY,CAAC;IAChI,KAAK,MAAM7D,UAAUX,QAAS;QAC5B,KAAK,MAAM,EAAE/C,OAAO,EAAEkD,KAAK,EAAE,IAAIQ,OAAO7D,QAAQ,CAAE;YAChD8D,QAAQQ,GAAG,CAAC,CAAC,EAAE,EAAET,OAAOnD,MAAM,CAAC,GAAG,EAAEP,QAAQ,EAAE,CAAC;YAE/C,KAAK,MAAM,EAAEK,IAAI,EAAE8C,IAAI,EAAE,IAAID,MAAO;gBAClC,MAAMsB,MAAM,GAAGd,OAAOnD,MAAM,CAAC,CAAC,EAAEP,QAAQ,CAAC,EAAEK,MAAM;gBACjD,MAAMmH,eAAeF,SAASP,OAAO,CAACvC,IAAI;gBAE1Cb,QAAQQ,GAAG,CAAC,CAAC,EAAE,EAAE9D,KAAK,CAAC,CAAC;gBAExB,IAAI,AAAC8C,KAAiCa,KAAK,EAAE;oBAC3CL,QAAQQ,GAAG,CAAC,CAAC,oBAAoB,EAAE,AAAChB,KAAiCa,KAAK,CAAC,QAAQ,CAAC;oBACpF;gBACF;gBAEA,KAAK,MAAM,CAACgD,QAAQd,MAAM,IAAI7B,OAAOC,OAAO,CAACnB,MAAO;oBAClD,IAAI6D,WAAW,SAAS;oBACxB,MAAMS,UAAU,AAACvB,MAAgCC,OAAO;oBACxD,MAAMuB,gBAAgBF,cAAc,CAACR,OAAO;oBAE5C,IAAIU,kBAAkB7E,aAAa6E,kBAAkB,GAAG;wBACtD,MAAMC,SAAS,AAAEF,CAAAA,UAAUC,aAAY,IAAKA,gBAAiB;wBAC7D,MAAME,QAAQZ,WAAW;wBACzB,MAAMa,WAAWD,QAAQD,SAASJ,YAAYI,SAAS,CAACJ;wBACxD,MAAMO,YAAYF,QAAQD,SAAS,CAACJ,YAAYI,SAASJ;wBAEzD,IAAIQ,YAAY;wBAChB,IAAIF,UAAUE,YAAY;6BACrB,IAAID,WAAWC,YAAY;wBAEhC,MAAMC,YAAYL,UAAU,IAAI,CAAC,CAAC,EAAEA,OAAOM,OAAO,CAAC,GAAG,CAAC,CAAC,GAAG,GAAGN,OAAOM,OAAO,CAAC,GAAG,CAAC,CAAC;wBAClF,MAAMC,gBAAgBJ,YAAY,CAAC,QAAQ,EAAEE,UAAU,OAAO,CAAC,GAAGH,WAAW,CAAC,QAAQ,EAAEG,UAAU,OAAO,CAAC,GAAGA;wBAE7GrE,QAAQQ,GAAG,CAAC,CAAC,IAAI,EAAE4D,UAAU,CAAC,EAAEf,OAAO,EAAE,EAAE,AAACd,MAAiCzB,QAAQ,GAAG,EAAE,EAAEyD,cAAc,CAAC,CAAC;oBAC9G,OAAO;wBACLvE,QAAQQ,GAAG,CAAC,CAAC,MAAM,EAAE6C,OAAO,EAAE,EAAE,AAACd,MAAiCzB,QAAQ,GAAG,MAAM,CAAC;oBACtF;gBACF;YACF;QACF;IACF;IAEAd,QAAQQ,GAAG,CAAC,CAAC,iBAAiB,EAAEmD,SAASJ,SAAS,EAAE;AACtD,EAAE"}