overtake 0.0.1-rc3 → 0.0.4
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 +59 -16
- package/index.d.ts +24 -50
- package/index.js +117 -175
- package/package.json +4 -3
- package/reporter.js +0 -90
package/cli.js
CHANGED
|
@@ -1,19 +1,62 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
1
|
+
#!/usr/bin/env -S node --no-warnings
|
|
2
2
|
|
|
3
|
+
import { Command } from 'commander';
|
|
3
4
|
import { promisify } from 'util';
|
|
5
|
+
import Path from 'path';
|
|
4
6
|
import glob from 'glob';
|
|
5
|
-
import {
|
|
6
|
-
import
|
|
7
|
-
|
|
8
|
-
const
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
7
|
+
import { load, createScript, benchmark, setup, teardown, measure, perform, run, defaultReporter } from './index.js';
|
|
8
|
+
import packageJson from './package.json' assert { type: 'json' };
|
|
9
|
+
|
|
10
|
+
const commands = new Command();
|
|
11
|
+
|
|
12
|
+
commands.name('overtake').description(packageJson.description).version(packageJson.version, '-v, --version');
|
|
13
|
+
|
|
14
|
+
commands
|
|
15
|
+
.argument('[files...]', 'file paths or path patterns to search benchmark scripts')
|
|
16
|
+
.option('-i, --inline [inline]', 'inline code to benchmark', (value, previous) => previous.concat([value]), [])
|
|
17
|
+
.option('-c, --count [count]', 'perform count for inline code', (v) => parseInt(v))
|
|
18
|
+
.action(async (patterns, { count = 1, inline }) => {
|
|
19
|
+
Object.assign(globalThis, { benchmark, setup, teardown, measure, perform });
|
|
20
|
+
|
|
21
|
+
const globAsync = promisify(glob);
|
|
22
|
+
const foundFiles = await Promise.all(patterns.map((pattern) => globAsync(pattern)));
|
|
23
|
+
const files = [
|
|
24
|
+
...new Set(
|
|
25
|
+
[]
|
|
26
|
+
.concat(...foundFiles)
|
|
27
|
+
.map((filename) => Path.resolve(filename))
|
|
28
|
+
.filter(Boolean)
|
|
29
|
+
),
|
|
30
|
+
];
|
|
31
|
+
|
|
32
|
+
const scripts = [];
|
|
33
|
+
if (inline.length) {
|
|
34
|
+
const inlineScript = await createScript('', () => {
|
|
35
|
+
benchmark('', () => {
|
|
36
|
+
inline.forEach((code) => {
|
|
37
|
+
measure(code, `() => () => { ${code} }`);
|
|
38
|
+
});
|
|
39
|
+
perform('', count);
|
|
40
|
+
});
|
|
41
|
+
});
|
|
42
|
+
scripts.push(inlineScript);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
for (const file of files) {
|
|
46
|
+
const filename = Path.resolve(file);
|
|
47
|
+
const script = await load(filename);
|
|
48
|
+
scripts.push(script);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
await run(scripts, defaultReporter);
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
commands.on('--help', () => {
|
|
55
|
+
console.log('');
|
|
56
|
+
console.log('Examples:');
|
|
57
|
+
console.log(' $ overtake **/__benchmarks__/*.js');
|
|
58
|
+
console.log(' $ overtake -i "class A{}" -i "function A(){}" -i "const A = () => {}" -c 1000000');
|
|
59
|
+
console.log(' $ overtake -v');
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
commands.parse(process.argv);
|
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,118 @@
|
|
|
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;
|
|
7
|
+
export const NOOP = () => {};
|
|
36
8
|
|
|
37
|
-
|
|
9
|
+
export const setup = (fn) => {
|
|
10
|
+
suiteContext.getContext().setup = fn;
|
|
11
|
+
};
|
|
38
12
|
|
|
39
|
-
|
|
13
|
+
export const teardown = (fn) => {
|
|
14
|
+
suiteContext.getContext().teardown = fn;
|
|
15
|
+
};
|
|
40
16
|
|
|
41
|
-
|
|
17
|
+
export const measure = (title, fn) => {
|
|
18
|
+
suiteContext.getContext().measures.push({ title, init: fn });
|
|
19
|
+
};
|
|
42
20
|
|
|
43
|
-
|
|
21
|
+
export const perform = (title, count, args) => {
|
|
22
|
+
suiteContext.getContext().performs.push({ title, count, args });
|
|
23
|
+
};
|
|
44
24
|
|
|
45
|
-
|
|
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
|
+
};
|
|
46
40
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
}
|
|
41
|
+
export const createScript = async (filename, fn) => {
|
|
42
|
+
const suites = [];
|
|
43
|
+
const script = { filename, suites };
|
|
44
|
+
await overtakeContext.contextualize(script, fn);
|
|
52
45
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
this.#overtake.onSetupRegister.on((setup) => (this.setup = setup)),
|
|
56
|
-
this.#overtake.onMeasureRegister.on((measure) => this.measures.push(measure)),
|
|
57
|
-
this.#overtake.onPerformRegister.on((perform) => this.performs.push(perform)),
|
|
58
|
-
this.#overtake.onTeardownRegister.on((teardown) => (this.teardown = teardown)),
|
|
59
|
-
];
|
|
60
|
-
await this.#init();
|
|
61
|
-
unsubscribes.forEach((unsubscribe) => unsubscribe());
|
|
62
|
-
}
|
|
63
|
-
}
|
|
46
|
+
return script;
|
|
47
|
+
};
|
|
64
48
|
|
|
65
|
-
export
|
|
66
|
-
|
|
49
|
+
export const load = async (filename) => {
|
|
50
|
+
return createScript(filename, () => import(filename));
|
|
51
|
+
};
|
|
67
52
|
|
|
68
|
-
|
|
53
|
+
const map = {
|
|
54
|
+
script: '⭐ Script ',
|
|
55
|
+
suite: '⇶ Suite ',
|
|
56
|
+
perform: '➤ Perform ',
|
|
57
|
+
measure: '✓ Measure',
|
|
58
|
+
};
|
|
69
59
|
|
|
70
|
-
|
|
60
|
+
export const defaultReporter = async (type, title, test) => {
|
|
61
|
+
console.group(`${map[type]} ${title}`);
|
|
62
|
+
await test({ test: defaultReporter, output: (report) => console.table(report) });
|
|
63
|
+
console.groupEnd();
|
|
64
|
+
};
|
|
71
65
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
66
|
+
const ACCURACY = 6;
|
|
67
|
+
export function formatFloat(value, digits = ACCURACY) {
|
|
68
|
+
return parseFloat(value.toFixed(digits));
|
|
75
69
|
}
|
|
76
70
|
|
|
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);
|
|
71
|
+
export const run = async (scripts, reporter) => {
|
|
72
|
+
for (const script of scripts) {
|
|
73
|
+
await reporter('script', script.filename, async (scriptTest) => {
|
|
150
74
|
for (const suite of script.suites) {
|
|
151
|
-
await
|
|
152
|
-
|
|
153
|
-
for (const measure of suite.measures) {
|
|
154
|
-
this.onMeasureStart(measure);
|
|
75
|
+
await scriptTest.test('suite', suite.title, async (suiteTest) => {
|
|
76
|
+
await suiteContext.contextualize(suite, suite.init);
|
|
155
77
|
for (const perform of suite.performs) {
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
78
|
+
await suiteTest.test('perform', perform.title, async (performTest) => {
|
|
79
|
+
for (const measure of suite.measures) {
|
|
80
|
+
await performTest.test('measure', measure.title, async (measureTest) => {
|
|
81
|
+
const result = await runWorker({
|
|
82
|
+
setup: suite.setup,
|
|
83
|
+
teardown: suite.teardown,
|
|
84
|
+
init: measure.init,
|
|
85
|
+
count: perform.count,
|
|
86
|
+
args: perform.args,
|
|
87
|
+
});
|
|
88
|
+
if (result.success) {
|
|
89
|
+
measureTest.output({
|
|
90
|
+
[formatFloat(result.mode)]: {
|
|
91
|
+
total: formatFloat(result.total),
|
|
92
|
+
med: formatFloat(result.med),
|
|
93
|
+
p95: formatFloat(result.p95),
|
|
94
|
+
p99: formatFloat(result.p99),
|
|
95
|
+
count: result.count,
|
|
96
|
+
},
|
|
97
|
+
});
|
|
98
|
+
} else {
|
|
99
|
+
measureTest.output({
|
|
100
|
+
error: {
|
|
101
|
+
reason: result.error,
|
|
102
|
+
},
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
});
|
|
169
108
|
}
|
|
170
|
-
|
|
171
|
-
}
|
|
172
|
-
this.onSuiteComplete(perform);
|
|
109
|
+
});
|
|
173
110
|
}
|
|
174
|
-
|
|
175
|
-
}
|
|
176
|
-
this.onComplete(this);
|
|
111
|
+
});
|
|
177
112
|
}
|
|
178
|
-
}
|
|
113
|
+
};
|
|
179
114
|
|
|
180
|
-
export async function runWorker({ args, count, ...options }, onProgress) {
|
|
115
|
+
export async function runWorker({ args, count, ...options }, onProgress = null) {
|
|
181
116
|
const setupCode = options.setup.toString();
|
|
182
117
|
const teardownCode = options.teardown.toString();
|
|
183
118
|
const initCode = options.init.toString();
|
|
@@ -192,7 +127,7 @@ export async function runWorker({ args, count, ...options }, onProgress) {
|
|
|
192
127
|
const worker = new WorkerThreads.Worker(new URL('runner.js', import.meta.url), { argv: [params] });
|
|
193
128
|
return new Promise((resolve) => {
|
|
194
129
|
worker.on('message', (data) => {
|
|
195
|
-
if (data.type === 'progress') {
|
|
130
|
+
if (onProgress && data.type === 'progress') {
|
|
196
131
|
onProgress(data);
|
|
197
132
|
} else if (data.type === 'report') {
|
|
198
133
|
resolve(data);
|
|
@@ -211,8 +146,8 @@ export async function start(input) {
|
|
|
211
146
|
const setup = Function(`return ${setupCode};`)();
|
|
212
147
|
const teardown = Function(`return ${teardownCode};`)();
|
|
213
148
|
const init = Function(`return ${initCode};`)();
|
|
149
|
+
const initArgsSize = init.length;
|
|
214
150
|
const send = WorkerThreads.parentPort ? (data) => WorkerThreads.parentPort.postMessage(data) : (data) => console.log(data);
|
|
215
|
-
|
|
216
151
|
let i = count;
|
|
217
152
|
let done = FALSE_START;
|
|
218
153
|
|
|
@@ -224,11 +159,14 @@ export async function start(input) {
|
|
|
224
159
|
const context = await setup();
|
|
225
160
|
const setupMark = performance.now();
|
|
226
161
|
|
|
227
|
-
const initArgs = [
|
|
228
|
-
if (
|
|
162
|
+
const initArgs = [];
|
|
163
|
+
if (initArgsSize !== 0) {
|
|
164
|
+
initArgs.push(() => done());
|
|
165
|
+
}
|
|
166
|
+
if (initArgsSize > 2) {
|
|
229
167
|
initArgs.unshift(args);
|
|
230
168
|
}
|
|
231
|
-
if (
|
|
169
|
+
if (initArgsSize > 1) {
|
|
232
170
|
initArgs.unshift(context);
|
|
233
171
|
}
|
|
234
172
|
|
|
@@ -259,6 +197,9 @@ export async function start(input) {
|
|
|
259
197
|
|
|
260
198
|
const startTickTime = performance.now();
|
|
261
199
|
action(...args[argIdx], idx);
|
|
200
|
+
if (!initArgsSize) {
|
|
201
|
+
done();
|
|
202
|
+
}
|
|
262
203
|
};
|
|
263
204
|
const cyclesMark = performance.now();
|
|
264
205
|
|
|
@@ -292,14 +233,7 @@ export async function start(input) {
|
|
|
292
233
|
});
|
|
293
234
|
buckets.sort((a, b) => a[1] - b[1]);
|
|
294
235
|
|
|
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];
|
|
236
|
+
const percentile = (p) => timings[Math.trunc((p * timings.length) / 100)];
|
|
303
237
|
const mode = buckets[buckets.length - 1][0];
|
|
304
238
|
|
|
305
239
|
send({
|
|
@@ -310,11 +244,19 @@ export async function start(input) {
|
|
|
310
244
|
max,
|
|
311
245
|
sum,
|
|
312
246
|
avg,
|
|
313
|
-
med,
|
|
314
247
|
mode,
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
248
|
+
p1: percentile(1),
|
|
249
|
+
p5: percentile(5),
|
|
250
|
+
p10: percentile(10),
|
|
251
|
+
p20: percentile(20),
|
|
252
|
+
p33: percentile(33),
|
|
253
|
+
p50: percentile(50),
|
|
254
|
+
med: percentile(50),
|
|
255
|
+
p66: percentile(66),
|
|
256
|
+
p80: percentile(80),
|
|
257
|
+
p90: percentile(90),
|
|
258
|
+
p95: percentile(95),
|
|
259
|
+
p99: percentile(99),
|
|
318
260
|
setup: setupMark - startMark,
|
|
319
261
|
init: initDoneMark - initMark,
|
|
320
262
|
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.4",
|
|
4
4
|
"description": "NodeJS performance benchmark",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"types": "index.d.ts",
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
"overtake": "cli.js"
|
|
10
10
|
},
|
|
11
11
|
"scripts": {
|
|
12
|
-
"start": "
|
|
12
|
+
"start": "./cli.js",
|
|
13
13
|
"test": "yarn node --experimental-vm-modules $(yarn bin jest) --detectOpenHandles",
|
|
14
14
|
"lint": "eslint .",
|
|
15
15
|
"prepare": "husky install"
|
|
@@ -39,7 +39,8 @@
|
|
|
39
39
|
"pretty-quick": "^3.1.3"
|
|
40
40
|
},
|
|
41
41
|
"dependencies": {
|
|
42
|
-
"
|
|
42
|
+
"commander": "^9.2.0",
|
|
43
|
+
"conode": "^0.1.0",
|
|
43
44
|
"glob": "^8.0.1"
|
|
44
45
|
}
|
|
45
46
|
}
|
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
|
-
}
|