overtake 0.0.1-rc3 → 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/cli.js +11 -7
- package/index.d.ts +24 -50
- package/index.js +103 -173
- package/package.json +2 -2
- package/reporter.js +0 -90
package/cli.js
CHANGED
|
@@ -1,19 +1,23 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
import { promisify } from 'util';
|
|
4
|
+
import Path from 'path';
|
|
4
5
|
import glob from 'glob';
|
|
5
|
-
import {
|
|
6
|
-
import { defaultReporter } from './reporter.js';
|
|
6
|
+
import { load, benchmark, setup, teardown, measure, perform, run, defaultReporter } from './index.js';
|
|
7
7
|
|
|
8
8
|
const globAsync = promisify(glob);
|
|
9
9
|
const pattern = process.argv[2] || '**/__benchmarks__/**/*.js';
|
|
10
|
-
|
|
10
|
+
|
|
11
|
+
Object.assign(globalThis, { benchmark, setup, teardown, measure, perform });
|
|
11
12
|
|
|
12
13
|
(async () => {
|
|
13
14
|
const files = await globAsync(pattern);
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
const scripts = [];
|
|
16
|
+
for (const file of files) {
|
|
17
|
+
const filename = Path.resolve(file);
|
|
18
|
+
const script = await load(filename);
|
|
19
|
+
scripts.push(script);
|
|
17
20
|
}
|
|
18
|
-
|
|
21
|
+
|
|
22
|
+
await run(scripts, defaultReporter);
|
|
19
23
|
})().catch((e) => console.error(e));
|
package/index.d.ts
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import { Event } from 'evnty';
|
|
2
|
-
|
|
3
1
|
declare global {
|
|
4
2
|
type CanBePromise<T> = Promise<T> | T;
|
|
5
3
|
|
|
@@ -11,8 +9,15 @@ declare global {
|
|
|
11
9
|
max: number;
|
|
12
10
|
sum: number;
|
|
13
11
|
avg: number;
|
|
14
|
-
med: number;
|
|
15
12
|
mode: number;
|
|
13
|
+
p1: number;
|
|
14
|
+
p5: number;
|
|
15
|
+
p20: number;
|
|
16
|
+
p33: number;
|
|
17
|
+
p50: number;
|
|
18
|
+
med: number;
|
|
19
|
+
p66: number;
|
|
20
|
+
p80: number;
|
|
16
21
|
p90: number;
|
|
17
22
|
p95: number;
|
|
18
23
|
p99: number;
|
|
@@ -23,52 +28,6 @@ declare global {
|
|
|
23
28
|
total: number;
|
|
24
29
|
}
|
|
25
30
|
|
|
26
|
-
interface Overtake {
|
|
27
|
-
onLoad: Event<any>;
|
|
28
|
-
|
|
29
|
-
onRun: Event<any>;
|
|
30
|
-
|
|
31
|
-
onComplete: Event<any>;
|
|
32
|
-
|
|
33
|
-
onScriptRegister: Event<any>;
|
|
34
|
-
|
|
35
|
-
onScriptStart: Event<any>;
|
|
36
|
-
|
|
37
|
-
onScriptComplete: Event<any>;
|
|
38
|
-
|
|
39
|
-
onSuiteRegister: Event<any>;
|
|
40
|
-
|
|
41
|
-
onSuiteStart: Event<any>;
|
|
42
|
-
|
|
43
|
-
onSuiteComplete: Event<any>;
|
|
44
|
-
|
|
45
|
-
onSetupRegister: Event<any>;
|
|
46
|
-
|
|
47
|
-
onTeardownRegister: Event<any>;
|
|
48
|
-
|
|
49
|
-
onMeasureRegister: Event<any>;
|
|
50
|
-
|
|
51
|
-
onMeasureStart: Event<any>;
|
|
52
|
-
|
|
53
|
-
onMeasureComplete: Event<any>;
|
|
54
|
-
|
|
55
|
-
onPerformRegister: Event<any>;
|
|
56
|
-
|
|
57
|
-
onPerformStart: Event<any>;
|
|
58
|
-
|
|
59
|
-
onPerformProgress: Event<any>;
|
|
60
|
-
|
|
61
|
-
onPerformComplete: Event<any>;
|
|
62
|
-
|
|
63
|
-
onReport: Event<Report>;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
function benchmark(title: string, init: () => void): void;
|
|
67
|
-
|
|
68
|
-
function setup<C>(init: () => CanBePromise<C>): any;
|
|
69
|
-
|
|
70
|
-
function teardown<C>(teardown: (context: C) => CanBePromise<void>): void;
|
|
71
|
-
|
|
72
31
|
type MeasureInitResult = CanBePromise<() => void>;
|
|
73
32
|
|
|
74
33
|
function measure(title: string, init: () => MeasureInitResult): void;
|
|
@@ -78,5 +37,20 @@ declare global {
|
|
|
78
37
|
|
|
79
38
|
function perform<A>(title: string, counter: number, args: A): void;
|
|
80
39
|
|
|
81
|
-
function
|
|
40
|
+
function setup<C>(init: () => CanBePromise<C>): void;
|
|
41
|
+
|
|
42
|
+
function teardown<C>(teardown: (context: C) => CanBePromise<void>): void;
|
|
43
|
+
|
|
44
|
+
interface Suite {
|
|
45
|
+
title: string;
|
|
46
|
+
setup: typeof setup;
|
|
47
|
+
teardown: typeof teardown;
|
|
48
|
+
measures: typeof measure[];
|
|
49
|
+
performs: typeof perform[];
|
|
50
|
+
init: () => void;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function benchmark(title: string, init: () => void): void;
|
|
54
|
+
|
|
55
|
+
function script(filename): Promise<Suite[]>;
|
|
82
56
|
}
|
package/index.js
CHANGED
|
@@ -1,183 +1,112 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { createContext } from 'conode';
|
|
2
2
|
import WorkerThreads from 'worker_threads';
|
|
3
|
-
import { Event } from 'evnty';
|
|
4
3
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
export class Perform {
|
|
8
|
-
title = '';
|
|
9
|
-
|
|
10
|
-
count = 0;
|
|
11
|
-
|
|
12
|
-
args;
|
|
13
|
-
|
|
14
|
-
constructor(overtake, title, count, args) {
|
|
15
|
-
this.title = title;
|
|
16
|
-
this.count = count;
|
|
17
|
-
this.args = args;
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
export class Measure {
|
|
22
|
-
title = '';
|
|
4
|
+
const overtakeContext = createContext();
|
|
5
|
+
const suiteContext = createContext();
|
|
23
6
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
constructor(overtake, title, init = NOOP) {
|
|
27
|
-
this.title = title;
|
|
28
|
-
this.init = init;
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
export class Suite {
|
|
33
|
-
title = '';
|
|
34
|
-
|
|
35
|
-
setup = NOOP;
|
|
36
|
-
|
|
37
|
-
measures = [];
|
|
38
|
-
|
|
39
|
-
performs = [];
|
|
7
|
+
export const NOOP = () => {};
|
|
40
8
|
|
|
41
|
-
|
|
9
|
+
export const setup = (fn) => {
|
|
10
|
+
suiteContext.getContext().setup = fn;
|
|
11
|
+
};
|
|
42
12
|
|
|
43
|
-
|
|
13
|
+
export const teardown = (fn) => {
|
|
14
|
+
suiteContext.getContext().teardown = fn;
|
|
15
|
+
};
|
|
44
16
|
|
|
45
|
-
|
|
17
|
+
export const measure = (title, fn) => {
|
|
18
|
+
suiteContext.getContext().measures.push({ title, init: fn });
|
|
19
|
+
};
|
|
46
20
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
this.#init = init;
|
|
51
|
-
}
|
|
21
|
+
export const perform = (title, count, args) => {
|
|
22
|
+
suiteContext.getContext().performs.push({ title, count, args });
|
|
23
|
+
};
|
|
52
24
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
25
|
+
export const benchmark = (title, fn) => {
|
|
26
|
+
const setup = NOOP;
|
|
27
|
+
const teardown = NOOP;
|
|
28
|
+
const measures = [];
|
|
29
|
+
const performs = [];
|
|
30
|
+
|
|
31
|
+
overtakeContext.getContext().suites.push({
|
|
32
|
+
title,
|
|
33
|
+
setup,
|
|
34
|
+
teardown,
|
|
35
|
+
measures,
|
|
36
|
+
performs,
|
|
37
|
+
init: fn,
|
|
38
|
+
});
|
|
39
|
+
};
|
|
64
40
|
|
|
65
|
-
export
|
|
66
|
-
|
|
41
|
+
export const load = async (filename) => {
|
|
42
|
+
const suites = [];
|
|
43
|
+
const script = { filename, suites };
|
|
44
|
+
await overtakeContext.contextualize(script, () => import(filename));
|
|
67
45
|
|
|
68
|
-
|
|
46
|
+
return script;
|
|
47
|
+
};
|
|
48
|
+
const map = {
|
|
49
|
+
script: '⭐ Script ',
|
|
50
|
+
suite: '⇶ Suite ',
|
|
51
|
+
perform: '➤ Perform ',
|
|
52
|
+
measure: '✓ Measure',
|
|
53
|
+
};
|
|
69
54
|
|
|
70
|
-
|
|
55
|
+
export const defaultReporter = async (type, title, test) => {
|
|
56
|
+
console.group(`${map[type]} ${title}`);
|
|
57
|
+
await test({ test: defaultReporter, output: (report) => console.table(report) });
|
|
58
|
+
console.groupEnd();
|
|
59
|
+
};
|
|
71
60
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
61
|
+
const ACCURACY = 6;
|
|
62
|
+
export function formatFloat(value, digits = ACCURACY) {
|
|
63
|
+
return parseFloat(value.toFixed(digits));
|
|
75
64
|
}
|
|
76
65
|
|
|
77
|
-
export
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
onRun = new Event();
|
|
81
|
-
|
|
82
|
-
onComplete = new Event();
|
|
83
|
-
|
|
84
|
-
onScriptRegister = new Event();
|
|
85
|
-
|
|
86
|
-
onScriptStart = new Event();
|
|
87
|
-
|
|
88
|
-
onScriptComplete = new Event();
|
|
89
|
-
|
|
90
|
-
onSuiteRegister = new Event();
|
|
91
|
-
|
|
92
|
-
onSuiteStart = new Event();
|
|
93
|
-
|
|
94
|
-
onSuiteComplete = new Event();
|
|
95
|
-
|
|
96
|
-
onSetupRegister = new Event();
|
|
97
|
-
|
|
98
|
-
onTeardownRegister = new Event();
|
|
99
|
-
|
|
100
|
-
onMeasureRegister = new Event();
|
|
101
|
-
|
|
102
|
-
onMeasureStart = new Event();
|
|
103
|
-
|
|
104
|
-
onMeasureComplete = new Event();
|
|
105
|
-
|
|
106
|
-
onPerformRegister = new Event();
|
|
107
|
-
|
|
108
|
-
onPerformStart = new Event();
|
|
109
|
-
|
|
110
|
-
onPerformProgress = new Event();
|
|
111
|
-
|
|
112
|
-
onPerformComplete = new Event();
|
|
113
|
-
|
|
114
|
-
onReport = new Event();
|
|
115
|
-
|
|
116
|
-
scripts = [];
|
|
117
|
-
|
|
118
|
-
reporters = [];
|
|
119
|
-
|
|
120
|
-
constructor(options = {}) {
|
|
121
|
-
Object.assign(globalThis, {
|
|
122
|
-
benchmark: (title, init) => this.onSuiteRegister(new Suite(this, title, init)),
|
|
123
|
-
setup: (init) => this.onSetupRegister(init),
|
|
124
|
-
teardown: (init) => this.onTeardownRegister(init),
|
|
125
|
-
measure: (title, init) => this.onMeasureRegister(new Measure(this, title, init)),
|
|
126
|
-
perform: (title, count, args) => this.onPerformRegister(new Perform(this, title, count, args)),
|
|
127
|
-
reporter: (reporter) => this.reporters.push(reporter(this)),
|
|
128
|
-
});
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
async load(files) {
|
|
132
|
-
this.onLoad(this);
|
|
133
|
-
for (const file of files) {
|
|
134
|
-
const filename = Path.resolve(file);
|
|
135
|
-
const script = new Script(filename);
|
|
136
|
-
const unsubscribe = this.onSuiteRegister.on((suite) => {
|
|
137
|
-
script.suites.push(suite);
|
|
138
|
-
});
|
|
139
|
-
await import(filename);
|
|
140
|
-
unsubscribe();
|
|
141
|
-
this.scripts.push(script);
|
|
142
|
-
this.onScriptRegister(script);
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
async run() {
|
|
147
|
-
this.onRun();
|
|
148
|
-
for (const script of this.scripts) {
|
|
149
|
-
this.onScriptStart(script);
|
|
66
|
+
export const run = async (scripts, reporter) => {
|
|
67
|
+
for (const script of scripts) {
|
|
68
|
+
await reporter('script', script.filename, async (scriptTest) => {
|
|
150
69
|
for (const suite of script.suites) {
|
|
151
|
-
await
|
|
152
|
-
|
|
153
|
-
for (const measure of suite.measures) {
|
|
154
|
-
this.onMeasureStart(measure);
|
|
70
|
+
await scriptTest.test('suite', suite.title, async (suiteTest) => {
|
|
71
|
+
await suiteContext.contextualize(suite, suite.init);
|
|
155
72
|
for (const perform of suite.performs) {
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
73
|
+
await suiteTest.test('perform', perform.title, async (performTest) => {
|
|
74
|
+
for (const measure of suite.measures) {
|
|
75
|
+
await performTest.test('measure', measure.title, async (measureTest) => {
|
|
76
|
+
const result = await runWorker({
|
|
77
|
+
setup: suite.setup,
|
|
78
|
+
teardown: suite.teardown,
|
|
79
|
+
init: measure.init,
|
|
80
|
+
count: perform.count,
|
|
81
|
+
args: perform.args,
|
|
82
|
+
});
|
|
83
|
+
if (result.success) {
|
|
84
|
+
measureTest.output({
|
|
85
|
+
[formatFloat(result.mode)]: {
|
|
86
|
+
total: formatFloat(result.total),
|
|
87
|
+
med: formatFloat(result.med),
|
|
88
|
+
p95: formatFloat(result.p95),
|
|
89
|
+
p99: formatFloat(result.p99),
|
|
90
|
+
},
|
|
91
|
+
});
|
|
92
|
+
} else {
|
|
93
|
+
measureTest.output({
|
|
94
|
+
error: {
|
|
95
|
+
reason: result.error,
|
|
96
|
+
},
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
});
|
|
169
102
|
}
|
|
170
|
-
|
|
171
|
-
}
|
|
172
|
-
this.onSuiteComplete(perform);
|
|
103
|
+
});
|
|
173
104
|
}
|
|
174
|
-
|
|
175
|
-
}
|
|
176
|
-
this.onComplete(this);
|
|
105
|
+
});
|
|
177
106
|
}
|
|
178
|
-
}
|
|
107
|
+
};
|
|
179
108
|
|
|
180
|
-
export async function runWorker({ args, count, ...options }, onProgress) {
|
|
109
|
+
export async function runWorker({ args, count, ...options }, onProgress = null) {
|
|
181
110
|
const setupCode = options.setup.toString();
|
|
182
111
|
const teardownCode = options.teardown.toString();
|
|
183
112
|
const initCode = options.init.toString();
|
|
@@ -192,7 +121,7 @@ export async function runWorker({ args, count, ...options }, onProgress) {
|
|
|
192
121
|
const worker = new WorkerThreads.Worker(new URL('runner.js', import.meta.url), { argv: [params] });
|
|
193
122
|
return new Promise((resolve) => {
|
|
194
123
|
worker.on('message', (data) => {
|
|
195
|
-
if (data.type === 'progress') {
|
|
124
|
+
if (onProgress && data.type === 'progress') {
|
|
196
125
|
onProgress(data);
|
|
197
126
|
} else if (data.type === 'report') {
|
|
198
127
|
resolve(data);
|
|
@@ -292,14 +221,7 @@ export async function start(input) {
|
|
|
292
221
|
});
|
|
293
222
|
buckets.sort((a, b) => a[1] - b[1]);
|
|
294
223
|
|
|
295
|
-
const
|
|
296
|
-
const med = timings[medIdx];
|
|
297
|
-
const p90Idx = Math.trunc((90 * timings.length) / 100);
|
|
298
|
-
const p90 = timings[p90Idx];
|
|
299
|
-
const p95Idx = Math.trunc((95 * timings.length) / 100);
|
|
300
|
-
const p95 = timings[p95Idx];
|
|
301
|
-
const p99Idx = Math.trunc((99 * timings.length) / 100);
|
|
302
|
-
const p99 = timings[p99Idx];
|
|
224
|
+
const percentile = (p) => timings[Math.trunc((p * timings.length) / 100)];
|
|
303
225
|
const mode = buckets[buckets.length - 1][0];
|
|
304
226
|
|
|
305
227
|
send({
|
|
@@ -310,11 +232,19 @@ export async function start(input) {
|
|
|
310
232
|
max,
|
|
311
233
|
sum,
|
|
312
234
|
avg,
|
|
313
|
-
med,
|
|
314
235
|
mode,
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
236
|
+
p1: percentile(1),
|
|
237
|
+
p5: percentile(5),
|
|
238
|
+
p10: percentile(10),
|
|
239
|
+
p20: percentile(20),
|
|
240
|
+
p33: percentile(33),
|
|
241
|
+
p50: percentile(50),
|
|
242
|
+
med: percentile(50),
|
|
243
|
+
p66: percentile(66),
|
|
244
|
+
p80: percentile(80),
|
|
245
|
+
p90: percentile(90),
|
|
246
|
+
p95: percentile(95),
|
|
247
|
+
p99: percentile(99),
|
|
318
248
|
setup: setupMark - startMark,
|
|
319
249
|
init: initDoneMark - initMark,
|
|
320
250
|
cycles: teardownMark - cyclesMark,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "overtake",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.2",
|
|
4
4
|
"description": "NodeJS performance benchmark",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"types": "index.d.ts",
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
"pretty-quick": "^3.1.3"
|
|
40
40
|
},
|
|
41
41
|
"dependencies": {
|
|
42
|
-
"
|
|
42
|
+
"conode": "^0.1.0",
|
|
43
43
|
"glob": "^8.0.1"
|
|
44
44
|
}
|
|
45
45
|
}
|
package/reporter.js
DELETED
|
@@ -1,90 +0,0 @@
|
|
|
1
|
-
const SPINNER = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏', '⠿'];
|
|
2
|
-
const SPINNER_INTERVAL = 100;
|
|
3
|
-
const SPINNER_PADDING = 5;
|
|
4
|
-
|
|
5
|
-
const ACCURACY = 6;
|
|
6
|
-
|
|
7
|
-
/** TODO
|
|
8
|
-
* [PROGRESS] script/file.js
|
|
9
|
-
* Test suite title
|
|
10
|
-
* ➤ Measure
|
|
11
|
-
* ✓ Perform
|
|
12
|
-
* ✕ Perform
|
|
13
|
-
* */
|
|
14
|
-
|
|
15
|
-
const renderString = (message, x, direction) => {
|
|
16
|
-
const size = message.length;
|
|
17
|
-
process.stdout.moveCursor(0, -1);
|
|
18
|
-
process.stdout.cursorTo(x);
|
|
19
|
-
process.stdout.clearLine(direction);
|
|
20
|
-
if (direction === -1) {
|
|
21
|
-
process.stdout.cursorTo(0);
|
|
22
|
-
}
|
|
23
|
-
process.stdout.write(message);
|
|
24
|
-
process.stdout.moveCursor(-process.stdout.rows, 1);
|
|
25
|
-
|
|
26
|
-
return size;
|
|
27
|
-
};
|
|
28
|
-
|
|
29
|
-
const renderSpinner = (index) => renderString(SPINNER[index], 0, -1);
|
|
30
|
-
|
|
31
|
-
const paddings = [];
|
|
32
|
-
|
|
33
|
-
const renderMessage = (column, message) => {
|
|
34
|
-
const padding = SPINNER_PADDING + column * 10;
|
|
35
|
-
paddings[column + 1] = renderString(message, padding, 1);
|
|
36
|
-
};
|
|
37
|
-
|
|
38
|
-
export function formatFloat(value, digits = ACCURACY) {
|
|
39
|
-
return parseFloat(value.toFixed(digits));
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
export function defaultReporter(overtake) {
|
|
43
|
-
const spinnerSize = SPINNER.length - 1;
|
|
44
|
-
let i = 0;
|
|
45
|
-
let timerId = null;
|
|
46
|
-
|
|
47
|
-
overtake.onLoad.on(() => {});
|
|
48
|
-
overtake.onRun.on(() => {
|
|
49
|
-
console.log();
|
|
50
|
-
});
|
|
51
|
-
overtake.onComplete.on(() => {});
|
|
52
|
-
overtake.onScriptRegister.on(() => {});
|
|
53
|
-
overtake.onScriptStart.on(() => {});
|
|
54
|
-
overtake.onScriptComplete.on(() => {});
|
|
55
|
-
overtake.onSuiteRegister.on(() => {});
|
|
56
|
-
overtake.onSuiteStart.on(() => {});
|
|
57
|
-
overtake.onSuiteComplete.on(() => {});
|
|
58
|
-
overtake.onSetupRegister.on(() => {});
|
|
59
|
-
overtake.onTeardownRegister.on(() => {});
|
|
60
|
-
overtake.onMeasureRegister.on(() => {});
|
|
61
|
-
overtake.onMeasureStart.on((measure) => {
|
|
62
|
-
console.log(measure.title);
|
|
63
|
-
});
|
|
64
|
-
overtake.onMeasureComplete.on(() => {});
|
|
65
|
-
overtake.onPerformRegister.on(() => {});
|
|
66
|
-
overtake.onPerformStart.on((perform) => {
|
|
67
|
-
console.log(perform.title);
|
|
68
|
-
console.log();
|
|
69
|
-
i = 0;
|
|
70
|
-
timerId = setInterval(() => renderSpinner(i++ % spinnerSize), SPINNER_INTERVAL);
|
|
71
|
-
});
|
|
72
|
-
overtake.onPerformComplete.on(() => {
|
|
73
|
-
clearInterval(timerId);
|
|
74
|
-
renderSpinner(spinnerSize);
|
|
75
|
-
});
|
|
76
|
-
overtake.onPerformProgress.on(({ stage, progress }) => {
|
|
77
|
-
renderMessage(0, stage);
|
|
78
|
-
if (typeof progress !== 'undefined') {
|
|
79
|
-
renderMessage(1, `${(progress * 100).toFixed(0)}%`.padStart(4, ' '));
|
|
80
|
-
}
|
|
81
|
-
});
|
|
82
|
-
overtake.onReport.on((report) => {
|
|
83
|
-
if (report.success) {
|
|
84
|
-
renderMessage(2, `total:${report.total.toFixed(0)}ms mode:${report.mode.toFixed(ACCURACY)}ms`);
|
|
85
|
-
} else {
|
|
86
|
-
renderMessage(1, report.error);
|
|
87
|
-
}
|
|
88
|
-
console.log();
|
|
89
|
-
});
|
|
90
|
-
}
|