overtake 1.4.0 → 2.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. package/README.md +4 -15
  2. package/build/cli.js +126 -125
  3. package/build/executor.d.ts +6 -2
  4. package/build/executor.js +59 -46
  5. package/build/gc-watcher.js +2 -6
  6. package/build/index.d.ts +10 -11
  7. package/build/index.js +153 -155
  8. package/build/register-hook.d.ts +1 -0
  9. package/build/register-hook.js +15 -0
  10. package/build/reporter.d.ts +10 -2
  11. package/build/reporter.js +176 -214
  12. package/build/runner.d.ts +1 -1
  13. package/build/runner.js +128 -119
  14. package/build/types.d.ts +6 -6
  15. package/build/types.js +9 -14
  16. package/build/utils.d.ts +1 -17
  17. package/build/utils.js +53 -85
  18. package/build/worker.js +25 -24
  19. package/package.json +7 -25
  20. package/src/__tests__/assert-no-closure.ts +135 -0
  21. package/src/__tests__/benchmark-execute.ts +48 -0
  22. package/src/cli.ts +137 -142
  23. package/src/executor.ts +45 -15
  24. package/src/index.ts +85 -57
  25. package/src/register-hook.ts +15 -0
  26. package/src/reporter.ts +26 -18
  27. package/src/runner.ts +1 -4
  28. package/src/types.ts +8 -8
  29. package/src/utils.ts +15 -54
  30. package/src/worker.ts +5 -2
  31. package/tsconfig.json +2 -1
  32. package/build/cli.cjs +0 -179
  33. package/build/cli.cjs.map +0 -1
  34. package/build/cli.js.map +0 -1
  35. package/build/executor.cjs +0 -123
  36. package/build/executor.cjs.map +0 -1
  37. package/build/executor.js.map +0 -1
  38. package/build/gc-watcher.cjs +0 -30
  39. package/build/gc-watcher.cjs.map +0 -1
  40. package/build/gc-watcher.js.map +0 -1
  41. package/build/index.cjs +0 -442
  42. package/build/index.cjs.map +0 -1
  43. package/build/index.js.map +0 -1
  44. package/build/reporter.cjs +0 -311
  45. package/build/reporter.cjs.map +0 -1
  46. package/build/reporter.js.map +0 -1
  47. package/build/runner.cjs +0 -532
  48. package/build/runner.cjs.map +0 -1
  49. package/build/runner.js.map +0 -1
  50. package/build/types.cjs +0 -66
  51. package/build/types.cjs.map +0 -1
  52. package/build/types.js.map +0 -1
  53. package/build/utils.cjs +0 -174
  54. package/build/utils.cjs.map +0 -1
  55. package/build/utils.js.map +0 -1
  56. package/build/worker.cjs +0 -155
  57. package/build/worker.cjs.map +0 -1
  58. package/build/worker.js.map +0 -1
  59. package/src/__tests__/assert-no-closure.js +0 -134
package/build/index.js CHANGED
@@ -1,26 +1,29 @@
1
1
  import { cpus } from 'node:os';
2
2
  import Progress from 'progress';
3
- import { createExecutor } from "./executor.js";
4
- import { DEFAULT_CYCLES } from "./types.js";
3
+ import { createExecutor } from './executor.js';
4
+ import { DEFAULT_CYCLES } from './types.js';
5
5
  export const DEFAULT_WORKERS = Math.max(1, Math.ceil(cpus().length / 4));
6
- export const AsyncFunction = (async ()=>{}).constructor;
7
6
  const BENCHMARK_URL = Symbol.for('overtake.benchmarkUrl');
