overtake 1.0.0-rc.0 → 1.0.0-rc.3
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 -3
- package/build/cli.cjs +8 -8
- package/build/cli.cjs.map +1 -1
- package/build/cli.js +2 -2
- package/build/cli.js.map +1 -1
- package/build/executor.cjs.map +1 -1
- package/build/executor.js.map +1 -1
- package/build/index.cjs +228 -11
- package/build/index.cjs.map +1 -1
- package/build/index.d.ts +65 -3
- package/build/index.js +187 -1
- package/build/index.js.map +1 -1
- package/build/queue.cjs.map +1 -1
- package/build/queue.js.map +1 -1
- package/build/reporter.cjs +1 -1
- package/build/reporter.cjs.map +1 -1
- package/build/reporter.js +1 -1
- package/build/reporter.js.map +1 -1
- package/build/runner.cjs.map +1 -1
- package/build/runner.js.map +1 -1
- package/build/types.cjs.map +1 -1
- package/build/types.js.map +1 -1
- package/build/utils.cjs +2 -2
- package/build/utils.cjs.map +1 -1
- package/build/utils.js +2 -2
- package/build/utils.js.map +1 -1
- package/examples/array-copy.ts +17 -0
- package/package.json +3 -3
- package/src/cli.ts +2 -2
- package/src/index.ts +232 -3
- package/src/reporter.ts +1 -1
- package/build/__tests__/runner.d.ts +0 -1
- package/build/benchmark.cjs +0 -237
- package/build/benchmark.cjs.map +0 -1
- package/build/benchmark.d.ts +0 -64
- package/build/benchmark.js +0 -189
- package/build/benchmark.js.map +0 -1
- package/overtakes/array-copy.md +0 -80
- package/overtakes/array-delete-element.md +0 -44
- package/overtakes/async.md +0 -25
- package/overtakes/class-vs-function.md +0 -31
- package/overtakes/postgres-vs-mongo.md +0 -55
- package/src/__tests__/runner.ts +0 -34
- package/src/benchmark.ts +0 -231
package/src/benchmark.ts
DELETED
|
@@ -1,231 +0,0 @@
|
|
|
1
|
-
import { cpus } from 'node:os';
|
|
2
|
-
import { createExecutor, ExecutorOptions, ExecutorReport } from './executor.js';
|
|
3
|
-
import { MaybePromise, StepFn, SetupFn, TeardownFn, FeedFn, ReportType, ReportTypeList, DEFAULT_CYCLES } from './types.js';
|
|
4
|
-
|
|
5
|
-
export const DEFAULT_WORKERS = cpus().length;
|
|
6
|
-
|
|
7
|
-
export const AsyncFunction = (async () => {}).constructor;
|
|
8
|
-
|
|
9
|
-
export interface TargetReport<R extends ReportTypeList> {
|
|
10
|
-
target: string;
|
|
11
|
-
measures: MeasureReport<R>[];
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
export interface MeasureReport<R extends ReportTypeList> {
|
|
15
|
-
measure: string;
|
|
16
|
-
feeds: FeedReport<R>[];
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export interface FeedReport<R extends ReportTypeList> {
|
|
20
|
-
feed: string;
|
|
21
|
-
data: ExecutorReport<R>;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
export const DEFAULT_REPORT_TYPES = ['ops'] as const;
|
|
25
|
-
export type DefaultReportTypes = (typeof DEFAULT_REPORT_TYPES)[number];
|
|
26
|
-
|
|
27
|
-
export class MeasureContext<TContext, TInput> {
|
|
28
|
-
public pre?: StepFn<TContext, TInput>;
|
|
29
|
-
public post?: StepFn<TContext, TInput>;
|
|
30
|
-
|
|
31
|
-
constructor(
|
|
32
|
-
public title: string,
|
|
33
|
-
public run: StepFn<TContext, TInput>,
|
|
34
|
-
) {}
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
export class Measure<TContext, TInput> {
|
|
38
|
-
#ctx: MeasureContext<TContext, TInput>;
|
|
39
|
-
|
|
40
|
-
constructor(ctx: MeasureContext<TContext, TInput>) {
|
|
41
|
-
this.#ctx = ctx;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
pre(fn: StepFn<TContext, TInput>): Measure<TContext, TInput> {
|
|
45
|
-
this.#ctx.pre = fn;
|
|
46
|
-
return this;
|
|
47
|
-
}
|
|
48
|
-
post(fn: StepFn<TContext, TInput>): Measure<TContext, TInput> {
|
|
49
|
-
this.#ctx.post = fn;
|
|
50
|
-
return this;
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
export class TargetContext<TContext, TInput> {
|
|
55
|
-
public teardown?: TeardownFn<TContext>;
|
|
56
|
-
public measures: MeasureContext<TContext, TInput>[] = [];
|
|
57
|
-
|
|
58
|
-
constructor(
|
|
59
|
-
readonly title: string,
|
|
60
|
-
readonly setup?: SetupFn<MaybePromise<TContext>>,
|
|
61
|
-
) {}
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
export class Target<TContext, TInput> {
|
|
65
|
-
#ctx: TargetContext<TContext, TInput>;
|
|
66
|
-
|
|
67
|
-
constructor(ctx: TargetContext<TContext, TInput>) {
|
|
68
|
-
this.#ctx = ctx;
|
|
69
|
-
}
|
|
70
|
-
teardown(fn: TeardownFn<TContext>): Target<TContext, TInput> {
|
|
71
|
-
this.#ctx.teardown = fn;
|
|
72
|
-
|
|
73
|
-
return this;
|
|
74
|
-
}
|
|
75
|
-
measure(title: string, run: StepFn<TContext, TInput>): Measure<TContext, TInput> {
|
|
76
|
-
const measure = new MeasureContext(title, run);
|
|
77
|
-
this.#ctx.measures.push(measure);
|
|
78
|
-
|
|
79
|
-
return new Measure(measure);
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
export class FeedContext<TInput> {
|
|
84
|
-
constructor(
|
|
85
|
-
readonly title: string,
|
|
86
|
-
readonly fn?: FeedFn<TInput>,
|
|
87
|
-
) {}
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
export class Benchmark<TInput> {
|
|
91
|
-
#targets: TargetContext<unknown, TInput>[] = [];
|
|
92
|
-
#feeds: FeedContext<TInput>[] = [];
|
|
93
|
-
#executed = false;
|
|
94
|
-
|
|
95
|
-
static create(title: string): Benchmark<void>;
|
|
96
|
-
static create<I>(title: string, fn: FeedFn<I>): Benchmark<I>;
|
|
97
|
-
static create<I>(title: string, fn?: FeedFn<I> | undefined): Benchmark<I> {
|
|
98
|
-
if (fn) {
|
|
99
|
-
return new Benchmark(title, fn);
|
|
100
|
-
} else {
|
|
101
|
-
return new Benchmark(title);
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
constructor(title: string);
|
|
106
|
-
constructor(title: string, fn: FeedFn<TInput>);
|
|
107
|
-
constructor(title: string, fn?: FeedFn<TInput> | undefined) {
|
|
108
|
-
if (fn) {
|
|
109
|
-
this.feed(title, fn);
|
|
110
|
-
} else {
|
|
111
|
-
this.feed(title);
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
feed(title: string): Benchmark<TInput | void>;
|
|
116
|
-
feed<I>(title: string, fn: FeedFn<I>): Benchmark<TInput | I>;
|
|
117
|
-
feed<I>(title: string, fn?: FeedFn<I> | undefined): Benchmark<TInput | I> {
|
|
118
|
-
const self = this as Benchmark<TInput | I>;
|
|
119
|
-
self.#feeds.push(fn ? new FeedContext(title, fn) : new FeedContext(title));
|
|
120
|
-
|
|
121
|
-
return self;
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
target<TContext>(title: string): Target<void, TInput>;
|
|
125
|
-
target<TContext>(title: string, setup: SetupFn<Awaited<TContext>>): Target<TContext, TInput>;
|
|
126
|
-
target<TContext>(title: string, setup?: SetupFn<Awaited<TContext>> | undefined): Target<TContext, TInput> {
|
|
127
|
-
const target = new TargetContext<TContext, TInput>(title, setup);
|
|
128
|
-
this.#targets.push(target as TargetContext<unknown, TInput>);
|
|
129
|
-
|
|
130
|
-
return new Target<TContext, TInput>(target);
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
async execute<R extends readonly ReportType[] = typeof DEFAULT_REPORT_TYPES>({
|
|
134
|
-
workers = DEFAULT_WORKERS,
|
|
135
|
-
warmupCycles = 20,
|
|
136
|
-
maxCycles = DEFAULT_CYCLES,
|
|
137
|
-
minCycles = 50,
|
|
138
|
-
absThreshold = 1_000,
|
|
139
|
-
relThreshold = 0.02,
|
|
140
|
-
reportTypes = DEFAULT_REPORT_TYPES as unknown as R,
|
|
141
|
-
}: ExecutorOptions<R>): Promise<TargetReport<R>[]> {
|
|
142
|
-
if (this.#executed) {
|
|
143
|
-
throw new Error("Benchmark is executed and can't be reused");
|
|
144
|
-
}
|
|
145
|
-
this.#executed = true;
|
|
146
|
-
|
|
147
|
-
const executor = createExecutor<unknown, TInput, R>({
|
|
148
|
-
workers,
|
|
149
|
-
warmupCycles,
|
|
150
|
-
maxCycles,
|
|
151
|
-
minCycles,
|
|
152
|
-
absThreshold,
|
|
153
|
-
relThreshold,
|
|
154
|
-
reportTypes,
|
|
155
|
-
});
|
|
156
|
-
|
|
157
|
-
const reports: TargetReport<R>[] = [];
|
|
158
|
-
for (const target of this.#targets) {
|
|
159
|
-
const targetReport: TargetReport<R> = { target: target.title, measures: [] };
|
|
160
|
-
for (const measure of target.measures) {
|
|
161
|
-
const measureReport: MeasureReport<R> = { measure: measure.title, feeds: [] };
|
|
162
|
-
for (const feed of this.#feeds) {
|
|
163
|
-
const data = await feed.fn?.();
|
|
164
|
-
executor
|
|
165
|
-
.push<ExecutorReport<R>>({
|
|
166
|
-
setup: target.setup,
|
|
167
|
-
teardown: target.teardown,
|
|
168
|
-
pre: measure.pre,
|
|
169
|
-
run: measure.run,
|
|
170
|
-
post: measure.post,
|
|
171
|
-
data,
|
|
172
|
-
})
|
|
173
|
-
.then((data) => {
|
|
174
|
-
measureReport.feeds.push({
|
|
175
|
-
feed: feed.title,
|
|
176
|
-
data,
|
|
177
|
-
});
|
|
178
|
-
});
|
|
179
|
-
}
|
|
180
|
-
targetReport.measures.push(measureReport);
|
|
181
|
-
}
|
|
182
|
-
reports.push(targetReport);
|
|
183
|
-
}
|
|
184
|
-
await executor.drain();
|
|
185
|
-
executor.kill();
|
|
186
|
-
|
|
187
|
-
return reports;
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
export const printSimpleReports = <R extends ReportTypeList>(reports: TargetReport<R>[]) => {
|
|
192
|
-
for (const report of reports) {
|
|
193
|
-
for (const { measure, feeds } of report.measures) {
|
|
194
|
-
console.group('\n', report.target, measure);
|
|
195
|
-
for (const { feed, data } of feeds) {
|
|
196
|
-
const output = Object.entries(data)
|
|
197
|
-
.map(([key, report]) => `${key}: ${report.toString()}`)
|
|
198
|
-
.join('; ');
|
|
199
|
-
console.log(feed, output);
|
|
200
|
-
}
|
|
201
|
-
console.groupEnd();
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
};
|
|
205
|
-
|
|
206
|
-
export const printTableReports = <R extends ReportTypeList>(reports: TargetReport<R>[]) => {
|
|
207
|
-
for (const report of reports) {
|
|
208
|
-
for (const { measure, feeds } of report.measures) {
|
|
209
|
-
console.log('\n', report.target, measure);
|
|
210
|
-
const table: Record<string, unknown> = {};
|
|
211
|
-
for (const { feed, data } of feeds) {
|
|
212
|
-
table[feed] = Object.fromEntries(Object.entries(data).map(([key, report]) => [key, report.toString()]));
|
|
213
|
-
}
|
|
214
|
-
console.table(table);
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
};
|
|
218
|
-
|
|
219
|
-
export const printJSONReports = <R extends ReportTypeList>(reports: TargetReport<R>[], padding?: number) => {
|
|
220
|
-
const output = {} as Record<string, Record<string, Record<string, string>>>;
|
|
221
|
-
for (const report of reports) {
|
|
222
|
-
for (const { measure, feeds } of report.measures) {
|
|
223
|
-
const row = {} as Record<string, Record<string, string>>;
|
|
224
|
-
for (const { feed, data } of feeds) {
|
|
225
|
-
row[feed] = Object.fromEntries(Object.entries(data).map(([key, report]) => [key, report.toString()]));
|
|
226
|
-
}
|
|
227
|
-
output[`${report.target} ${measure}`] = row;
|
|
228
|
-
}
|
|
229
|
-
}
|
|
230
|
-
console.log(JSON.stringify(output, null, padding));
|
|
231
|
-
};
|