overtake 1.4.0 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -15
- package/bin/overtake.js +1 -1
- package/build/executor.d.ts +7 -3
- package/build/index.d.ts +10 -11
- package/build/reporter.d.ts +10 -2
- package/build/runner.d.ts +1 -1
- package/build/types.d.ts +6 -6
- package/build/utils.d.ts +1 -17
- package/package.json +8 -26
- package/src/__tests__/assert-no-closure.ts +135 -0
- package/src/__tests__/benchmark-execute.ts +48 -0
- package/src/cli.ts +139 -144
- package/src/executor.ts +48 -18
- package/src/index.ts +85 -57
- package/src/reporter.ts +27 -19
- package/src/runner.ts +2 -5
- package/src/types.ts +8 -8
- package/src/utils.ts +15 -54
- package/src/worker.ts +6 -3
- package/tsconfig.json +3 -1
- package/build/cli.cjs +0 -179
- package/build/cli.cjs.map +0 -1
- package/build/cli.js +0 -134
- package/build/cli.js.map +0 -1
- package/build/executor.cjs +0 -123
- package/build/executor.cjs.map +0 -1
- package/build/executor.js +0 -113
- package/build/executor.js.map +0 -1
- package/build/gc-watcher.cjs +0 -30
- package/build/gc-watcher.cjs.map +0 -1
- package/build/gc-watcher.js +0 -20
- package/build/gc-watcher.js.map +0 -1
- package/build/index.cjs +0 -442
- package/build/index.cjs.map +0 -1
- package/build/index.js +0 -377
- package/build/index.js.map +0 -1
- package/build/reporter.cjs +0 -311
- package/build/reporter.cjs.map +0 -1
- package/build/reporter.js +0 -293
- package/build/reporter.js.map +0 -1
- package/build/runner.cjs +0 -532
- package/build/runner.cjs.map +0 -1
- package/build/runner.js +0 -522
- package/build/runner.js.map +0 -1
- package/build/types.cjs +0 -66
- package/build/types.cjs.map +0 -1
- package/build/types.js +0 -33
- package/build/types.js.map +0 -1
- package/build/utils.cjs +0 -174
- package/build/utils.cjs.map +0 -1
- package/build/utils.js +0 -132
- package/build/utils.js.map +0 -1
- package/build/worker.cjs +0 -155
- package/build/worker.cjs.map +0 -1
- package/build/worker.js +0 -110
- package/build/worker.js.map +0 -1
- package/src/__tests__/assert-no-closure.js +0 -134
package/build/reporter.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/reporter.ts"],"sourcesContent":["import { div, max, divs, isqrt } from './utils.js';\nimport { ReportType, DURATION_SCALE } 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\nconst SQRT_SCALE = 1_000_000n;\nconst SQRT_SCALE_SQ = SQRT_SCALE * SQRT_SCALE;\nconst Z95_NUM = 196n;\nconst Z95_DENOM = 100n;\n\nconst computeStats = (durations: BigUint64Array) => {\n let sum = 0n;\n for (const d of durations) sum += d;\n const n = BigInt(durations.length);\n const mean = sum / n;\n let ssd = 0n;\n for (const d of durations) {\n const diff = d - mean;\n ssd += diff * diff;\n }\n return { sum, mean, ssd, 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 const { mean: avgScaled, ssd, n: nBig } = computeStats(durations);\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 let uncertainty = 0;\n if (n >= 2 && avgScaled > 0n) {\n const RME_PRECISION = 1_000_000n;\n const semOverMeanSqScaled = (ssd * RME_PRECISION * RME_PRECISION) / (BigInt(n - 1) * nBig * avgScaled * avgScaled);\n const semOverMeanScaled = isqrt(semOverMeanSqScaled);\n uncertainty = Number(Z95_NUM * semOverMeanScaled) / Number(RME_PRECISION);\n }\n return new Report(type, value, uncertainty, scale);\n }\n case 'mean': {\n const { sum } = computeStats(durations);\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 const { ssd } = computeStats(durations);\n const variance = ssd / 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 const { ssd } = computeStats(durations);\n const scaledVariance = (ssd * SQRT_SCALE_SQ) / BigInt(n - 1);\n const sdScaled = isqrt(scaledVariance);\n return new Report(type, sdScaled, 0, DURATION_SCALE * SQRT_SCALE);\n }\n\n case 'sem': {\n if (n < 2) return new Report(type, 0n, 0, DURATION_SCALE);\n const { ssd, n: nBig } = computeStats(durations);\n const semSqScaled = (ssd * SQRT_SCALE_SQ) / (BigInt(n - 1) * nBig);\n const semScaled = isqrt(semSqScaled);\n return new Report(type, semScaled, 0, DURATION_SCALE * SQRT_SCALE);\n }\n\n case 'moe': {\n if (n < 2) return new Report(type, 0n, 0, DURATION_SCALE);\n const { ssd, n: nBig } = computeStats(durations);\n const semSqScaled = (ssd * SQRT_SCALE_SQ) / (BigInt(n - 1) * nBig);\n const semScaled = isqrt(semSqScaled);\n const moeScaled = (Z95_NUM * semScaled) / Z95_DENOM;\n return new Report(type, moeScaled, 0, DURATION_SCALE * SQRT_SCALE);\n }\n\n case 'rme': {\n if (n < 2) return new Report(type, 0n);\n const { mean, ssd, n: nBig } = computeStats(durations);\n if (mean === 0n) return new Report(type, 0n);\n const RME_PRECISION = 1_000_000n;\n const semOverMeanSqScaled = (ssd * RME_PRECISION * RME_PRECISION) / (BigInt(n - 1) * nBig * mean * mean);\n const semOverMeanScaled = isqrt(semOverMeanSqScaled);\n const rmeScaled = (Z95_NUM * semOverMeanScaled * 100n) / RME_PRECISION;\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 const { mean, ssd, n: nBig } = computeStats(durations);\n const semSqScaled = (ssd * SQRT_SCALE_SQ) / (BigInt(n - 1) * nBig);\n const semScaled = isqrt(semSqScaled);\n const moeScaled = (Z95_NUM * semScaled) / Z95_DENOM;\n const ciLowerScaled = mean * SQRT_SCALE - moeScaled;\n return new Report(type, ciLowerScaled > 0n ? ciLowerScaled : 0n, 0, DURATION_SCALE * SQRT_SCALE);\n }\n\n case 'ci_upper': {\n if (n < 2) return new Report(type, 0n, 0, DURATION_SCALE);\n const { mean, ssd, n: nBig } = computeStats(durations);\n const semSqScaled = (ssd * SQRT_SCALE_SQ) / (BigInt(n - 1) * nBig);\n const semScaled = isqrt(semSqScaled);\n const moeScaled = (Z95_NUM * semScaled) / Z95_DENOM;\n const ciUpperScaled = mean * SQRT_SCALE + moeScaled;\n return new Report(type, ciUpperScaled, 0, DURATION_SCALE * SQRT_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","isqrt","DURATION_SCALE","units","unit","factor","smartFixed","n","toLocaleString","undefined","minimumFractionDigits","maximumFractionDigits","useGrouping","Report","type","value","uncertainty","scale","valueOf","Number","toString","display","varianceUnits","u","candidate","SQRT_SCALE","SQRT_SCALE_SQ","Z95_NUM","Z95_DENOM","computeStats","durations","sum","d","BigInt","length","mean","ssd","diff","createReport","mid","Math","floor","med","freq","Map","maxCount","modeVal","count","get","set","lower","upper","firstIdx","indexOf","lastIdx","lastIndexOf","gap","avgScaled","nBig","nsPerSecScaled","raw","extra","ceil","log10","exp","RME_PRECISION","semOverMeanSqScaled","semOverMeanScaled","variance","scaledVariance","sdScaled","semSqScaled","semScaled","moeScaled","rmeScaled","medianIdx","median","deviations","BigUint64Array","i","sort","madIdx","mad","q1Idx","q3Idx","q1","q3","iqr","ciLowerScaled","ciUpperScaled","p","slice","idx","min","prev","next"],"mappings":"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"}
|
package/build/runner.cjs
DELETED
|
@@ -1,532 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", {
|
|
3
|
-
value: true
|
|
4
|
-
});
|
|
5
|
-
Object.defineProperty(exports, "benchmark", {
|
|
6
|
-
enumerable: true,
|
|
7
|
-
get: function() {
|
|
8
|
-
return benchmark;
|
|
9
|
-
}
|
|
10
|
-
});
|
|
11
|
-
const _nodeperf_hooks = require("node:perf_hooks");
|
|
12
|
-
const _typescjs = require("./types.cjs");
|
|
13
|
-
const _gcwatchercjs = require("./gc-watcher.cjs");
|
|
14
|
-
const COMPLETE_VALUE = 100_00;
|
|
15
|
-
const hr = process.hrtime.bigint.bind(process.hrtime);
|
|
16
|
-
const sink = new Int32Array(1);
|
|
17
|
-
const consume = (value)=>{
|
|
18
|
-
let payload = 0;
|
|
19
|
-
switch(typeof value){
|
|
20
|
-
case 'number':
|
|
21
|
-
payload = Number.isFinite(value) ? Math.trunc(value) : 0;
|
|
22
|
-
break;
|
|
23
|
-
case 'bigint':
|
|
24
|
-
payload = Number(value & 0xffff_ffffn);
|
|
25
|
-
break;
|
|
26
|
-
case 'string':
|
|
27
|
-
payload = value.length;
|
|
28
|
-
break;
|
|
29
|
-
case 'boolean':
|
|
30
|
-
payload = value ? 1 : 0;
|
|
31
|
-
break;
|
|
32
|
-
case 'object':
|
|
33
|
-
payload = value === null ? 0 : 1;
|
|
34
|
-
break;
|
|
35
|
-
case 'function':
|
|
36
|
-
payload = 1;
|
|
37
|
-
break;
|
|
38
|
-
default:
|
|
39
|
-
payload = -1;
|
|
40
|
-
}
|
|
41
|
-
sink[0] ^= payload;
|
|
42
|
-
};
|
|
43
|
-
const runSync = (run, overhead)=>{
|
|
44
|
-
return (...args)=>{
|
|
45
|
-
const start = hr();
|
|
46
|
-
const result = run(...args);
|
|
47
|
-
consume(result);
|
|
48
|
-
const duration = hr() - start;
|
|
49
|
-
return duration > overhead ? duration - overhead : 0n;
|
|
50
|
-
};
|
|
51
|
-
};
|
|
52
|
-
const runAsync = (run)=>{
|
|
53
|
-
return async (...args)=>{
|
|
54
|
-
const start = hr();
|
|
55
|
-
const result = await run(...args);
|
|
56
|
-
consume(result);
|
|
57
|
-
return hr() - start;
|
|
58
|
-
};
|
|
59
|
-
};
|
|
60
|
-
const isThenable = (value)=>{
|
|
61
|
-
return value !== null && (typeof value === 'object' || typeof value === 'function') && typeof value.then === 'function';
|
|
62
|
-
};
|
|
63
|
-
const TARGET_SAMPLE_NS = 1_000_000n;
|
|
64
|
-
const MAX_BATCH = 1_048_576;
|
|
65
|
-
const PROGRESS_STRIDE = 16;
|
|
66
|
-
const GC_STRIDE = 32;
|
|
67
|
-
const OUTLIER_MULTIPLIER = 4;
|
|
68
|
-
const OUTLIER_IQR_MULTIPLIER = 3;
|
|
69
|
-
const OUTLIER_WINDOW = 64;
|
|
70
|
-
const OUTLIER_ABS_THRESHOLD = 10_000_000;
|
|
71
|
-
const BASELINE_SAMPLES = 16;
|
|
72
|
-
const OUTLIER_SCRATCH = new Float64Array(OUTLIER_WINDOW);
|
|
73
|
-
const measureTimerOverhead = ()=>{
|
|
74
|
-
let total = 0n;
|
|
75
|
-
for(let i = 0; i < BASELINE_SAMPLES; i++){
|
|
76
|
-
const start = hr();
|
|
77
|
-
consume(0);
|
|
78
|
-
total += hr() - start;
|
|
79
|
-
}
|
|
80
|
-
return total / BigInt(BASELINE_SAMPLES);
|
|
81
|
-
};
|
|
82
|
-
const collectSample = async ({ batchSize, run, runRaw, runIsAsync, pre, preIsAsync, post, postIsAsync, context, data, nextNonce })=>{
|
|
83
|
-
const canBatchTime = !runIsAsync && !pre && !post;
|
|
84
|
-
if (canBatchTime) {
|
|
85
|
-
const batchStart = hr();
|
|
86
|
-
if (nextNonce) {
|
|
87
|
-
for(let b = 0; b < batchSize; b++){
|
|
88
|
-
consume(runRaw(context, data, nextNonce()));
|
|
89
|
-
}
|
|
90
|
-
} else {
|
|
91
|
-
for(let b = 0; b < batchSize; b++){
|
|
92
|
-
consume(runRaw(context, data));
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
return (hr() - batchStart) * _typescjs.DURATION_SCALE / BigInt(batchSize);
|
|
96
|
-
}
|
|
97
|
-
let sampleDuration = 0n;
|
|
98
|
-
for(let b = 0; b < batchSize; b++){
|
|
99
|
-
if (pre) {
|
|
100
|
-
if (preIsAsync) {
|
|
101
|
-
await pre(context, data);
|
|
102
|
-
} else {
|
|
103
|
-
pre(context, data);
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
if (runIsAsync) {
|
|
107
|
-
const runAsyncFn = run;
|
|
108
|
-
const duration = nextNonce ? await runAsyncFn(context, data, nextNonce()) : await runAsyncFn(context, data);
|
|
109
|
-
sampleDuration += duration;
|
|
110
|
-
} else {
|
|
111
|
-
const runSyncFn = run;
|
|
112
|
-
const duration = nextNonce ? runSyncFn(context, data, nextNonce()) : runSyncFn(context, data);
|
|
113
|
-
sampleDuration += duration;
|
|
114
|
-
}
|
|
115
|
-
if (post) {
|
|
116
|
-
if (postIsAsync) {
|
|
117
|
-
await post(context, data);
|
|
118
|
-
} else {
|
|
119
|
-
post(context, data);
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
return sampleDuration * _typescjs.DURATION_SCALE / BigInt(batchSize);
|
|
124
|
-
};
|
|
125
|
-
const tuneParameters = async ({ initialBatch, run, runRaw, runIsAsync, pre, preIsAsync, post, postIsAsync, context, data, minCycles, relThreshold, maxCycles, nextNonce })=>{
|
|
126
|
-
let batchSize = initialBatch;
|
|
127
|
-
let bestCv = Number.POSITIVE_INFINITY;
|
|
128
|
-
let bestBatch = batchSize;
|
|
129
|
-
for(let attempt = 0; attempt < 3; attempt++){
|
|
130
|
-
const samples = [];
|
|
131
|
-
const sampleCount = Math.min(8, maxCycles);
|
|
132
|
-
for(let s = 0; s < sampleCount; s++){
|
|
133
|
-
const duration = await collectSample({
|
|
134
|
-
batchSize,
|
|
135
|
-
run,
|
|
136
|
-
runRaw,
|
|
137
|
-
runIsAsync,
|
|
138
|
-
pre,
|
|
139
|
-
preIsAsync,
|
|
140
|
-
post,
|
|
141
|
-
postIsAsync,
|
|
142
|
-
context,
|
|
143
|
-
data,
|
|
144
|
-
nextNonce
|
|
145
|
-
});
|
|
146
|
-
samples.push(Number(duration));
|
|
147
|
-
}
|
|
148
|
-
const mean = samples.reduce((acc, v)=>acc + v, 0) / samples.length;
|
|
149
|
-
const variance = samples.reduce((acc, v)=>acc + (v - mean) * (v - mean), 0) / Math.max(1, samples.length - 1);
|
|
150
|
-
const stddev = Math.sqrt(variance);
|
|
151
|
-
const cv = mean === 0 ? Number.POSITIVE_INFINITY : stddev / mean;
|
|
152
|
-
if (cv < bestCv) {
|
|
153
|
-
bestCv = cv;
|
|
154
|
-
bestBatch = batchSize;
|
|
155
|
-
}
|
|
156
|
-
if (cv <= relThreshold || batchSize >= MAX_BATCH) {
|
|
157
|
-
break;
|
|
158
|
-
}
|
|
159
|
-
batchSize = Math.min(MAX_BATCH, batchSize * 2);
|
|
160
|
-
}
|
|
161
|
-
const tunedRel = bestCv < relThreshold ? Math.max(bestCv * 1.5, relThreshold * 0.5) : relThreshold;
|
|
162
|
-
const tunedMin = Math.min(maxCycles, Math.max(minCycles, Math.ceil(minCycles * Math.max(1, bestCv / (relThreshold || 1e-6)))));
|
|
163
|
-
return {
|
|
164
|
-
batchSize: bestBatch,
|
|
165
|
-
relThreshold: tunedRel,
|
|
166
|
-
minCycles: tunedMin
|
|
167
|
-
};
|
|
168
|
-
};
|
|
169
|
-
const createGCTracker = ()=>{
|
|
170
|
-
if (process.env.OVERTAKE_GC_OBSERVER !== '1') {
|
|
171
|
-
return null;
|
|
172
|
-
}
|
|
173
|
-
if (typeof _nodeperf_hooks.PerformanceObserver === 'undefined') {
|
|
174
|
-
return null;
|
|
175
|
-
}
|
|
176
|
-
const events = [];
|
|
177
|
-
const observer = new _nodeperf_hooks.PerformanceObserver((list)=>{
|
|
178
|
-
for (const entry of list.getEntries()){
|
|
179
|
-
events.push({
|
|
180
|
-
start: entry.startTime,
|
|
181
|
-
end: entry.startTime + entry.duration
|
|
182
|
-
});
|
|
183
|
-
}
|
|
184
|
-
});
|
|
185
|
-
try {
|
|
186
|
-
observer.observe({
|
|
187
|
-
entryTypes: [
|
|
188
|
-
'gc'
|
|
189
|
-
]
|
|
190
|
-
});
|
|
191
|
-
} catch {
|
|
192
|
-
return null;
|
|
193
|
-
}
|
|
194
|
-
const overlaps = (start, end)=>{
|
|
195
|
-
let noisy = false;
|
|
196
|
-
for(let i = events.length - 1; i >= 0; i--){
|
|
197
|
-
const event = events[i];
|
|
198
|
-
if (event.end < start - 5_000) {
|
|
199
|
-
events.splice(i, 1);
|
|
200
|
-
continue;
|
|
201
|
-
}
|
|
202
|
-
if (event.start <= end && event.end >= start) {
|
|
203
|
-
noisy = true;
|
|
204
|
-
}
|
|
205
|
-
}
|
|
206
|
-
return noisy;
|
|
207
|
-
};
|
|
208
|
-
const dispose = ()=>observer.disconnect();
|
|
209
|
-
return {
|
|
210
|
-
overlaps,
|
|
211
|
-
dispose
|
|
212
|
-
};
|
|
213
|
-
};
|
|
214
|
-
const pushWindow = (arr, value, cap)=>{
|
|
215
|
-
if (arr.length === cap) {
|
|
216
|
-
arr.shift();
|
|
217
|
-
}
|
|
218
|
-
arr.push(value);
|
|
219
|
-
};
|
|
220
|
-
const medianAndIqr = (arr)=>{
|
|
221
|
-
if (arr.length === 0) return {
|
|
222
|
-
median: 0,
|
|
223
|
-
iqr: 0
|
|
224
|
-
};
|
|
225
|
-
for(let i = 0; i < arr.length; i++){
|
|
226
|
-
OUTLIER_SCRATCH[i] = arr[i];
|
|
227
|
-
}
|
|
228
|
-
const view = OUTLIER_SCRATCH.subarray(0, arr.length);
|
|
229
|
-
view.sort();
|
|
230
|
-
const mid = Math.floor(view.length / 2);
|
|
231
|
-
const median = view.length % 2 === 0 ? (view[mid - 1] + view[mid]) / 2 : view[mid];
|
|
232
|
-
const q1Idx = Math.floor(view.length * 0.25);
|
|
233
|
-
const q3Idx = Math.floor(view.length * 0.75);
|
|
234
|
-
const q1 = view[q1Idx];
|
|
235
|
-
const q3 = view[q3Idx];
|
|
236
|
-
return {
|
|
237
|
-
median,
|
|
238
|
-
iqr: q3 - q1
|
|
239
|
-
};
|
|
240
|
-
};
|
|
241
|
-
const windowCv = (arr)=>{
|
|
242
|
-
if (arr.length < 2) return Number.POSITIVE_INFINITY;
|
|
243
|
-
const mean = arr.reduce((a, v)=>a + v, 0) / arr.length;
|
|
244
|
-
const variance = arr.reduce((a, v)=>a + (v - mean) * (v - mean), 0) / (arr.length - 1);
|
|
245
|
-
const stddev = Math.sqrt(variance);
|
|
246
|
-
return mean === 0 ? Number.POSITIVE_INFINITY : stddev / mean;
|
|
247
|
-
};
|
|
248
|
-
const benchmark = async ({ setup, teardown, pre, run: runRaw, post, data, warmupCycles, minCycles, absThreshold, relThreshold, gcObserver = false, durationsSAB, controlSAB })=>{
|
|
249
|
-
const durations = new BigUint64Array(durationsSAB);
|
|
250
|
-
const control = new Int32Array(controlSAB);
|
|
251
|
-
control[_typescjs.Control.INDEX] = 0;
|
|
252
|
-
control[_typescjs.Control.PROGRESS] = 0;
|
|
253
|
-
control[_typescjs.Control.COMPLETE] = 255;
|
|
254
|
-
control[_typescjs.Control.HEAP_USED] = 0;
|
|
255
|
-
const context = await setup?.();
|
|
256
|
-
const heapBefore = process.memoryUsage().heapUsed;
|
|
257
|
-
const input = data;
|
|
258
|
-
const maxCycles = durations.length;
|
|
259
|
-
const gcWatcher = gcObserver ? new _gcwatchercjs.GCWatcher() : null;
|
|
260
|
-
const gcTracker = gcObserver ? createGCTracker() : null;
|
|
261
|
-
try {
|
|
262
|
-
let preIsAsync = false;
|
|
263
|
-
if (pre) {
|
|
264
|
-
const preResult = pre(context, input);
|
|
265
|
-
preIsAsync = isThenable(preResult);
|
|
266
|
-
if (preIsAsync) {
|
|
267
|
-
await preResult;
|
|
268
|
-
}
|
|
269
|
-
}
|
|
270
|
-
const probeStart = hr();
|
|
271
|
-
const probeResult = runRaw(context, input);
|
|
272
|
-
const runIsAsync = isThenable(probeResult);
|
|
273
|
-
if (runIsAsync) {
|
|
274
|
-
const resolved = await probeResult;
|
|
275
|
-
consume(resolved);
|
|
276
|
-
} else {
|
|
277
|
-
consume(probeResult);
|
|
278
|
-
}
|
|
279
|
-
const durationProbeRaw = hr() - probeStart;
|
|
280
|
-
let postIsAsync = false;
|
|
281
|
-
if (post) {
|
|
282
|
-
const postResult = post(context, input);
|
|
283
|
-
postIsAsync = isThenable(postResult);
|
|
284
|
-
if (postIsAsync) {
|
|
285
|
-
await postResult;
|
|
286
|
-
}
|
|
287
|
-
}
|
|
288
|
-
const timerOverhead = runIsAsync ? 0n : measureTimerOverhead();
|
|
289
|
-
let durationProbe = runIsAsync ? durationProbeRaw : durationProbeRaw > timerOverhead ? durationProbeRaw - timerOverhead : 0n;
|
|
290
|
-
const shouldPerturbInput = process.env.OVERTAKE_PERTURB_INPUT === '1';
|
|
291
|
-
let nonce = 0;
|
|
292
|
-
const nextNonce = shouldPerturbInput ? ()=>{
|
|
293
|
-
nonce = nonce + 1 | 0;
|
|
294
|
-
return nonce;
|
|
295
|
-
} : null;
|
|
296
|
-
if (!runIsAsync && !pre && !post) {
|
|
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();
|
|
301
|
-
if (nextNonce) {
|
|
302
|
-
for(let i = 0; i < INITIAL_PROBE_SIZE; i++){
|
|
303
|
-
consume(runRaw(context, input, nextNonce()));
|
|
304
|
-
}
|
|
305
|
-
} else {
|
|
306
|
-
for(let i = 0; i < INITIAL_PROBE_SIZE; i++){
|
|
307
|
-
consume(runRaw(context, input));
|
|
308
|
-
}
|
|
309
|
-
}
|
|
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);
|
|
329
|
-
}
|
|
330
|
-
const runTimedSync = runIsAsync ? null : runSync(runRaw, timerOverhead);
|
|
331
|
-
const runTimedAsync = runIsAsync ? runAsync(runRaw) : null;
|
|
332
|
-
const run = runIsAsync ? runTimedAsync : runTimedSync;
|
|
333
|
-
const runOnceSync = runIsAsync ? null : nextNonce ? (ctx, dataValue)=>runTimedSync(ctx, dataValue, nextNonce()) : runTimedSync;
|
|
334
|
-
const runOnceAsync = runIsAsync ? nextNonce ? (ctx, dataValue)=>runTimedAsync(ctx, dataValue, nextNonce()) : runTimedAsync : null;
|
|
335
|
-
const preSync = preIsAsync ? null : pre;
|
|
336
|
-
const preAsync = preIsAsync ? pre : null;
|
|
337
|
-
const postSync = postIsAsync ? null : post;
|
|
338
|
-
const postAsync = postIsAsync ? post : null;
|
|
339
|
-
const durationPerRun = durationProbe === 0n ? 1n : durationProbe;
|
|
340
|
-
const suggestedBatch = Number(TARGET_SAMPLE_NS / durationPerRun);
|
|
341
|
-
const minBatchForFastOps = durationProbe < 100n ? 100_000 : 1;
|
|
342
|
-
const initialBatchSize = Math.min(MAX_BATCH, Math.max(minBatchForFastOps, suggestedBatch));
|
|
343
|
-
const tuned = await tuneParameters({
|
|
344
|
-
initialBatch: initialBatchSize,
|
|
345
|
-
run,
|
|
346
|
-
runRaw,
|
|
347
|
-
runIsAsync,
|
|
348
|
-
pre,
|
|
349
|
-
preIsAsync,
|
|
350
|
-
post,
|
|
351
|
-
postIsAsync,
|
|
352
|
-
context,
|
|
353
|
-
data: input,
|
|
354
|
-
minCycles,
|
|
355
|
-
relThreshold,
|
|
356
|
-
maxCycles,
|
|
357
|
-
nextNonce
|
|
358
|
-
});
|
|
359
|
-
let batchSize = tuned.batchSize;
|
|
360
|
-
minCycles = tuned.minCycles;
|
|
361
|
-
relThreshold = tuned.relThreshold;
|
|
362
|
-
const warmupStart = _nodeperf_hooks.performance.now();
|
|
363
|
-
let warmupRemaining = warmupCycles;
|
|
364
|
-
const warmupWindow = [];
|
|
365
|
-
const warmupCap = Math.max(warmupCycles, Math.min(maxCycles, warmupCycles * 4 || 1000));
|
|
366
|
-
const canBatchTime = !runIsAsync && !preSync && !preAsync && !postSync && !postAsync;
|
|
367
|
-
const runWarmup = async ()=>{
|
|
368
|
-
if (canBatchTime) {
|
|
369
|
-
const batchStart = hr();
|
|
370
|
-
if (nextNonce) {
|
|
371
|
-
for(let b = 0; b < batchSize; b++){
|
|
372
|
-
consume(runRaw(context, input, nextNonce()));
|
|
373
|
-
}
|
|
374
|
-
} else {
|
|
375
|
-
for(let b = 0; b < batchSize; b++){
|
|
376
|
-
consume(runRaw(context, input));
|
|
377
|
-
}
|
|
378
|
-
}
|
|
379
|
-
return (hr() - batchStart) * _typescjs.DURATION_SCALE / BigInt(batchSize);
|
|
380
|
-
}
|
|
381
|
-
if (preSync) {
|
|
382
|
-
preSync(context, input);
|
|
383
|
-
} else if (preAsync) {
|
|
384
|
-
await preAsync(context, input);
|
|
385
|
-
}
|
|
386
|
-
const duration = runIsAsync ? await runOnceAsync(context, input) : runOnceSync(context, input);
|
|
387
|
-
if (postSync) {
|
|
388
|
-
postSync(context, input);
|
|
389
|
-
} else if (postAsync) {
|
|
390
|
-
await postAsync(context, input);
|
|
391
|
-
}
|
|
392
|
-
return duration * _typescjs.DURATION_SCALE;
|
|
393
|
-
};
|
|
394
|
-
while(_nodeperf_hooks.performance.now() - warmupStart < 1_000 && warmupRemaining > 0){
|
|
395
|
-
const duration = await runWarmup();
|
|
396
|
-
pushWindow(warmupWindow, Number(duration), warmupCap);
|
|
397
|
-
warmupRemaining--;
|
|
398
|
-
}
|
|
399
|
-
let warmupDone = 0;
|
|
400
|
-
while(warmupDone < warmupRemaining){
|
|
401
|
-
const duration = await runWarmup();
|
|
402
|
-
pushWindow(warmupWindow, Number(duration), warmupCap);
|
|
403
|
-
warmupDone++;
|
|
404
|
-
if (global.gc && warmupDone % GC_STRIDE === 0) {
|
|
405
|
-
global.gc();
|
|
406
|
-
}
|
|
407
|
-
}
|
|
408
|
-
while(warmupWindow.length >= 8 && warmupWindow.length < warmupCap){
|
|
409
|
-
const cv = windowCv(warmupWindow);
|
|
410
|
-
if (cv <= relThreshold * 2) {
|
|
411
|
-
break;
|
|
412
|
-
}
|
|
413
|
-
const duration = await runWarmup();
|
|
414
|
-
pushWindow(warmupWindow, Number(duration), warmupCap);
|
|
415
|
-
}
|
|
416
|
-
let i = 0;
|
|
417
|
-
const WELFORD_SCALE = 1_000_000n;
|
|
418
|
-
let meanS = 0n;
|
|
419
|
-
let m2S = 0n;
|
|
420
|
-
const outlierWindow = [];
|
|
421
|
-
let skipped = 0;
|
|
422
|
-
const maxSkipped = maxCycles * 10;
|
|
423
|
-
let disableFiltering = false;
|
|
424
|
-
const absThScaled = BigInt(Math.round(absThreshold)) * WELFORD_SCALE;
|
|
425
|
-
const absThSq = absThScaled * absThScaled;
|
|
426
|
-
const REL_PRECISION = 1_000_000n;
|
|
427
|
-
const relThBigint = BigInt(Math.round(relThreshold * Number(REL_PRECISION)));
|
|
428
|
-
const relThSq = relThBigint * relThBigint;
|
|
429
|
-
const relPrecSq = REL_PRECISION * REL_PRECISION;
|
|
430
|
-
const Z95_SQ_NUM = 38416n;
|
|
431
|
-
const Z95_SQ_DENOM = 10000n;
|
|
432
|
-
while(true){
|
|
433
|
-
if (i >= maxCycles) break;
|
|
434
|
-
if (!disableFiltering && skipped >= maxSkipped) {
|
|
435
|
-
console.error(`Warning: ${skipped} samples skipped due to noise/outlier detection. ` + `Disabling filtering for remaining samples. Results may have higher variance.`);
|
|
436
|
-
disableFiltering = true;
|
|
437
|
-
}
|
|
438
|
-
if (global.gc && i > 0 && i % GC_STRIDE === 0) {
|
|
439
|
-
global.gc();
|
|
440
|
-
}
|
|
441
|
-
const gcMarker = gcWatcher?.start();
|
|
442
|
-
const sampleStart = _nodeperf_hooks.performance.now();
|
|
443
|
-
let sampleDuration = 0n;
|
|
444
|
-
if (canBatchTime) {
|
|
445
|
-
const batchStart = hr();
|
|
446
|
-
if (nextNonce) {
|
|
447
|
-
for(let b = 0; b < batchSize; b++){
|
|
448
|
-
consume(runRaw(context, input, nextNonce()));
|
|
449
|
-
}
|
|
450
|
-
} else {
|
|
451
|
-
for(let b = 0; b < batchSize; b++){
|
|
452
|
-
consume(runRaw(context, input));
|
|
453
|
-
}
|
|
454
|
-
}
|
|
455
|
-
const batchDuration = hr() - batchStart;
|
|
456
|
-
sampleDuration = batchDuration * _typescjs.DURATION_SCALE / BigInt(batchSize);
|
|
457
|
-
} else {
|
|
458
|
-
for(let b = 0; b < batchSize; b++){
|
|
459
|
-
if (preSync) {
|
|
460
|
-
preSync(context, input);
|
|
461
|
-
} else if (preAsync) {
|
|
462
|
-
await preAsync(context, input);
|
|
463
|
-
}
|
|
464
|
-
const duration = runIsAsync ? await runOnceAsync(context, input) : runOnceSync(context, input);
|
|
465
|
-
sampleDuration += duration;
|
|
466
|
-
if (postSync) {
|
|
467
|
-
postSync(context, input);
|
|
468
|
-
} else if (postAsync) {
|
|
469
|
-
await postAsync(context, input);
|
|
470
|
-
}
|
|
471
|
-
}
|
|
472
|
-
sampleDuration = sampleDuration * _typescjs.DURATION_SCALE / BigInt(batchSize);
|
|
473
|
-
}
|
|
474
|
-
const sampleEnd = _nodeperf_hooks.performance.now();
|
|
475
|
-
if (!disableFiltering) {
|
|
476
|
-
const gcNoise = (gcMarker ? gcWatcher.seen(gcMarker) : false) || (gcTracker?.overlaps(sampleStart, sampleEnd) ?? false);
|
|
477
|
-
if (gcNoise) {
|
|
478
|
-
skipped++;
|
|
479
|
-
continue;
|
|
480
|
-
}
|
|
481
|
-
}
|
|
482
|
-
const durationNumber = Number(sampleDuration);
|
|
483
|
-
if (!disableFiltering) {
|
|
484
|
-
const { median, iqr } = medianAndIqr(outlierWindow);
|
|
485
|
-
pushWindow(outlierWindow, durationNumber, OUTLIER_WINDOW);
|
|
486
|
-
const maxAllowed = median + OUTLIER_IQR_MULTIPLIER * iqr || Number.POSITIVE_INFINITY;
|
|
487
|
-
if (outlierWindow.length >= 8 && durationNumber > maxAllowed && durationNumber - median > OUTLIER_ABS_THRESHOLD) {
|
|
488
|
-
skipped++;
|
|
489
|
-
continue;
|
|
490
|
-
}
|
|
491
|
-
const meanNumber = Number(meanS / WELFORD_SCALE);
|
|
492
|
-
if (i >= 8 && meanNumber > 0 && durationNumber > OUTLIER_MULTIPLIER * meanNumber && durationNumber - meanNumber > OUTLIER_ABS_THRESHOLD) {
|
|
493
|
-
skipped++;
|
|
494
|
-
continue;
|
|
495
|
-
}
|
|
496
|
-
} else {
|
|
497
|
-
pushWindow(outlierWindow, durationNumber, OUTLIER_WINDOW);
|
|
498
|
-
}
|
|
499
|
-
durations[i++] = sampleDuration;
|
|
500
|
-
const deltaS = sampleDuration * WELFORD_SCALE - meanS;
|
|
501
|
-
meanS += deltaS / BigInt(i);
|
|
502
|
-
m2S += deltaS * (sampleDuration * WELFORD_SCALE - meanS);
|
|
503
|
-
const progress = i / maxCycles * COMPLETE_VALUE;
|
|
504
|
-
if (i % PROGRESS_STRIDE === 0) {
|
|
505
|
-
control[_typescjs.Control.PROGRESS] = progress;
|
|
506
|
-
}
|
|
507
|
-
if (i >= minCycles) {
|
|
508
|
-
if (m2S <= absThSq * BigInt(i - 1)) break;
|
|
509
|
-
const ni = BigInt(i);
|
|
510
|
-
if (meanS !== 0n && Z95_SQ_NUM * m2S * relPrecSq <= relThSq * ni * (ni - 1n) * meanS * meanS * Z95_SQ_DENOM) break;
|
|
511
|
-
}
|
|
512
|
-
}
|
|
513
|
-
control[_typescjs.Control.INDEX] = i;
|
|
514
|
-
control[_typescjs.Control.COMPLETE] = 0;
|
|
515
|
-
const heapAfter = process.memoryUsage().heapUsed;
|
|
516
|
-
control[_typescjs.Control.HEAP_USED] = Math.max(0, Math.round((heapAfter - heapBefore) / 1024));
|
|
517
|
-
} catch (e) {
|
|
518
|
-
console.error(e && typeof e === 'object' && 'stack' in e ? e.stack : e);
|
|
519
|
-
control[_typescjs.Control.COMPLETE] = 1;
|
|
520
|
-
} finally{
|
|
521
|
-
gcTracker?.dispose?.();
|
|
522
|
-
try {
|
|
523
|
-
await teardown?.(context);
|
|
524
|
-
} catch (e) {
|
|
525
|
-
control[_typescjs.Control.COMPLETE] = 2;
|
|
526
|
-
console.error(e && typeof e === 'object' && 'stack' in e ? e.stack : e);
|
|
527
|
-
}
|
|
528
|
-
}
|
|
529
|
-
return control[_typescjs.Control.COMPLETE];
|
|
530
|
-
};
|
|
531
|
-
|
|
532
|
-
//# sourceMappingURL=runner.cjs.map
|
package/build/runner.cjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/runner.ts"],"sourcesContent":["import { performance, PerformanceObserver } from 'node:perf_hooks';\nimport { Options, Control, DURATION_SCALE } from './types.js';\nimport { GCWatcher } from './gc-watcher.js';\nimport { StepFn } from './types.js';\n\nconst COMPLETE_VALUE = 100_00;\n\nconst hr = process.hrtime.bigint.bind(process.hrtime);\n\nconst sink = new Int32Array(1);\nconst consume = (value: unknown) => {\n let payload = 0;\n switch (typeof value) {\n case 'number':\n payload = Number.isFinite(value) ? Math.trunc(value) : 0;\n break;\n case 'bigint':\n payload = Number(value & 0xffff_ffffn);\n break;\n case 'string':\n payload = value.length;\n break;\n case 'boolean':\n payload = value ? 1 : 0;\n break;\n case 'object':\n payload = value === null ? 0 : 1;\n break;\n case 'function':\n payload = 1;\n break;\n default:\n payload = -1;\n }\n sink[0] ^= payload;\n};\n\nconst runSync = (run: Function, overhead: bigint) => {\n return (...args: unknown[]) => {\n const start = hr();\n const result = run(...args);\n consume(result);\n const duration = hr() - start;\n return duration > overhead ? duration - overhead : 0n;\n };\n};\n\nconst runAsync = (run: Function) => {\n return async (...args: unknown[]) => {\n const start = hr();\n const result = await run(...args);\n consume(result);\n return hr() - start;\n };\n};\n\nconst isThenable = (value: unknown): value is PromiseLike<unknown> => {\n return value !== null && (typeof value === 'object' || typeof value === 'function') && typeof (value as PromiseLike<unknown>).then === 'function';\n};\n\nconst TARGET_SAMPLE_NS = 1_000_000n; // aim for ~1ms per measured sample\nconst MAX_BATCH = 1_048_576;\nconst PROGRESS_STRIDE = 16;\nconst GC_STRIDE = 32;\nconst OUTLIER_MULTIPLIER = 4;\nconst OUTLIER_IQR_MULTIPLIER = 3;\nconst OUTLIER_WINDOW = 64;\nconst OUTLIER_ABS_THRESHOLD = 10_000_000;\nconst BASELINE_SAMPLES = 16;\nconst OUTLIER_SCRATCH = new Float64Array(OUTLIER_WINDOW);\n\ntype GCEvent = { start: number; end: number };\ntype RunTimedSync<TContext, TInput> = (ctx: TContext, data: TInput, nonce?: number) => bigint;\ntype RunTimedAsync<TContext, TInput> = (ctx: TContext, data: TInput, nonce?: number) => Promise<bigint>;\n\nconst measureTimerOverhead = () => {\n let total = 0n;\n for (let i = 0; i < BASELINE_SAMPLES; i++) {\n const start = hr();\n consume(0);\n total += hr() - start;\n }\n return total / BigInt(BASELINE_SAMPLES);\n};\n\nconst collectSample = async <TContext, TInput>({\n batchSize,\n run,\n runRaw,\n runIsAsync,\n pre,\n preIsAsync,\n post,\n postIsAsync,\n context,\n data,\n nextNonce,\n}: {\n batchSize: number;\n run: RunTimedSync<TContext, TInput> | RunTimedAsync<TContext, TInput>;\n runRaw: StepFn<TContext, TInput>;\n runIsAsync: boolean;\n pre: StepFn<TContext, TInput> | undefined;\n preIsAsync: boolean;\n post: StepFn<TContext, TInput> | undefined;\n postIsAsync: boolean;\n context: TContext;\n data: TInput;\n nextNonce: (() => number) | null;\n}) => {\n const canBatchTime = !runIsAsync && !pre && !post;\n if (canBatchTime) {\n const batchStart = hr();\n if (nextNonce) {\n for (let b = 0; b < batchSize; b++) {\n consume((runRaw as Function)(context, data, nextNonce()));\n }\n } else {\n for (let b = 0; b < batchSize; b++) {\n consume(runRaw(context, data));\n }\n }\n return ((hr() - batchStart) * DURATION_SCALE) / BigInt(batchSize);\n }\n\n let sampleDuration = 0n;\n for (let b = 0; b < batchSize; b++) {\n if (pre) {\n if (preIsAsync) {\n await pre(context, data);\n } else {\n pre(context, data);\n }\n }\n\n if (runIsAsync) {\n const runAsyncFn = run as RunTimedAsync<TContext, TInput>;\n const duration = nextNonce ? await runAsyncFn(context, data, nextNonce()) : await runAsyncFn(context, data);\n sampleDuration += duration;\n } else {\n const runSyncFn = run as RunTimedSync<TContext, TInput>;\n const duration = nextNonce ? runSyncFn(context, data, nextNonce()) : runSyncFn(context, data);\n sampleDuration += duration;\n }\n\n if (post) {\n if (postIsAsync) {\n await post(context, data);\n } else {\n post(context, data);\n }\n }\n }\n return (sampleDuration * DURATION_SCALE) / BigInt(batchSize);\n};\n\nconst tuneParameters = async <TContext, TInput>({\n initialBatch,\n run,\n runRaw,\n runIsAsync,\n pre,\n preIsAsync,\n post,\n postIsAsync,\n context,\n data,\n minCycles,\n relThreshold,\n maxCycles,\n nextNonce,\n}: {\n initialBatch: number;\n run: RunTimedSync<TContext, TInput> | RunTimedAsync<TContext, TInput>;\n runRaw: StepFn<TContext, TInput>;\n runIsAsync: boolean;\n pre?: StepFn<TContext, TInput>;\n preIsAsync: boolean;\n post?: StepFn<TContext, TInput>;\n postIsAsync: boolean;\n context: TContext;\n data: TInput;\n minCycles: number;\n relThreshold: number;\n maxCycles: number;\n nextNonce: (() => number) | null;\n}) => {\n let batchSize = initialBatch;\n let bestCv = Number.POSITIVE_INFINITY;\n let bestBatch = batchSize;\n\n for (let attempt = 0; attempt < 3; attempt++) {\n const samples: number[] = [];\n const sampleCount = Math.min(8, maxCycles);\n for (let s = 0; s < sampleCount; s++) {\n const duration = await collectSample({\n batchSize,\n run,\n runRaw,\n runIsAsync,\n pre,\n preIsAsync,\n post,\n postIsAsync,\n context,\n data,\n nextNonce,\n });\n samples.push(Number(duration));\n }\n const mean = samples.reduce((acc, v) => acc + v, 0) / samples.length;\n const variance = samples.reduce((acc, v) => acc + (v - mean) * (v - mean), 0) / Math.max(1, samples.length - 1);\n const stddev = Math.sqrt(variance);\n const cv = mean === 0 ? Number.POSITIVE_INFINITY : stddev / mean;\n\n if (cv < bestCv) {\n bestCv = cv;\n bestBatch = batchSize;\n }\n\n if (cv <= relThreshold || batchSize >= MAX_BATCH) {\n break;\n }\n batchSize = Math.min(MAX_BATCH, batchSize * 2);\n }\n\n const tunedRel = bestCv < relThreshold ? Math.max(bestCv * 1.5, relThreshold * 0.5) : relThreshold;\n const tunedMin = Math.min(maxCycles, Math.max(minCycles, Math.ceil(minCycles * Math.max(1, bestCv / (relThreshold || 1e-6)))));\n\n return { batchSize: bestBatch, relThreshold: tunedRel, minCycles: tunedMin };\n};\n\nconst createGCTracker = () => {\n if (process.env.OVERTAKE_GC_OBSERVER !== '1') {\n return null;\n }\n if (typeof PerformanceObserver === 'undefined') {\n return null;\n }\n\n const events: GCEvent[] = [];\n const observer = new PerformanceObserver((list) => {\n for (const entry of list.getEntries()) {\n events.push({ start: entry.startTime, end: entry.startTime + entry.duration });\n }\n });\n\n try {\n observer.observe({ entryTypes: ['gc'] });\n } catch {\n return null;\n }\n\n const overlaps = (start: number, end: number) => {\n let noisy = false;\n for (let i = events.length - 1; i >= 0; i--) {\n const event = events[i];\n if (event.end < start - 5_000) {\n events.splice(i, 1);\n continue;\n }\n if (event.start <= end && event.end >= start) {\n noisy = true;\n }\n }\n return noisy;\n };\n\n const dispose = () => observer.disconnect();\n\n return { overlaps, dispose };\n};\n\nconst pushWindow = (arr: number[], value: number, cap: number) => {\n if (arr.length === cap) {\n arr.shift();\n }\n arr.push(value);\n};\n\nconst medianAndIqr = (arr: number[]) => {\n if (arr.length === 0) return { median: 0, iqr: 0 };\n for (let i = 0; i < arr.length; i++) {\n OUTLIER_SCRATCH[i] = arr[i];\n }\n const view = OUTLIER_SCRATCH.subarray(0, arr.length);\n view.sort();\n const mid = Math.floor(view.length / 2);\n const median = view.length % 2 === 0 ? (view[mid - 1] + view[mid]) / 2 : view[mid];\n const q1Idx = Math.floor(view.length * 0.25);\n const q3Idx = Math.floor(view.length * 0.75);\n const q1 = view[q1Idx];\n const q3 = view[q3Idx];\n return { median, iqr: q3 - q1 };\n};\n\nconst windowCv = (arr: number[]) => {\n if (arr.length < 2) return Number.POSITIVE_INFINITY;\n const mean = arr.reduce((a, v) => a + v, 0) / arr.length;\n const variance = arr.reduce((a, v) => a + (v - mean) * (v - mean), 0) / (arr.length - 1);\n const stddev = Math.sqrt(variance);\n return mean === 0 ? Number.POSITIVE_INFINITY : stddev / mean;\n};\n\nexport const benchmark = async <TContext, TInput>({\n setup,\n teardown,\n pre,\n run: runRaw,\n post,\n data,\n\n warmupCycles,\n minCycles,\n absThreshold,\n relThreshold,\n gcObserver = false,\n\n durationsSAB,\n controlSAB,\n}: Required<Options<TContext, TInput>>) => {\n const durations = new BigUint64Array(durationsSAB);\n const control = new Int32Array(controlSAB);\n\n control[Control.INDEX] = 0;\n control[Control.PROGRESS] = 0;\n control[Control.COMPLETE] = 255;\n control[Control.HEAP_USED] = 0;\n\n const context = (await setup?.()) as TContext;\n const heapBefore = process.memoryUsage().heapUsed;\n const input = data as TInput;\n const maxCycles = durations.length;\n const gcWatcher = gcObserver ? new GCWatcher() : null;\n const gcTracker = gcObserver ? createGCTracker() : null;\n\n try {\n // classify sync/async and capture initial duration\n let preIsAsync = false;\n if (pre) {\n const preResult = pre(context, input);\n preIsAsync = isThenable(preResult);\n if (preIsAsync) {\n await preResult;\n }\n }\n\n const probeStart = hr();\n const probeResult = runRaw(context, input);\n const runIsAsync = isThenable(probeResult);\n if (runIsAsync) {\n const resolved = await probeResult;\n consume(resolved);\n } else {\n consume(probeResult);\n }\n const durationProbeRaw = hr() - probeStart;\n\n let postIsAsync = false;\n if (post) {\n const postResult = post(context, input);\n postIsAsync = isThenable(postResult);\n if (postIsAsync) {\n await postResult;\n }\n }\n\n const timerOverhead = runIsAsync ? 0n : measureTimerOverhead();\n let durationProbe = runIsAsync ? durationProbeRaw : durationProbeRaw > timerOverhead ? durationProbeRaw - timerOverhead : 0n;\n\n const shouldPerturbInput = process.env.OVERTAKE_PERTURB_INPUT === '1';\n let nonce = 0;\n const nextNonce = shouldPerturbInput\n ? () => {\n nonce = (nonce + 1) | 0;\n return nonce;\n }\n : null;\n\n if (!runIsAsync && !pre && !post) {\n const PROBE_TIME_LIMIT_NS = 1_000_000_000n;\n const INITIAL_PROBE_SIZE = 10;\n const MAX_PROBE_SIZE = 10_000;\n\n const initialStart = hr();\n if (nextNonce) {\n for (let i = 0; i < INITIAL_PROBE_SIZE; i++) {\n consume((runRaw as Function)(context, input, nextNonce()));\n }\n } else {\n for (let i = 0; i < INITIAL_PROBE_SIZE; i++) {\n consume(runRaw(context, input));\n }\n }\n const initialDuration = hr() - initialStart;\n const estimatedPerOp = initialDuration / BigInt(INITIAL_PROBE_SIZE);\n\n const remainingBudget = PROBE_TIME_LIMIT_NS - initialDuration;\n const additionalIterations = estimatedPerOp > 0n ? Number(remainingBudget / estimatedPerOp) : MAX_PROBE_SIZE - INITIAL_PROBE_SIZE;\n const cappedAdditional = Math.min(Math.max(0, additionalIterations), MAX_PROBE_SIZE - INITIAL_PROBE_SIZE);\n\n let totalIterations = INITIAL_PROBE_SIZE;\n if (cappedAdditional > 0) {\n if (nextNonce) {\n for (let i = 0; i < cappedAdditional; i++) {\n consume((runRaw as Function)(context, input, nextNonce()));\n }\n } else {\n for (let i = 0; i < cappedAdditional; i++) {\n consume(runRaw(context, input));\n }\n }\n totalIterations += cappedAdditional;\n }\n\n durationProbe = (hr() - initialStart) / BigInt(totalIterations);\n }\n\n const runTimedSync = runIsAsync ? null : runSync(runRaw, timerOverhead);\n const runTimedAsync = runIsAsync ? runAsync(runRaw) : null;\n const run = runIsAsync ? runTimedAsync! : runTimedSync!;\n\n const runOnceSync: RunTimedSync<TContext, TInput> | null = runIsAsync ? null : nextNonce ? (ctx, dataValue) => runTimedSync!(ctx, dataValue, nextNonce()) : runTimedSync!;\n const runOnceAsync: RunTimedAsync<TContext, TInput> | null = runIsAsync ? (nextNonce ? (ctx, dataValue) => runTimedAsync!(ctx, dataValue, nextNonce()) : runTimedAsync!) : null;\n\n const preSync = preIsAsync ? null : pre;\n const preAsync = preIsAsync ? pre : null;\n const postSync = postIsAsync ? null : post;\n const postAsync = postIsAsync ? post : null;\n\n // choose batch size to amortize timer overhead\n const durationPerRun = durationProbe === 0n ? 1n : durationProbe;\n const suggestedBatch = Number(TARGET_SAMPLE_NS / durationPerRun);\n const minBatchForFastOps = durationProbe < 100n ? 100_000 : 1;\n const initialBatchSize = Math.min(MAX_BATCH, Math.max(minBatchForFastOps, suggestedBatch));\n\n // auto-tune based on warmup samples\n const tuned = await tuneParameters({\n initialBatch: initialBatchSize,\n run,\n runRaw,\n runIsAsync,\n pre,\n preIsAsync,\n post,\n postIsAsync,\n context,\n data: input,\n minCycles,\n relThreshold,\n maxCycles,\n nextNonce,\n });\n let batchSize = tuned.batchSize;\n minCycles = tuned.minCycles;\n relThreshold = tuned.relThreshold;\n\n // warmup: run until requested cycles, adapt if unstable\n const warmupStart = performance.now();\n let warmupRemaining = warmupCycles;\n const warmupWindow: number[] = [];\n const warmupCap = Math.max(warmupCycles, Math.min(maxCycles, warmupCycles * 4 || 1000));\n const canBatchTime = !runIsAsync && !preSync && !preAsync && !postSync && !postAsync;\n\n const runWarmup = async () => {\n if (canBatchTime) {\n const batchStart = hr();\n if (nextNonce) {\n for (let b = 0; b < batchSize; b++) {\n consume((runRaw as Function)(context, input, nextNonce()));\n }\n } else {\n for (let b = 0; b < batchSize; b++) {\n consume(runRaw(context, input));\n }\n }\n return ((hr() - batchStart) * DURATION_SCALE) / BigInt(batchSize);\n }\n\n if (preSync) {\n preSync(context, input);\n } else if (preAsync) {\n await preAsync(context, input);\n }\n\n const duration = runIsAsync ? await runOnceAsync!(context, input) : runOnceSync!(context, input);\n\n if (postSync) {\n postSync(context, input);\n } else if (postAsync) {\n await postAsync(context, input);\n }\n\n return duration * DURATION_SCALE;\n };\n\n while (performance.now() - warmupStart < 1_000 && warmupRemaining > 0) {\n const duration = await runWarmup();\n pushWindow(warmupWindow, Number(duration), warmupCap);\n warmupRemaining--;\n }\n let warmupDone = 0;\n while (warmupDone < warmupRemaining) {\n const duration = await runWarmup();\n pushWindow(warmupWindow, Number(duration), warmupCap);\n warmupDone++;\n if (global.gc && warmupDone % GC_STRIDE === 0) {\n global.gc();\n }\n }\n while (warmupWindow.length >= 8 && warmupWindow.length < warmupCap) {\n const cv = windowCv(warmupWindow);\n if (cv <= relThreshold * 2) {\n break;\n }\n const duration = await runWarmup();\n pushWindow(warmupWindow, Number(duration), warmupCap);\n }\n\n let i = 0;\n const WELFORD_SCALE = 1_000_000n;\n let meanS = 0n;\n let m2S = 0n;\n const outlierWindow: number[] = [];\n let skipped = 0;\n const maxSkipped = maxCycles * 10;\n let disableFiltering = false;\n\n const absThScaled = BigInt(Math.round(absThreshold)) * WELFORD_SCALE;\n const absThSq = absThScaled * absThScaled;\n const REL_PRECISION = 1_000_000n;\n const relThBigint = BigInt(Math.round(relThreshold * Number(REL_PRECISION)));\n const relThSq = relThBigint * relThBigint;\n const relPrecSq = REL_PRECISION * REL_PRECISION;\n const Z95_SQ_NUM = 38416n;\n const Z95_SQ_DENOM = 10000n;\n\n while (true) {\n if (i >= maxCycles) break;\n if (!disableFiltering && skipped >= maxSkipped) {\n console.error(`Warning: ${skipped} samples skipped due to noise/outlier detection. ` + `Disabling filtering for remaining samples. Results may have higher variance.`);\n disableFiltering = true;\n }\n\n if (global.gc && i > 0 && i % GC_STRIDE === 0) {\n global.gc();\n }\n\n const gcMarker = gcWatcher?.start();\n const sampleStart = performance.now();\n let sampleDuration = 0n;\n\n if (canBatchTime) {\n const batchStart = hr();\n if (nextNonce) {\n for (let b = 0; b < batchSize; b++) {\n consume((runRaw as Function)(context, input, nextNonce()));\n }\n } else {\n for (let b = 0; b < batchSize; b++) {\n consume(runRaw(context, input));\n }\n }\n const batchDuration = hr() - batchStart;\n sampleDuration = (batchDuration * DURATION_SCALE) / BigInt(batchSize);\n } else {\n for (let b = 0; b < batchSize; b++) {\n if (preSync) {\n preSync(context, input);\n } else if (preAsync) {\n await preAsync(context, input);\n }\n\n const duration = runIsAsync ? await runOnceAsync!(context, input) : runOnceSync!(context, input);\n sampleDuration += duration;\n\n if (postSync) {\n postSync(context, input);\n } else if (postAsync) {\n await postAsync(context, input);\n }\n }\n sampleDuration = (sampleDuration * DURATION_SCALE) / BigInt(batchSize);\n }\n\n const sampleEnd = performance.now();\n if (!disableFiltering) {\n const gcNoise = (gcMarker ? gcWatcher!.seen(gcMarker) : false) || (gcTracker?.overlaps(sampleStart, sampleEnd) ?? false);\n if (gcNoise) {\n skipped++;\n continue;\n }\n }\n\n const durationNumber = Number(sampleDuration);\n if (!disableFiltering) {\n const { median, iqr } = medianAndIqr(outlierWindow);\n pushWindow(outlierWindow, durationNumber, OUTLIER_WINDOW);\n const maxAllowed = median + OUTLIER_IQR_MULTIPLIER * iqr || Number.POSITIVE_INFINITY;\n if (outlierWindow.length >= 8 && durationNumber > maxAllowed && durationNumber - median > OUTLIER_ABS_THRESHOLD) {\n skipped++;\n continue;\n }\n\n const meanNumber = Number(meanS / WELFORD_SCALE);\n if (i >= 8 && meanNumber > 0 && durationNumber > OUTLIER_MULTIPLIER * meanNumber && durationNumber - meanNumber > OUTLIER_ABS_THRESHOLD) {\n skipped++;\n continue;\n }\n } else {\n pushWindow(outlierWindow, durationNumber, OUTLIER_WINDOW);\n }\n\n durations[i++] = sampleDuration;\n const deltaS = sampleDuration * WELFORD_SCALE - meanS;\n meanS += deltaS / BigInt(i);\n m2S += deltaS * (sampleDuration * WELFORD_SCALE - meanS);\n\n const progress = (i / maxCycles) * COMPLETE_VALUE;\n if (i % PROGRESS_STRIDE === 0) {\n control[Control.PROGRESS] = progress;\n }\n\n if (i >= minCycles) {\n if (m2S <= absThSq * BigInt(i - 1)) break;\n // RME convergence: Z95 * sem/mean <= relThreshold\n // Z95^2 * m2S / (n*(n-1)*meanS^2) <= relThreshold^2\n const ni = BigInt(i);\n if (meanS !== 0n && Z95_SQ_NUM * m2S * relPrecSq <= relThSq * ni * (ni - 1n) * meanS * meanS * Z95_SQ_DENOM) break;\n }\n }\n\n control[Control.INDEX] = i;\n control[Control.COMPLETE] = 0;\n const heapAfter = process.memoryUsage().heapUsed;\n control[Control.HEAP_USED] = Math.max(0, Math.round((heapAfter - heapBefore) / 1024));\n } catch (e) {\n console.error(e && typeof e === 'object' && 'stack' in e ? e.stack : e);\n control[Control.COMPLETE] = 1;\n } finally {\n gcTracker?.dispose?.();\n try {\n await teardown?.(context);\n } catch (e) {\n control[Control.COMPLETE] = 2;\n console.error(e && typeof e === 'object' && 'stack' in e ? e.stack : e);\n }\n }\n\n return control[Control.COMPLETE];\n};\n"],"names":["benchmark","COMPLETE_VALUE","hr","process","hrtime","bigint","bind","sink","Int32Array","consume","value","payload","Number","isFinite","Math","trunc","length","runSync","run","overhead","args","start","result","duration","runAsync","isThenable","then","TARGET_SAMPLE_NS","MAX_BATCH","PROGRESS_STRIDE","GC_STRIDE","OUTLIER_MULTIPLIER","OUTLIER_IQR_MULTIPLIER","OUTLIER_WINDOW","OUTLIER_ABS_THRESHOLD","BASELINE_SAMPLES","OUTLIER_SCRATCH","Float64Array","measureTimerOverhead","total","i","BigInt","collectSample","batchSize","runRaw","runIsAsync","pre","preIsAsync","post","postIsAsync","context","data","nextNonce","canBatchTime","batchStart","b","DURATION_SCALE","sampleDuration","runAsyncFn","runSyncFn","tuneParameters","initialBatch","minCycles","relThreshold","maxCycles","bestCv","POSITIVE_INFINITY","bestBatch","attempt","samples","sampleCount","min","s","push","mean","reduce","acc","v","variance","max","stddev","sqrt","cv","tunedRel","tunedMin","ceil","createGCTracker","env","OVERTAKE_GC_OBSERVER","PerformanceObserver","events","observer","list","entry","getEntries","startTime","end","observe","entryTypes","overlaps","noisy","event","splice","dispose","disconnect","pushWindow","arr","cap","shift","medianAndIqr","median","iqr","view","subarray","sort","mid","floor","q1Idx","q3Idx","q1","q3","windowCv","a","setup","teardown","warmupCycles","absThreshold","gcObserver","durationsSAB","controlSAB","durations","BigUint64Array","control","Control","INDEX","PROGRESS","COMPLETE","HEAP_USED","heapBefore","memoryUsage","heapUsed","input","gcWatcher","GCWatcher","gcTracker","preResult","probeStart","probeResult","resolved","durationProbeRaw","postResult","timerOverhead","durationProbe","shouldPerturbInput","OVERTAKE_PERTURB_INPUT","nonce","PROBE_TIME_LIMIT_NS","INITIAL_PROBE_SIZE","MAX_PROBE_SIZE","initialStart","initialDuration","estimatedPerOp","remainingBudget","additionalIterations","cappedAdditional","totalIterations","runTimedSync","runTimedAsync","runOnceSync","ctx","dataValue","runOnceAsync","preSync","preAsync","postSync","postAsync","durationPerRun","suggestedBatch","minBatchForFastOps","initialBatchSize","tuned","warmupStart","performance","now","warmupRemaining","warmupWindow","warmupCap","runWarmup","warmupDone","global","gc","WELFORD_SCALE","meanS","m2S","outlierWindow","skipped","maxSkipped","disableFiltering","absThScaled","round","absThSq","REL_PRECISION","relThBigint","relThSq","relPrecSq","Z95_SQ_NUM","Z95_SQ_DENOM","console","error","gcMarker","sampleStart","batchDuration","sampleEnd","gcNoise","seen","durationNumber","maxAllowed","meanNumber","deltaS","progress","ni","heapAfter","e","stack"],"mappings":";;;;+BAgTaA;;;eAAAA;;;gCAhToC;0BACA;8BACvB;AAG1B,MAAMC,iBAAiB;AAEvB,MAAMC,KAAKC,QAAQC,MAAM,CAACC,MAAM,CAACC,IAAI,CAACH,QAAQC,MAAM;AAEpD,MAAMG,OAAO,IAAIC,WAAW;AAC5B,MAAMC,UAAU,CAACC;IACf,IAAIC,UAAU;IACd,OAAQ,OAAOD;QACb,KAAK;YACHC,UAAUC,OAAOC,QAAQ,CAACH,SAASI,KAAKC,KAAK,CAACL,SAAS;YACvD;QACF,KAAK;YACHC,UAAUC,OAAOF,QAAQ,YAAY;YACrC;QACF,KAAK;YACHC,UAAUD,MAAMM,MAAM;YACtB;QACF,KAAK;YACHL,UAAUD,QAAQ,IAAI;YACtB;QACF,KAAK;YACHC,UAAUD,UAAU,OAAO,IAAI;YAC/B;QACF,KAAK;YACHC,UAAU;YACV;QACF;YACEA,UAAU,CAAC;IACf;IACAJ,IAAI,CAAC,EAAE,IAAII;AACb;AAEA,MAAMM,UAAU,CAACC,KAAeC;IAC9B,OAAO,CAAC,GAAGC;QACT,MAAMC,QAAQnB;QACd,MAAMoB,SAASJ,OAAOE;QACtBX,QAAQa;QACR,MAAMC,WAAWrB,OAAOmB;QACxB,OAAOE,WAAWJ,WAAWI,WAAWJ,WAAW,EAAE;IACvD;AACF;AAEA,MAAMK,WAAW,CAACN;IAChB,OAAO,OAAO,GAAGE;QACf,MAAMC,QAAQnB;QACd,MAAMoB,SAAS,MAAMJ,OAAOE;QAC5BX,QAAQa;QACR,OAAOpB,OAAOmB;IAChB;AACF;AAEA,MAAMI,aAAa,CAACf;IAClB,OAAOA,UAAU,QAAS,CAAA,OAAOA,UAAU,YAAY,OAAOA,UAAU,UAAS,KAAM,OAAO,AAACA,MAA+BgB,IAAI,KAAK;AACzI;AAEA,MAAMC,mBAAmB,UAAU;AACnC,MAAMC,YAAY;AAClB,MAAMC,kBAAkB;AACxB,MAAMC,YAAY;AAClB,MAAMC,qBAAqB;AAC3B,MAAMC,yBAAyB;AAC/B,MAAMC,iBAAiB;AACvB,MAAMC,wBAAwB;AAC9B,MAAMC,mBAAmB;AACzB,MAAMC,kBAAkB,IAAIC,aAAaJ;AAMzC,MAAMK,uBAAuB;IAC3B,IAAIC,QAAQ,EAAE;IACd,IAAK,IAAIC,IAAI,GAAGA,IAAIL,kBAAkBK,IAAK;QACzC,MAAMnB,QAAQnB;QACdO,QAAQ;QACR8B,SAASrC,OAAOmB;IAClB;IACA,OAAOkB,QAAQE,OAAON;AACxB;AAEA,MAAMO,gBAAgB,OAAyB,EAC7CC,SAAS,EACTzB,GAAG,EACH0B,MAAM,EACNC,UAAU,EACVC,GAAG,EACHC,UAAU,EACVC,IAAI,EACJC,WAAW,EACXC,OAAO,EACPC,IAAI,EACJC,SAAS,EAaV;IACC,MAAMC,eAAe,CAACR,cAAc,CAACC,OAAO,CAACE;IAC7C,IAAIK,cAAc;QAChB,MAAMC,aAAapD;QACnB,IAAIkD,WAAW;YACb,IAAK,IAAIG,IAAI,GAAGA,IAAIZ,WAAWY,IAAK;gBAClC9C,QAAQ,AAACmC,OAAoBM,SAASC,MAAMC;YAC9C;QACF,OAAO;YACL,IAAK,IAAIG,IAAI,GAAGA,IAAIZ,WAAWY,IAAK;gBAClC9C,QAAQmC,OAAOM,SAASC;YAC1B;QACF;QACA,OAAO,AAAEjD,CAAAA,OAAOoD,UAAS,IAAKE,wBAAc,GAAIf,OAAOE;IACzD;IAEA,IAAIc,iBAAiB,EAAE;IACvB,IAAK,IAAIF,IAAI,GAAGA,IAAIZ,WAAWY,IAAK;QAClC,IAAIT,KAAK;YACP,IAAIC,YAAY;gBACd,MAAMD,IAAII,SAASC;YACrB,OAAO;gBACLL,IAAII,SAASC;YACf;QACF;QAEA,IAAIN,YAAY;YACd,MAAMa,aAAaxC;YACnB,MAAMK,WAAW6B,YAAY,MAAMM,WAAWR,SAASC,MAAMC,eAAe,MAAMM,WAAWR,SAASC;YACtGM,kBAAkBlC;QACpB,OAAO;YACL,MAAMoC,YAAYzC;YAClB,MAAMK,WAAW6B,YAAYO,UAAUT,SAASC,MAAMC,eAAeO,UAAUT,SAASC;YACxFM,kBAAkBlC;QACpB;QAEA,IAAIyB,MAAM;YACR,IAAIC,aAAa;gBACf,MAAMD,KAAKE,SAASC;YACtB,OAAO;gBACLH,KAAKE,SAASC;YAChB;QACF;IACF;IACA,OAAO,AAACM,iBAAiBD,wBAAc,GAAIf,OAAOE;AACpD;AAEA,MAAMiB,iBAAiB,OAAyB,EAC9CC,YAAY,EACZ3C,GAAG,EACH0B,MAAM,EACNC,UAAU,EACVC,GAAG,EACHC,UAAU,EACVC,IAAI,EACJC,WAAW,EACXC,OAAO,EACPC,IAAI,EACJW,SAAS,EACTC,YAAY,EACZC,SAAS,EACTZ,SAAS,EAgBV;IACC,IAAIT,YAAYkB;IAChB,IAAII,SAASrD,OAAOsD,iBAAiB;IACrC,IAAIC,YAAYxB;IAEhB,IAAK,IAAIyB,UAAU,GAAGA,UAAU,GAAGA,UAAW;QAC5C,MAAMC,UAAoB,EAAE;QAC5B,MAAMC,cAAcxD,KAAKyD,GAAG,CAAC,GAAGP;QAChC,IAAK,IAAIQ,IAAI,GAAGA,IAAIF,aAAaE,IAAK;YACpC,MAAMjD,WAAW,MAAMmB,cAAc;gBACnCC;gBACAzB;gBACA0B;gBACAC;gBACAC;gBACAC;gBACAC;gBACAC;gBACAC;gBACAC;gBACAC;YACF;YACAiB,QAAQI,IAAI,CAAC7D,OAAOW;QACtB;QACA,MAAMmD,OAAOL,QAAQM,MAAM,CAAC,CAACC,KAAKC,IAAMD,MAAMC,GAAG,KAAKR,QAAQrD,MAAM;QACpE,MAAM8D,WAAWT,QAAQM,MAAM,CAAC,CAACC,KAAKC,IAAMD,MAAM,AAACC,CAAAA,IAAIH,IAAG,IAAMG,CAAAA,IAAIH,IAAG,GAAI,KAAK5D,KAAKiE,GAAG,CAAC,GAAGV,QAAQrD,MAAM,GAAG;QAC7G,MAAMgE,SAASlE,KAAKmE,IAAI,CAACH;QACzB,MAAMI,KAAKR,SAAS,IAAI9D,OAAOsD,iBAAiB,GAAGc,SAASN;QAE5D,IAAIQ,KAAKjB,QAAQ;YACfA,SAASiB;YACTf,YAAYxB;QACd;QAEA,IAAIuC,MAAMnB,gBAAgBpB,aAAaf,WAAW;YAChD;QACF;QACAe,YAAY7B,KAAKyD,GAAG,CAAC3C,WAAWe,YAAY;IAC9C;IAEA,MAAMwC,WAAWlB,SAASF,eAAejD,KAAKiE,GAAG,CAACd,SAAS,KAAKF,eAAe,OAAOA;IACtF,MAAMqB,WAAWtE,KAAKyD,GAAG,CAACP,WAAWlD,KAAKiE,GAAG,CAACjB,WAAWhD,KAAKuE,IAAI,CAACvB,YAAYhD,KAAKiE,GAAG,CAAC,GAAGd,SAAUF,CAAAA,gBAAgB,IAAG;IAExH,OAAO;QAAEpB,WAAWwB;QAAWJ,cAAcoB;QAAUrB,WAAWsB;IAAS;AAC7E;AAEA,MAAME,kBAAkB;IACtB,IAAInF,QAAQoF,GAAG,CAACC,oBAAoB,KAAK,KAAK;QAC5C,OAAO;IACT;IACA,IAAI,OAAOC,mCAAmB,KAAK,aAAa;QAC9C,OAAO;IACT;IAEA,MAAMC,SAAoB,EAAE;IAC5B,MAAMC,WAAW,IAAIF,mCAAmB,CAAC,CAACG;QACxC,KAAK,MAAMC,SAASD,KAAKE,UAAU,GAAI;YACrCJ,OAAOjB,IAAI,CAAC;gBAAEpD,OAAOwE,MAAME,SAAS;gBAAEC,KAAKH,MAAME,SAAS,GAAGF,MAAMtE,QAAQ;YAAC;QAC9E;IACF;IAEA,IAAI;QACFoE,SAASM,OAAO,CAAC;YAAEC,YAAY;gBAAC;aAAK;QAAC;IACxC,EAAE,OAAM;QACN,OAAO;IACT;IAEA,MAAMC,WAAW,CAAC9E,OAAe2E;QAC/B,IAAII,QAAQ;QACZ,IAAK,IAAI5D,IAAIkD,OAAO1E,MAAM,GAAG,GAAGwB,KAAK,GAAGA,IAAK;YAC3C,MAAM6D,QAAQX,MAAM,CAAClD,EAAE;YACvB,IAAI6D,MAAML,GAAG,GAAG3E,QAAQ,OAAO;gBAC7BqE,OAAOY,MAAM,CAAC9D,GAAG;gBACjB;YACF;YACA,IAAI6D,MAAMhF,KAAK,IAAI2E,OAAOK,MAAML,GAAG,IAAI3E,OAAO;gBAC5C+E,QAAQ;YACV;QACF;QACA,OAAOA;IACT;IAEA,MAAMG,UAAU,IAAMZ,SAASa,UAAU;IAEzC,OAAO;QAAEL;QAAUI;IAAQ;AAC7B;AAEA,MAAME,aAAa,CAACC,KAAehG,OAAeiG;IAChD,IAAID,IAAI1F,MAAM,KAAK2F,KAAK;QACtBD,IAAIE,KAAK;IACX;IACAF,IAAIjC,IAAI,CAAC/D;AACX;AAEA,MAAMmG,eAAe,CAACH;IACpB,IAAIA,IAAI1F,MAAM,KAAK,GAAG,OAAO;QAAE8F,QAAQ;QAAGC,KAAK;IAAE;IACjD,IAAK,IAAIvE,IAAI,GAAGA,IAAIkE,IAAI1F,MAAM,EAAEwB,IAAK;QACnCJ,eAAe,CAACI,EAAE,GAAGkE,GAAG,CAAClE,EAAE;IAC7B;IACA,MAAMwE,OAAO5E,gBAAgB6E,QAAQ,CAAC,GAAGP,IAAI1F,MAAM;IACnDgG,KAAKE,IAAI;IACT,MAAMC,MAAMrG,KAAKsG,KAAK,CAACJ,KAAKhG,MAAM,GAAG;IACrC,MAAM8F,SAASE,KAAKhG,MAAM,GAAG,MAAM,IAAI,AAACgG,CAAAA,IAAI,CAACG,MAAM,EAAE,GAAGH,IAAI,CAACG,IAAI,AAAD,IAAK,IAAIH,IAAI,CAACG,IAAI;IAClF,MAAME,QAAQvG,KAAKsG,KAAK,CAACJ,KAAKhG,MAAM,GAAG;IACvC,MAAMsG,QAAQxG,KAAKsG,KAAK,CAACJ,KAAKhG,MAAM,GAAG;IACvC,MAAMuG,KAAKP,IAAI,CAACK,MAAM;IACtB,MAAMG,KAAKR,IAAI,CAACM,MAAM;IACtB,OAAO;QAAER;QAAQC,KAAKS,KAAKD;IAAG;AAChC;AAEA,MAAME,WAAW,CAACf;IAChB,IAAIA,IAAI1F,MAAM,GAAG,GAAG,OAAOJ,OAAOsD,iBAAiB;IACnD,MAAMQ,OAAOgC,IAAI/B,MAAM,CAAC,CAAC+C,GAAG7C,IAAM6C,IAAI7C,GAAG,KAAK6B,IAAI1F,MAAM;IACxD,MAAM8D,WAAW4B,IAAI/B,MAAM,CAAC,CAAC+C,GAAG7C,IAAM6C,IAAI,AAAC7C,CAAAA,IAAIH,IAAG,IAAMG,CAAAA,IAAIH,IAAG,GAAI,KAAMgC,CAAAA,IAAI1F,MAAM,GAAG,CAAA;IACtF,MAAMgE,SAASlE,KAAKmE,IAAI,CAACH;IACzB,OAAOJ,SAAS,IAAI9D,OAAOsD,iBAAiB,GAAGc,SAASN;AAC1D;AAEO,MAAM1E,YAAY,OAAyB,EAChD2H,KAAK,EACLC,QAAQ,EACR9E,GAAG,EACH5B,KAAK0B,MAAM,EACXI,IAAI,EACJG,IAAI,EAEJ0E,YAAY,EACZ/D,SAAS,EACTgE,YAAY,EACZ/D,YAAY,EACZgE,aAAa,KAAK,EAElBC,YAAY,EACZC,UAAU,EAC0B;IACpC,MAAMC,YAAY,IAAIC,eAAeH;IACrC,MAAMI,UAAU,IAAI5H,WAAWyH;IAE/BG,OAAO,CAACC,iBAAO,CAACC,KAAK,CAAC,GAAG;IACzBF,OAAO,CAACC,iBAAO,CAACE,QAAQ,CAAC,GAAG;IAC5BH,OAAO,CAACC,iBAAO,CAACG,QAAQ,CAAC,GAAG;IAC5BJ,OAAO,CAACC,iBAAO,CAACI,SAAS,CAAC,GAAG;IAE7B,MAAMvF,UAAW,MAAMyE;IACvB,MAAMe,aAAavI,QAAQwI,WAAW,GAAGC,QAAQ;IACjD,MAAMC,QAAQ1F;IACd,MAAMa,YAAYkE,UAAUlH,MAAM;IAClC,MAAM8H,YAAYf,aAAa,IAAIgB,uBAAS,KAAK;IACjD,MAAMC,YAAYjB,aAAazC,oBAAoB;IAEnD,IAAI;QAEF,IAAIvC,aAAa;QACjB,IAAID,KAAK;YACP,MAAMmG,YAAYnG,IAAII,SAAS2F;YAC/B9F,aAAatB,WAAWwH;YACxB,IAAIlG,YAAY;gBACd,MAAMkG;YACR;QACF;QAEA,MAAMC,aAAahJ;QACnB,MAAMiJ,cAAcvG,OAAOM,SAAS2F;QACpC,MAAMhG,aAAapB,WAAW0H;QAC9B,IAAItG,YAAY;YACd,MAAMuG,WAAW,MAAMD;YACvB1I,QAAQ2I;QACV,OAAO;YACL3I,QAAQ0I;QACV;QACA,MAAME,mBAAmBnJ,OAAOgJ;QAEhC,IAAIjG,cAAc;QAClB,IAAID,MAAM;YACR,MAAMsG,aAAatG,KAAKE,SAAS2F;YACjC5F,cAAcxB,WAAW6H;YACzB,IAAIrG,aAAa;gBACf,MAAMqG;YACR;QACF;QAEA,MAAMC,gBAAgB1G,aAAa,EAAE,GAAGP;QACxC,IAAIkH,gBAAgB3G,aAAawG,mBAAmBA,mBAAmBE,gBAAgBF,mBAAmBE,gBAAgB,EAAE;QAE5H,MAAME,qBAAqBtJ,QAAQoF,GAAG,CAACmE,sBAAsB,KAAK;QAClE,IAAIC,QAAQ;QACZ,MAAMvG,YAAYqG,qBACd;YACEE,QAAQ,AAACA,QAAQ,IAAK;YACtB,OAAOA;QACT,IACA;QAEJ,IAAI,CAAC9G,cAAc,CAACC,OAAO,CAACE,MAAM;YAChC,MAAM4G,sBAAsB,cAAc;YAC1C,MAAMC,qBAAqB;YAC3B,MAAMC,iBAAiB;YAEvB,MAAMC,eAAe7J;YACrB,IAAIkD,WAAW;gBACb,IAAK,IAAIZ,IAAI,GAAGA,IAAIqH,oBAAoBrH,IAAK;oBAC3C/B,QAAQ,AAACmC,OAAoBM,SAAS2F,OAAOzF;gBAC/C;YACF,OAAO;gBACL,IAAK,IAAIZ,IAAI,GAAGA,IAAIqH,oBAAoBrH,IAAK;oBAC3C/B,QAAQmC,OAAOM,SAAS2F;gBAC1B;YACF;YACA,MAAMmB,kBAAkB9J,OAAO6J;YAC/B,MAAME,iBAAiBD,kBAAkBvH,OAAOoH;YAEhD,MAAMK,kBAAkBN,sBAAsBI;YAC9C,MAAMG,uBAAuBF,iBAAiB,EAAE,GAAGrJ,OAAOsJ,kBAAkBD,kBAAkBH,iBAAiBD;YAC/G,MAAMO,mBAAmBtJ,KAAKyD,GAAG,CAACzD,KAAKiE,GAAG,CAAC,GAAGoF,uBAAuBL,iBAAiBD;YAEtF,IAAIQ,kBAAkBR;YACtB,IAAIO,mBAAmB,GAAG;gBACxB,IAAIhH,WAAW;oBACb,IAAK,IAAIZ,IAAI,GAAGA,IAAI4H,kBAAkB5H,IAAK;wBACzC/B,QAAQ,AAACmC,OAAoBM,SAAS2F,OAAOzF;oBAC/C;gBACF,OAAO;oBACL,IAAK,IAAIZ,IAAI,GAAGA,IAAI4H,kBAAkB5H,IAAK;wBACzC/B,QAAQmC,OAAOM,SAAS2F;oBAC1B;gBACF;gBACAwB,mBAAmBD;YACrB;YAEAZ,gBAAgB,AAACtJ,CAAAA,OAAO6J,YAAW,IAAKtH,OAAO4H;QACjD;QAEA,MAAMC,eAAezH,aAAa,OAAO5B,QAAQ2B,QAAQ2G;QACzD,MAAMgB,gBAAgB1H,aAAarB,SAASoB,UAAU;QACtD,MAAM1B,MAAM2B,aAAa0H,gBAAiBD;QAE1C,MAAME,cAAqD3H,aAAa,OAAOO,YAAY,CAACqH,KAAKC,YAAcJ,aAAcG,KAAKC,WAAWtH,eAAekH;QAC5J,MAAMK,eAAuD9H,aAAcO,YAAY,CAACqH,KAAKC,YAAcH,cAAeE,KAAKC,WAAWtH,eAAemH,gBAAkB;QAE3K,MAAMK,UAAU7H,aAAa,OAAOD;QACpC,MAAM+H,WAAW9H,aAAaD,MAAM;QACpC,MAAMgI,WAAW7H,cAAc,OAAOD;QACtC,MAAM+H,YAAY9H,cAAcD,OAAO;QAGvC,MAAMgI,iBAAiBxB,kBAAkB,EAAE,GAAG,EAAE,GAAGA;QACnD,MAAMyB,iBAAiBrK,OAAOe,mBAAmBqJ;QACjD,MAAME,qBAAqB1B,gBAAgB,IAAI,GAAG,UAAU;QAC5D,MAAM2B,mBAAmBrK,KAAKyD,GAAG,CAAC3C,WAAWd,KAAKiE,GAAG,CAACmG,oBAAoBD;QAG1E,MAAMG,QAAQ,MAAMxH,eAAe;YACjCC,cAAcsH;YACdjK;YACA0B;YACAC;YACAC;YACAC;YACAC;YACAC;YACAC;YACAC,MAAM0F;YACN/E;YACAC;YACAC;YACAZ;QACF;QACA,IAAIT,YAAYyI,MAAMzI,SAAS;QAC/BmB,YAAYsH,MAAMtH,SAAS;QAC3BC,eAAeqH,MAAMrH,YAAY;QAGjC,MAAMsH,cAAcC,2BAAW,CAACC,GAAG;QACnC,IAAIC,kBAAkB3D;QACtB,MAAM4D,eAAyB,EAAE;QACjC,MAAMC,YAAY5K,KAAKiE,GAAG,CAAC8C,cAAc/G,KAAKyD,GAAG,CAACP,WAAW6D,eAAe,KAAK;QACjF,MAAMxE,eAAe,CAACR,cAAc,CAAC+H,WAAW,CAACC,YAAY,CAACC,YAAY,CAACC;QAE3E,MAAMY,YAAY;YAChB,IAAItI,cAAc;gBAChB,MAAMC,aAAapD;gBACnB,IAAIkD,WAAW;oBACb,IAAK,IAAIG,IAAI,GAAGA,IAAIZ,WAAWY,IAAK;wBAClC9C,QAAQ,AAACmC,OAAoBM,SAAS2F,OAAOzF;oBAC/C;gBACF,OAAO;oBACL,IAAK,IAAIG,IAAI,GAAGA,IAAIZ,WAAWY,IAAK;wBAClC9C,QAAQmC,OAAOM,SAAS2F;oBAC1B;gBACF;gBACA,OAAO,AAAE3I,CAAAA,OAAOoD,UAAS,IAAKE,wBAAc,GAAIf,OAAOE;YACzD;YAEA,IAAIiI,SAAS;gBACXA,QAAQ1H,SAAS2F;YACnB,OAAO,IAAIgC,UAAU;gBACnB,MAAMA,SAAS3H,SAAS2F;YAC1B;YAEA,MAAMtH,WAAWsB,aAAa,MAAM8H,aAAczH,SAAS2F,SAAS2B,YAAatH,SAAS2F;YAE1F,IAAIiC,UAAU;gBACZA,SAAS5H,SAAS2F;YACpB,OAAO,IAAIkC,WAAW;gBACpB,MAAMA,UAAU7H,SAAS2F;YAC3B;YAEA,OAAOtH,WAAWiC,wBAAc;QAClC;QAEA,MAAO8H,2BAAW,CAACC,GAAG,KAAKF,cAAc,SAASG,kBAAkB,EAAG;YACrE,MAAMjK,WAAW,MAAMoK;YACvBlF,WAAWgF,cAAc7K,OAAOW,WAAWmK;YAC3CF;QACF;QACA,IAAII,aAAa;QACjB,MAAOA,aAAaJ,gBAAiB;YACnC,MAAMjK,WAAW,MAAMoK;YACvBlF,WAAWgF,cAAc7K,OAAOW,WAAWmK;YAC3CE;YACA,IAAIC,OAAOC,EAAE,IAAIF,aAAa9J,cAAc,GAAG;gBAC7C+J,OAAOC,EAAE;YACX;QACF;QACA,MAAOL,aAAazK,MAAM,IAAI,KAAKyK,aAAazK,MAAM,GAAG0K,UAAW;YAClE,MAAMxG,KAAKuC,SAASgE;YACpB,IAAIvG,MAAMnB,eAAe,GAAG;gBAC1B;YACF;YACA,MAAMxC,WAAW,MAAMoK;YACvBlF,WAAWgF,cAAc7K,OAAOW,WAAWmK;QAC7C;QAEA,IAAIlJ,IAAI;QACR,MAAMuJ,gBAAgB,UAAU;QAChC,IAAIC,QAAQ,EAAE;QACd,IAAIC,MAAM,EAAE;QACZ,MAAMC,gBAA0B,EAAE;QAClC,IAAIC,UAAU;QACd,MAAMC,aAAapI,YAAY;QAC/B,IAAIqI,mBAAmB;QAEvB,MAAMC,cAAc7J,OAAO3B,KAAKyL,KAAK,CAACzE,iBAAiBiE;QACvD,MAAMS,UAAUF,cAAcA;QAC9B,MAAMG,gBAAgB,UAAU;QAChC,MAAMC,cAAcjK,OAAO3B,KAAKyL,KAAK,CAACxI,eAAenD,OAAO6L;QAC5D,MAAME,UAAUD,cAAcA;QAC9B,MAAME,YAAYH,gBAAgBA;QAClC,MAAMI,aAAa,MAAM;QACzB,MAAMC,eAAe,MAAM;QAE3B,MAAO,KAAM;YACX,IAAItK,KAAKwB,WAAW;YACpB,IAAI,CAACqI,oBAAoBF,WAAWC,YAAY;gBAC9CW,QAAQC,KAAK,CAAC,CAAC,SAAS,EAAEb,QAAQ,iDAAiD,CAAC,GAAG,CAAC,4EAA4E,CAAC;gBACrKE,mBAAmB;YACrB;YAEA,IAAIR,OAAOC,EAAE,IAAItJ,IAAI,KAAKA,IAAIV,cAAc,GAAG;gBAC7C+J,OAAOC,EAAE;YACX;YAEA,MAAMmB,WAAWnE,WAAWzH;YAC5B,MAAM6L,cAAc5B,2BAAW,CAACC,GAAG;YACnC,IAAI9H,iBAAiB,EAAE;YAEvB,IAAIJ,cAAc;gBAChB,MAAMC,aAAapD;gBACnB,IAAIkD,WAAW;oBACb,IAAK,IAAIG,IAAI,GAAGA,IAAIZ,WAAWY,IAAK;wBAClC9C,QAAQ,AAACmC,OAAoBM,SAAS2F,OAAOzF;oBAC/C;gBACF,OAAO;oBACL,IAAK,IAAIG,IAAI,GAAGA,IAAIZ,WAAWY,IAAK;wBAClC9C,QAAQmC,OAAOM,SAAS2F;oBAC1B;gBACF;gBACA,MAAMsE,gBAAgBjN,OAAOoD;gBAC7BG,iBAAiB,AAAC0J,gBAAgB3J,wBAAc,GAAIf,OAAOE;YAC7D,OAAO;gBACL,IAAK,IAAIY,IAAI,GAAGA,IAAIZ,WAAWY,IAAK;oBAClC,IAAIqH,SAAS;wBACXA,QAAQ1H,SAAS2F;oBACnB,OAAO,IAAIgC,UAAU;wBACnB,MAAMA,SAAS3H,SAAS2F;oBAC1B;oBAEA,MAAMtH,WAAWsB,aAAa,MAAM8H,aAAczH,SAAS2F,SAAS2B,YAAatH,SAAS2F;oBAC1FpF,kBAAkBlC;oBAElB,IAAIuJ,UAAU;wBACZA,SAAS5H,SAAS2F;oBACpB,OAAO,IAAIkC,WAAW;wBACpB,MAAMA,UAAU7H,SAAS2F;oBAC3B;gBACF;gBACApF,iBAAiB,AAACA,iBAAiBD,wBAAc,GAAIf,OAAOE;YAC9D;YAEA,MAAMyK,YAAY9B,2BAAW,CAACC,GAAG;YACjC,IAAI,CAACc,kBAAkB;gBACrB,MAAMgB,UAAU,AAACJ,CAAAA,WAAWnE,UAAWwE,IAAI,CAACL,YAAY,KAAI,KAAOjE,CAAAA,WAAW7C,SAAS+G,aAAaE,cAAc,KAAI;gBACtH,IAAIC,SAAS;oBACXlB;oBACA;gBACF;YACF;YAEA,MAAMoB,iBAAiB3M,OAAO6C;YAC9B,IAAI,CAAC4I,kBAAkB;gBACrB,MAAM,EAAEvF,MAAM,EAAEC,GAAG,EAAE,GAAGF,aAAaqF;gBACrCzF,WAAWyF,eAAeqB,gBAAgBtL;gBAC1C,MAAMuL,aAAa1G,SAAS9E,yBAAyB+E,OAAOnG,OAAOsD,iBAAiB;gBACpF,IAAIgI,cAAclL,MAAM,IAAI,KAAKuM,iBAAiBC,cAAcD,iBAAiBzG,SAAS5E,uBAAuB;oBAC/GiK;oBACA;gBACF;gBAEA,MAAMsB,aAAa7M,OAAOoL,QAAQD;gBAClC,IAAIvJ,KAAK,KAAKiL,aAAa,KAAKF,iBAAiBxL,qBAAqB0L,cAAcF,iBAAiBE,aAAavL,uBAAuB;oBACvIiK;oBACA;gBACF;YACF,OAAO;gBACL1F,WAAWyF,eAAeqB,gBAAgBtL;YAC5C;YAEAiG,SAAS,CAAC1F,IAAI,GAAGiB;YACjB,MAAMiK,SAASjK,iBAAiBsI,gBAAgBC;YAChDA,SAAS0B,SAASjL,OAAOD;YACzByJ,OAAOyB,SAAUjK,CAAAA,iBAAiBsI,gBAAgBC,KAAI;YAEtD,MAAM2B,WAAW,AAACnL,IAAIwB,YAAa/D;YACnC,IAAIuC,IAAIX,oBAAoB,GAAG;gBAC7BuG,OAAO,CAACC,iBAAO,CAACE,QAAQ,CAAC,GAAGoF;YAC9B;YAEA,IAAInL,KAAKsB,WAAW;gBAClB,IAAImI,OAAOO,UAAU/J,OAAOD,IAAI,IAAI;gBAGpC,MAAMoL,KAAKnL,OAAOD;gBAClB,IAAIwJ,UAAU,EAAE,IAAIa,aAAaZ,MAAMW,aAAaD,UAAUiB,KAAMA,CAAAA,KAAK,EAAE,AAAD,IAAK5B,QAAQA,QAAQc,cAAc;YAC/G;QACF;QAEA1E,OAAO,CAACC,iBAAO,CAACC,KAAK,CAAC,GAAG9F;QACzB4F,OAAO,CAACC,iBAAO,CAACG,QAAQ,CAAC,GAAG;QAC5B,MAAMqF,YAAY1N,QAAQwI,WAAW,GAAGC,QAAQ;QAChDR,OAAO,CAACC,iBAAO,CAACI,SAAS,CAAC,GAAG3H,KAAKiE,GAAG,CAAC,GAAGjE,KAAKyL,KAAK,CAAC,AAACsB,CAAAA,YAAYnF,UAAS,IAAK;IACjF,EAAE,OAAOoF,GAAG;QACVf,QAAQC,KAAK,CAACc,KAAK,OAAOA,MAAM,YAAY,WAAWA,IAAIA,EAAEC,KAAK,GAAGD;QACrE1F,OAAO,CAACC,iBAAO,CAACG,QAAQ,CAAC,GAAG;IAC9B,SAAU;QACRQ,WAAWzC;QACX,IAAI;YACF,MAAMqB,WAAW1E;QACnB,EAAE,OAAO4K,GAAG;YACV1F,OAAO,CAACC,iBAAO,CAACG,QAAQ,CAAC,GAAG;YAC5BuE,QAAQC,KAAK,CAACc,KAAK,OAAOA,MAAM,YAAY,WAAWA,IAAIA,EAAEC,KAAK,GAAGD;QACvE;IACF;IAEA,OAAO1F,OAAO,CAACC,iBAAO,CAACG,QAAQ,CAAC;AAClC"}
|