8
- export const DEFAULT_REPORT_TYPES = [
9
- 'ops'
10
- ];
7
+ export const DEFAULT_REPORT_TYPES = ['ops'];
8
+ const createExecutorErrorReport = (error) => ({
9
+ count: 0,
10
+ heapUsedKB: 0,
11
+ dceWarning: false,
12
+ error: error instanceof Error ? error.message : String(error),
13
+ });
11
14
  export class MeasureContext {
12
- title;
13
- run;
14
15
  pre;
15
16
  post;
16
- constructor(title, run){
17
+ title;
18
+ run;
19
+ constructor(title, run) {
17
20
  this.title = title;
18
21
  this.run = run;
19
22
  }
20
23
  }
21
24
  export class Measure {
22
25
  #ctx;
23
- constructor(ctx){
26
+ constructor(ctx) {
24
27
  this.#ctx = ctx;
25
28
  }
26
29
  pre(fn) {
@@ -33,18 +36,18 @@ export class Measure {
33
36
  }
34
37
  }
35
38
  export class TargetContext {
36
- title;
37
- setup;
38
39
  teardown;
39
40
  measures = [];
40
- constructor(title, setup){
41
+ title;
42
+ setup;
43
+ constructor(title, setup) {
41
44
  this.title = title;
42
45
  this.setup = setup;
43
46
  }
44
47
  }
45
48
  export class Target {
46
49
  #ctx;
47
- constructor(ctx){
50
+ constructor(ctx) {
48
51
  this.#ctx = ctx;
49
52
  }
50
53
  teardown(fn) {
@@ -60,7 +63,7 @@ export class Target {
60
63
  export class FeedContext {
61
64
  title;
62
65
  fn;
63
- constructor(title, fn){
66
+ constructor(title, fn) {
64
67
  this.title = title;
65
68
  this.fn = fn;
66
69
  }
@@ -72,14 +75,16 @@ export class Benchmark {
72
75
  static create(title, fn) {
73
76
  if (fn) {
74
77
  return new Benchmark(title, fn);
75
- } else {
78
+ }
79
+ else {
76
80
  return new Benchmark(title);
77
81
  }
78
82
  }
79
- constructor(title, fn){
83
+ constructor(title, fn) {
80
84
  if (fn) {
81
85
  this.feed(title, fn);
82
- } else {
86
+ }
87
+ else {
83
88
  this.feed(title);
84
89
  }
85
90
  }
@@ -93,14 +98,14 @@ export class Benchmark {
93
98
  this.#targets.push(target);
94
99
  return new Target(target);
95
100
  }
96
- async execute(options) {
97
- const { workers = DEFAULT_WORKERS, warmupCycles = 20, maxCycles = DEFAULT_CYCLES, minCycles = 50, absThreshold = 1_000, relThreshold = 0.02, gcObserver = true, reportTypes = DEFAULT_REPORT_TYPES, progress = false, progressInterval = 100 } = options;
101
+ async execute(options = {}) {
102
+ const { workers = DEFAULT_WORKERS, warmupCycles = 20, maxCycles = DEFAULT_CYCLES, minCycles = 50, absThreshold = 1_000, relThreshold = 0.02, gcObserver = true, reportTypes = DEFAULT_REPORT_TYPES, progress = false, progressInterval = 100, } = options;
98
103
  if (this.#executed) {
99
104
  throw new Error("Benchmark is executed and can't be reused");
100
105
  }
101
106
  this.#executed = true;
102
107
  const benchmarkUrl = options[BENCHMARK_URL];
103
- const totalBenchmarks = this.#targets.reduce((acc, t)=>acc + t.measures.length * this.#feeds.length, 0);
108
+ const totalBenchmarks = this.#targets.reduce((acc, t) => acc + t.measures.length * this.#feeds.length, 0);
104
109
  const progressMap = new Map();
105
110
  let completedBenchmarks = 0;
106
111
  let bar = null;
@@ -109,19 +114,17 @@ export class Benchmark {
109
114
  total: totalBenchmarks * 100,
110
115
  width: 30,
111
116
  complete: '=',
112
- incomplete: ' '
117
+ incomplete: ' ',
113
118
  });
114
119
  }
115
- const onProgress = progress ? (info)=>{
116
- progressMap.set(info.id, info.progress);
117
- const totalProgress = (completedBenchmarks + [
118
- ...progressMap.values()
119
- ].reduce((a, b)=>a + b, 0)) * 100;
120
- const label = info.id.length > 30 ? info.id.slice(0, 27) + '...' : info.id;
121
- bar?.update(totalProgress / (totalBenchmarks * 100), {
122
- label
123
- });
124
- } : undefined;
120
+ const onProgress = progress
121
+ ? (info) => {
122
+ progressMap.set(info.id, info.progress);
123
+ const totalProgress = (completedBenchmarks + [...progressMap.values()].reduce((a, b) => a + b, 0)) * 100;
124
+ const label = info.id.length > 30 ? info.id.slice(0, 27) + '...' : info.id;
125
+ bar?.update(totalProgress / (totalBenchmarks * 100), { label });
126
+ }
127
+ : undefined;
125
128
  const executor = createExecutor({
126
129
  workers,
127
130
  warmupCycles,
@@ -133,68 +136,78 @@ export class Benchmark {
133
136
  reportTypes,
134
137
  onProgress,
135
138
  progressInterval,
136
- [BENCHMARK_URL]: benchmarkUrl
139
+ [BENCHMARK_URL]: benchmarkUrl,
137
140
  });
138
141
  const reports = [];
139
- for (const target of this.#targets){
140
- const targetReport = {
141
- target: target.title,
142
- measures: []
143
- };
144
- for (const measure of target.measures){
145
- const measureReport = {
146
- measure: measure.title,
147
- feeds: []
148
- };
149
- for (const feed of this.#feeds){
150
- const id = `${target.title}/${measure.title}/${feed.title}`;
151
- const data = await feed.fn?.();
152
- executor.push({
153
- id,
154
- setup: target.setup,
155
- teardown: target.teardown,
156
- pre: measure.pre,
157
- run: measure.run,
158
- post: measure.post,
159
- data
160
- }).then((data)=>{
161
- progressMap.delete(id);
162
- completedBenchmarks++;
163
- measureReport.feeds.push({
142
+ const pendingReports = [];
143
+ try {
144
+ const feedData = await Promise.all(this.#feeds.map(async (feed) => ({ title: feed.title, data: await feed.fn?.() })));
145
+ for (const target of this.#targets) {
146
+ const targetReport = { target: target.title, measures: [] };
147
+ for (const measure of target.measures) {
148
+ const measureReport = { measure: measure.title, feeds: [] };
149
+ for (const feed of feedData) {
150
+ const id = `${target.title}/${measure.title}/${feed.title}`;
151
+ const feedReport = {
164
152
  feed: feed.title,
165
- data
166
- });
167
- });
153
+ data: createExecutorErrorReport('Benchmark did not produce a report'),
154
+ };
155
+ measureReport.feeds.push(feedReport);
156
+ pendingReports.push((async () => {
157
+ try {
158
+ feedReport.data = await executor.pushAsync({
159
+ id,
160
+ setup: target.setup,
161
+ teardown: target.teardown,
162
+ pre: measure.pre,
163
+ run: measure.run,
164
+ post: measure.post,
165
+ data: feed.data,
166
+ });
167
+ }
168
+ catch (error) {
169
+ feedReport.data = createExecutorErrorReport(error);
170
+ }
171
+ finally {
172
+ progressMap.delete(id);
173
+ completedBenchmarks++;
174
+ }
175
+ })());
176
+ }
177
+ targetReport.measures.push(measureReport);
168
178
  }
169
- targetReport.measures.push(measureReport);
179
+ reports.push(targetReport);
170
180
  }
171
- reports.push(targetReport);
181
+ await Promise.all(pendingReports);
182
+ if (bar) {
183
+ bar.update(1, { label: 'done' });
184
+ bar.terminate();
185
+ }
186
+ return reports;
172
187
  }
173
- await executor.drain();
174
- executor.kill();
175
- if (bar) {
176
- bar.update(1, {
177
- label: 'done'
178
- });
179
- bar.terminate();
188
+ finally {
189
+ executor.kill();
180
190
  }
181
- return reports;
182
191
  }
183
192
  }
184
- export const printSimpleReports = (reports)=>{
185
- for (const report of reports){
186
- for (const { measure, feeds } of report.measures){
193
+ export const printSimpleReports = (reports) => {
194
+ for (const report of reports) {
195
+ for (const { measure, feeds } of report.measures) {
187
196
  console.group('\n', report.target, measure);
188
- for (const { feed, data } of feeds){
197
+ for (const { feed, data } of feeds) {
189
198
  const { count, heapUsedKB, dceWarning, error: benchError, ...metrics } = data;
190
199
  if (benchError) {
191
200
  console.log(feed, `\x1b[31m[error: ${benchError}]\x1b[0m`);
192
201
  continue;
193
202
  }
194
- const output = Object.entries(metrics).map(([key, report])=>`${key}: ${report.toString()}`).join('; ');
203
+ const output = Object.entries(metrics)
204
+ .map(([key, report]) => `${key}: ${report.toString()}`)
205
+ .join('; ');
195
206
  const extras = [];
196
- if (heapUsedKB) extras.push(`heap: ${heapUsedKB}KB`);
197
- if (dceWarning) extras.push('\x1b[33m[DCE warning]\x1b[0m');
207
+ if (heapUsedKB)
208
+ extras.push(`heap: ${heapUsedKB}KB`);
209
+ if (dceWarning)
210
+ extras.push('\x1b[33m[DCE warning]\x1b[0m');
198
211
  const extrasStr = extras.length > 0 ? ` (${extras.join(', ')})` : '';
199
212
  console.log(feed, output + extrasStr);
200
213
  }
@@ -202,44 +215,36 @@ export const printSimpleReports = (reports)=>{
202
215
  }
203
216
  }
204
217
  };
205
- export const printTableReports = (reports)=>{
206
- for (const report of reports){
207
- for (const { measure, feeds } of report.measures){
218
+ export const printTableReports = (reports) => {
219
+ for (const report of reports) {
220
+ for (const { measure, feeds } of report.measures) {
208
221
  console.log('\n', report.target, measure);
209
222
  const table = {};
210
- for (const { feed, data } of feeds){
223
+ for (const { feed, data } of feeds) {
211
224
  const { error: benchError } = data;
212
225
  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
- ]));
226
+ table[feed] = { error: benchError };
227
+ }
228
+ else {
229
+ table[feed] = Object.fromEntries(Object.entries(data).map(([key, report]) => [key, report.toString()]));
221
230
  }
222
231
  }
223
232
  console.table(table);
224
233
  }
225
234
  }
226
235
  };
227
- export const printJSONReports = (reports, padding)=>{
236
+ export const printJSONReports = (reports, padding) => {
228
237
  const output = {};
229
- for (const report of reports){
230
- for (const { measure, feeds } of report.measures){
238
+ for (const report of reports) {
239
+ for (const { measure, feeds } of report.measures) {
231
240
  const row = {};
232
- for (const { feed, data } of feeds){
241
+ for (const { feed, data } of feeds) {
233
242
  const { error: benchError } = data;
234
243
  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
- ]));
244
+ row[feed] = { error: String(benchError) };
245
+ }
246
+ else {
247
+ row[feed] = Object.fromEntries(Object.entries(data).map(([key, report]) => [key, report.toString()]));
243
248
  }
244
249
  }
245
250
  output[`${report.target} ${measure}`] = row;
@@ -247,83 +252,74 @@ export const printJSONReports = (reports, padding)=>{
247
252
  }
248
253
  console.log(JSON.stringify(output, null, padding));
249
254
  };
250
- export const printMarkdownReports = (reports)=>{
251
- for (const report of reports){
252
- for (const { measure, feeds } of report.measures){
255
+ export const printMarkdownReports = (reports) => {
256
+ for (const report of reports) {
257
+ for (const { measure, feeds } of report.measures) {
253
258
  console.log(`\n## ${report.target} - ${measure}\n`);
254
- if (feeds.length === 0) continue;
255
- const firstValid = feeds.find((f)=>!f.data.error);
259
+ if (feeds.length === 0)
260
+ continue;
261
+ const firstValid = feeds.find((f) => !f.data.error);
256
262
  if (!firstValid) {
257
- for (const { feed, data } of feeds){
263
+ for (const { feed, data } of feeds) {
258
264
  console.log(`| ${feed} | error: ${data.error} |`);
259
265
  }
260
266
  continue;
261
267
  }
262
- const keys = Object.keys(firstValid.data).filter((k)=>k !== 'count' && k !== 'error');
263
- const header = [
264
- 'Feed',
265
- ...keys
266
- ].join(' | ');
267
- const separator = [
268
- '---',
269
- ...keys.map(()=>'---')
270
- ].join(' | ');
268
+ const keys = Object.keys(firstValid.data).filter((k) => k !== 'count' && k !== 'error');
269
+ const header = ['Feed', ...keys].join(' | ');
270
+ const separator = ['---', ...keys.map(() => '---')].join(' | ');
271
271
  console.log(`| ${header} |`);
272
272
  console.log(`| ${separator} |`);
273
- for (const { feed, data } of feeds){
273
+ for (const { feed, data } of feeds) {
274
274
  if (data.error) {
275
275
  console.log(`| ${feed} | error: ${data.error} |`);
276
276
  continue;
277
277
  }
278
- const values = keys.map((k)=>data[k]?.toString() ?? '-');
279
- console.log(`| ${[
280
- feed,
281
- ...values
282
- ].join(' | ')} |`);
278
+ const values = keys.map((k) => data[k]?.toString() ?? '-');
279
+ console.log(`| ${[feed, ...values].join(' | ')} |`);
283
280
  }
284
281
  }
285
282
  }
286
283
  };
287
- export const printHistogramReports = (reports, width = 40)=>{
288
- for (const report of reports){
289
- for (const { measure, feeds } of report.measures){
284
+ export const printHistogramReports = (reports, width = 40) => {
285
+ for (const report of reports) {
286
+ for (const { measure, feeds } of report.measures) {
290
287
  console.log(`\n${report.target} - ${measure}\n`);
291
288
  const opsKey = 'ops';
292
- const values = feeds.map((f)=>{
289
+ const values = feeds.map((f) => {
293
290
  const { error: benchError } = f.data;
294
291
  return {
295
292
  feed: f.feed,
296
- value: benchError ? 0 : f.data[opsKey]?.valueOf() ?? 0,
297
- error: benchError
293
+ value: benchError ? 0 : (f.data[opsKey]?.valueOf() ?? 0),
294
+ error: benchError,
298
295
  };
299
296
  });
300
- const maxValue = Math.max(...values.map((v)=>v.value));
301
- const maxLabelLen = Math.max(...values.map((v)=>v.feed.length));
302
- for (const { feed, value, error } of values){
297
+ const maxValue = Math.max(...values.map((v) => v.value));
298
+ const maxLabelLen = Math.max(...values.map((v) => v.feed.length));
299
+ for (const { feed, value, error } of values) {
303
300
  const label = feed.padEnd(maxLabelLen);
304
301
  if (error) {
305
302
  console.log(` ${label} | \x1b[31m[error: ${error}]\x1b[0m`);
306
303
  continue;
307
304
  }
308
- const barLen = maxValue > 0 ? Math.round(value / maxValue * width) : 0;
305
+ const barLen = maxValue > 0 ? Math.round((value / maxValue) * width) : 0;
309
306
  const bar = '\u2588'.repeat(barLen);
310
- const formatted = value.toLocaleString('en-US', {
311
- maximumFractionDigits: 2
312
- });
307
+ const formatted = value.toLocaleString('en-US', { maximumFractionDigits: 2 });
313
308
  console.log(` ${label} | ${bar} ${formatted} ops/s`);
314
309
  }
315
310
  }
316
311
  }
317
312
  };
318
- export const reportsToBaseline = (reports)=>{
313
+ export const reportsToBaseline = (reports) => {
319
314
  const results = {};
320
- for (const report of reports){
321
- for (const { measure, feeds } of report.measures){
322
- for (const { feed, data } of feeds){
323
- if (data.error) continue;
315
+ for (const report of reports) {
316
+ for (const { measure, feeds } of report.measures) {
317
+ for (const { feed, data } of feeds) {
318
+ if (data.error)
319
+ continue;
324
320
  const key = `${report.target}/${measure}/${feed}`;
325
321
  results[key] = {};
326
- for (const [metric, value] of Object.entries(data)){
322
+ for (const [metric, value] of Object.entries(data)) {
327
323
  if (metric !== 'count' && typeof value.valueOf === 'function') {
328
324
  results[key][metric] = value.valueOf();
329
325
  }
@@ -334,14 +330,14 @@ export const reportsToBaseline = (reports)=>{
334
330
  return {
335
331
  version: 1,
336
332
  timestamp: new Date().toISOString(),
337
- results
333
+ results,
338
334
  };
339
335
  };
340
- export const printComparisonReports = (reports, baseline, threshold = 5)=>{
341
- for (const report of reports){
342
- for (const { measure, feeds } of report.measures){
336
+ export const printComparisonReports = (reports, baseline, threshold = 5) => {
337
+ for (const report of reports) {
338
+ for (const { measure, feeds } of report.measures) {
343
339
  console.log(`\n${report.target} - ${measure}\n`);
344
- for (const { feed, data } of feeds){
340
+ for (const { feed, data } of feeds) {
345
341
  const key = `${report.target}/${measure}/${feed}`;
346
342
  const baselineData = baseline.results[key];
347
343
  console.log(` ${feed}:`);
@@ -349,22 +345,26 @@ export const printComparisonReports = (reports, baseline, threshold = 5)=>{
349
345
  console.log(` \x1b[31m[error: ${data.error}]\x1b[0m`);
350
346
  continue;
351
347
  }
352
- for (const [metric, value] of Object.entries(data)){
353
- if (metric === 'count') continue;
348
+ for (const [metric, value] of Object.entries(data)) {
349
+ if (metric === 'count')
350
+ continue;
354
351
  const current = value.valueOf();
355
352
  const baselineValue = baselineData?.[metric];
356
353
  if (baselineValue !== undefined && baselineValue !== 0) {
357
- const change = (current - baselineValue) / baselineValue * 100;
354
+ const change = ((current - baselineValue) / baselineValue) * 100;
358
355
  const isOps = metric === 'ops';
359
356
  const improved = isOps ? change > threshold : change < -threshold;
360
357
  const regressed = isOps ? change < -threshold : change > threshold;
361
358
  let indicator = ' ';
362
- if (improved) indicator = '\x1b[32m+\x1b[0m';
363
- else if (regressed) indicator = '\x1b[31m!\x1b[0m';
359
+ if (improved)
360
+ indicator = '\x1b[32m+\x1b[0m';
361
+ else if (regressed)
362
+ indicator = '\x1b[31m!\x1b[0m';
364
363
  const changeStr = change >= 0 ? `+${change.toFixed(1)}%` : `${change.toFixed(1)}%`;
365
364
  const coloredChange = regressed ? `\x1b[31m${changeStr}\x1b[0m` : improved ? `\x1b[32m${changeStr}\x1b[0m` : changeStr;
366
365
  console.log(` ${indicator} ${metric}: ${value.toString()} (${coloredChange})`);
367
- } else {
366
+ }
367
+ else {
368
368
  console.log(` * ${metric}: ${value.toString()} (new)`);
369
369
  }
370
370
  }
@@ -373,5 +373,3 @@ export const printComparisonReports = (reports, baseline, threshold = 5)=>{
373
373
  }
374
374
  console.log(`\nBaseline from: ${baseline.timestamp}`);
375
375
  };
376
-
377
- //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,15 @@
1
+ import { register } from 'node:module';
2
+ async function resolve(s, c, n) {
3
+ try {
4
+ return await n(s, c);
5
+ }
6
+ catch (e) {
7
+ if (s.endsWith('.js'))
8
+ try {
9
+ return await n(s.slice(0, -3) + '.ts', c);
10
+ }
11
+ catch { }
12
+ throw e;
13
+ }
14
+ }
15
+ register('data:text/javascript,' + encodeURIComponent(`export ${resolve.toString()}`));
@@ -1,4 +1,4 @@
1
- import { ReportType } from './types.js';
1
+ import { type ReportType } from './types.js';
2
2
  export declare class Report {
3
3
  readonly type: ReportType;
4
4
  readonly value: bigint;
@@ -8,4 +8,12 @@ export declare class Report {
8
8
  valueOf(): number;
9
9
  toString(): string;
10
10
  }
11
- export declare const createReport: (durations: BigUint64Array, type: ReportType) => Report;
11
+ type Stats = {
12
+ sum: bigint;
13
+ mean: bigint;
14
+ ssd: bigint;
15
+ n: bigint;
16
+ };
17
+ export declare const computeStats: (durations: BigUint64Array) => Stats;
18
+ export declare const createReport: (durations: BigUint64Array, type: ReportType, stats?: Stats) => Report;
19
+ export {};