@effect-bench/core 0.0.0-stage → 0.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/dist/src/Bench.d.ts +82 -0
- package/dist/src/Bench.d.ts.map +1 -0
- package/dist/src/Bench.js +36 -0
- package/dist/src/Bench.js.map +1 -0
- package/dist/src/BenchResult.d.ts +280 -0
- package/dist/src/BenchResult.d.ts.map +1 -0
- package/dist/src/BenchResult.js +107 -0
- package/dist/src/BenchResult.js.map +1 -0
- package/dist/src/Compare.d.ts +22 -0
- package/dist/src/Compare.d.ts.map +1 -0
- package/dist/src/Compare.js +75 -0
- package/dist/src/Compare.js.map +1 -0
- package/dist/src/Measure.d.ts +27 -0
- package/dist/src/Measure.d.ts.map +1 -0
- package/dist/src/Measure.js +68 -0
- package/dist/src/Measure.js.map +1 -0
- package/dist/src/Reporter.d.ts +5 -0
- package/dist/src/Reporter.d.ts.map +1 -0
- package/dist/src/Reporter.js +50 -0
- package/dist/src/Reporter.js.map +1 -0
- package/dist/src/Runner.d.ts +238 -0
- package/dist/src/Runner.d.ts.map +1 -0
- package/dist/src/Runner.js +220 -0
- package/dist/src/Runner.js.map +1 -0
- package/dist/src/Services.d.ts +37 -0
- package/dist/src/Services.d.ts.map +1 -0
- package/dist/src/Services.js +37 -0
- package/dist/src/Services.js.map +1 -0
- package/dist/src/Stats.d.ts +7 -0
- package/dist/src/Stats.d.ts.map +1 -0
- package/dist/src/Stats.js +46 -0
- package/dist/src/Stats.js.map +1 -0
- package/dist/src/index.d.ts +9 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +9 -0
- package/dist/src/index.js.map +1 -0
- package/package.json +22 -3
- package/src/Bench.ts +169 -0
- package/src/BenchResult.ts +136 -0
- package/src/Compare.ts +113 -0
- package/src/Measure.ts +96 -0
- package/src/Reporter.ts +57 -0
- package/src/Runner.ts +325 -0
- package/src/Services.ts +70 -0
- package/src/Stats.ts +52 -0
- package/src/index.ts +8 -0
- package/README.md +0 -3
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import type { Duration, Scope } from 'effect';
|
|
2
|
+
import { Effect, Layer } from 'effect';
|
|
3
|
+
export type ParamValue = string | number | boolean;
|
|
4
|
+
export type Params = Readonly<Record<string, ParamValue>>;
|
|
5
|
+
export interface Budget {
|
|
6
|
+
readonly p50?: Duration.Input;
|
|
7
|
+
readonly p99?: Duration.Input;
|
|
8
|
+
}
|
|
9
|
+
export interface Options {
|
|
10
|
+
/** Minimum number of samples to collect. */
|
|
11
|
+
readonly samples?: number;
|
|
12
|
+
/** Keep sampling until at least this much time has passed. */
|
|
13
|
+
readonly minTime?: Duration.Input;
|
|
14
|
+
readonly warmup?: Duration.Input;
|
|
15
|
+
/** Force a GC before every sample and record the heap delta. Needs `--expose-gc`. */
|
|
16
|
+
readonly memory?: boolean;
|
|
17
|
+
readonly budget?: Budget;
|
|
18
|
+
readonly tags?: ReadonlyArray<string>;
|
|
19
|
+
}
|
|
20
|
+
export type Operation = {
|
|
21
|
+
readonly _tag: 'Sync';
|
|
22
|
+
readonly run: () => unknown;
|
|
23
|
+
} | {
|
|
24
|
+
readonly _tag: 'Effect';
|
|
25
|
+
readonly run: Effect.Effect<unknown, unknown>;
|
|
26
|
+
};
|
|
27
|
+
export interface Bench<in Ctx = any, out R = any> {
|
|
28
|
+
readonly _tag: 'Bench';
|
|
29
|
+
readonly name: string;
|
|
30
|
+
readonly params: Params;
|
|
31
|
+
readonly group: {
|
|
32
|
+
readonly name: string;
|
|
33
|
+
readonly baseline: string;
|
|
34
|
+
} | undefined;
|
|
35
|
+
readonly options: Options;
|
|
36
|
+
readonly check: ((value: unknown) => boolean) | undefined;
|
|
37
|
+
readonly prepare: (ctx: Ctx) => Effect.Effect<Operation, unknown, R>;
|
|
38
|
+
}
|
|
39
|
+
/** Type relations between layer, setup and benches are enforced by `suite`; the runner only needs the erased shape. */
|
|
40
|
+
export interface Suite {
|
|
41
|
+
readonly _tag: 'Suite';
|
|
42
|
+
readonly name: string;
|
|
43
|
+
readonly layer: Layer.Layer<never, unknown>;
|
|
44
|
+
readonly setup: Effect.Effect<unknown, unknown, any>;
|
|
45
|
+
readonly options: Options;
|
|
46
|
+
readonly benches: ReadonlyArray<Bench>;
|
|
47
|
+
}
|
|
48
|
+
export interface SuiteOptions<Ctx, ROut> extends Options {
|
|
49
|
+
readonly layer?: Layer.Layer<ROut, unknown>;
|
|
50
|
+
readonly setup?: Effect.Effect<Ctx, unknown, ROut | Scope.Scope>;
|
|
51
|
+
}
|
|
52
|
+
type Entry<Ctx, R> = Bench<Ctx, R> | ReadonlyArray<Bench<Ctx, R>>;
|
|
53
|
+
export declare const suite: <Ctx = undefined, ROut = never>(name: string, options?: SuiteOptions<Ctx, ROut>) => (...entries: ReadonlyArray<Entry<Ctx, ROut>>) => Suite;
|
|
54
|
+
type BenchOptions<A> = Options & {
|
|
55
|
+
readonly check?: (value: A) => boolean;
|
|
56
|
+
};
|
|
57
|
+
/**
|
|
58
|
+
* An Effect value is re-run as is; a function is called for every operation, so building the Effect is measured too.
|
|
59
|
+
*/
|
|
60
|
+
export declare const make: <Ctx = unknown, A = unknown, E = never, R = never>(name: string, run: Effect.Effect<A, E, R> | ((ctx: Ctx) => Effect.Effect<A, E, R>), options?: BenchOptions<A>) => Bench<Ctx, R>;
|
|
61
|
+
export declare const sync: <Ctx = unknown, A = unknown>(name: string, run: (ctx: Ctx) => A, options?: BenchOptions<A>) => Bench<Ctx, never>;
|
|
62
|
+
type Matrix = Readonly<Record<string, ReadonlyArray<ParamValue>>>;
|
|
63
|
+
export type ParamsOf<M extends Matrix> = {
|
|
64
|
+
readonly [K in keyof M]: M[K][number];
|
|
65
|
+
};
|
|
66
|
+
interface ParamsPrepare<M extends Matrix, Ctx, I, R> {
|
|
67
|
+
readonly prepare?: (params: ParamsOf<M>, ctx: Ctx) => Effect.Effect<I, unknown, R>;
|
|
68
|
+
}
|
|
69
|
+
export declare const params: {
|
|
70
|
+
<const M extends Matrix, Ctx = unknown, I = ParamsOf<M>, A = unknown, E = never, R = never>(name: string, matrix: M, spec: ParamsPrepare<M, Ctx, I, R> & BenchOptions<A> & {
|
|
71
|
+
readonly run: (input: I, ctx: Ctx) => Effect.Effect<A, E, R>;
|
|
72
|
+
}): ReadonlyArray<Bench<Ctx, R>>;
|
|
73
|
+
<const M extends Matrix, Ctx = unknown, I = ParamsOf<M>, A = unknown, R = never>(name: string, matrix: M, spec: ParamsPrepare<M, Ctx, I, R> & BenchOptions<A> & {
|
|
74
|
+
readonly sync: (input: I, ctx: Ctx) => A;
|
|
75
|
+
}): ReadonlyArray<Bench<Ctx, R>>;
|
|
76
|
+
};
|
|
77
|
+
export declare const group: (name: string, options: {
|
|
78
|
+
readonly baseline: string;
|
|
79
|
+
}) => <Ctx, R>(...entries: ReadonlyArray<Entry<Ctx, R>>) => ReadonlyArray<Bench<Ctx, R>>;
|
|
80
|
+
export declare const benchId: (suiteName: string, bench: Pick<Bench, 'name' | 'params' | 'group'>) => string;
|
|
81
|
+
export {};
|
|
82
|
+
//# sourceMappingURL=Bench.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Bench.d.ts","sourceRoot":"","sources":["../../src/Bench.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,QAAQ,CAAA;AAC7C,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,QAAQ,CAAA;AAEtC,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAA;AAElD,MAAM,MAAM,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC,CAAA;AAEzD,MAAM,WAAW,MAAM;IACrB,QAAQ,CAAC,GAAG,CAAC,EAAE,QAAQ,CAAC,KAAK,CAAA;IAC7B,QAAQ,CAAC,GAAG,CAAC,EAAE,QAAQ,CAAC,KAAK,CAAA;CAC9B;AAED,MAAM,WAAW,OAAO;IACtB,4CAA4C;IAC5C,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAA;IACzB,8DAA8D;IAC9D,QAAQ,CAAC,OAAO,CAAC,EAAE,QAAQ,CAAC,KAAK,CAAA;IACjC,QAAQ,CAAC,MAAM,CAAC,EAAE,QAAQ,CAAC,KAAK,CAAA;IAChC,qFAAqF;IACrF,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,CAAA;IACzB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,IAAI,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,CAAA;CACtC;AAED,MAAM,MAAM,SAAS,GACjB;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,GAAG,EAAE,MAAM,OAAO,CAAA;CAAE,GACtD;IAAE,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IAAC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,OAAO,CAAC,CAAA;CAAE,CAAA;AAE9E,MAAM,WAAW,KAAK,CAAC,EAAE,CAAC,GAAG,GAAG,GAAG,EAAE,GAAG,CAAC,CAAC,GAAG,GAAG;IAC9C,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAA;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,KAAK,EAAE;QAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,GAAG,SAAS,CAAA;IAChF,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;IACzB,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,OAAO,KAAK,OAAO,CAAC,GAAG,SAAS,CAAA;IACzD,QAAQ,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,MAAM,CAAC,MAAM,CAAC,SAAS,EAAE,OAAO,EAAE,CAAC,CAAC,CAAA;CACrE;AAED,uHAAuH;AACvH,MAAM,WAAW,KAAK;IACpB,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAA;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,KAAK,EAAE,OAAO,CAAC,CAAA;IAC3C,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,CAAC,CAAA;IACpD,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;IACzB,QAAQ,CAAC,OAAO,EAAE,aAAa,CAAC,KAAK,CAAC,CAAA;CACvC;AAED,MAAM,WAAW,YAAY,CAAC,GAAG,EAAE,IAAI,CAAE,SAAQ,OAAO;IACtD,QAAQ,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC,KAAK,CAAC,IAAI,EAAE,OAAO,CAAC,CAAA;IAC3C,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE,OAAO,EAAE,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,CAAA;CACjE;AAED,KAAK,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,GAAG,aAAa,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAA;AAEjE,eAAO,MAAM,KAAK,GACf,GAAG,GAAG,SAAS,EAAE,IAAI,GAAG,KAAK,QAAQ,MAAM,YAAW,YAAY,CAAC,GAAG,EAAE,IAAI,CAAC,kBACjE,aAAa,CAAC,KAAK,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC,KAAG,KAU9C,CAAA;AAEH,KAAK,YAAY,CAAC,CAAC,IAAI,OAAO,GAAG;IAAE,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,OAAO,CAAA;CAAE,CAAA;AAS3E;;GAEG;AACH,eAAO,MAAM,IAAI,GAAI,GAAG,GAAG,OAAO,EAAE,CAAC,GAAG,OAAO,EAAE,CAAC,GAAG,KAAK,EAAE,CAAC,GAAG,KAAK,QAC7D,MAAM,OACP,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,GAAG,KAAK,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,YAC3D,YAAY,CAAC,CAAC,CAAC,KACvB,KAAK,CAAC,GAAG,EAAE,CAAC,CASZ,CAAA;AAEH,eAAO,MAAM,IAAI,GAAI,GAAG,GAAG,OAAO,EAAE,CAAC,GAAG,OAAO,QACvC,MAAM,OACP,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,YACX,YAAY,CAAC,CAAC,CAAC,KACvB,KAAK,CAAC,GAAG,EAAE,KAAK,CAA2F,CAAA;AAE9G,KAAK,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,UAAU,CAAC,CAAC,CAAC,CAAA;AAEjE,MAAM,MAAM,QAAQ,CAAC,CAAC,SAAS,MAAM,IAAI;IAAE,QAAQ,EAAE,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;CAAE,CAAA;AAQlF,UAAU,aAAa,CAAC,CAAC,SAAS,MAAM,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC;IACjD,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,GAAG,KAAK,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,CAAA;CACnF;AAED,eAAO,MAAM,MAAM,EAAE;IACnB,CAAC,KAAK,CAAC,CAAC,SAAS,MAAM,EAAE,GAAG,GAAG,OAAO,EAAE,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,GAAG,OAAO,EAAE,CAAC,GAAG,KAAK,EAAE,CAAC,GAAG,KAAK,EACxF,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,CAAC,EACT,IAAI,EAAE,aAAa,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC,GAC/B,YAAY,CAAC,CAAC,CAAC,GAAG;QAAE,QAAQ,CAAC,GAAG,EAAE,CAAC,KAAK,EAAE,CAAC,EAAE,GAAG,EAAE,GAAG,KAAK,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAA;KAAE,GACnF,aAAa,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAA;IAC/B,CAAC,KAAK,CAAC,CAAC,SAAS,MAAM,EAAE,GAAG,GAAG,OAAO,EAAE,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,GAAG,OAAO,EAAE,CAAC,GAAG,KAAK,EAC7E,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,CAAC,EACT,IAAI,EAAE,aAAa,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC,GAAG,YAAY,CAAC,CAAC,CAAC,GAAG;QAAE,QAAQ,CAAC,IAAI,EAAE,CAAC,KAAK,EAAE,CAAC,EAAE,GAAG,EAAE,GAAG,KAAK,CAAC,CAAA;KAAE,GACjG,aAAa,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAA;CA4B9B,CAAA;AAEH,eAAO,MAAM,KAAK,SACT,MAAM,WAAW;IAAE,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,MACpD,GAAG,EAAE,CAAC,cAAc,aAAa,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,KAAG,aAAa,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,CACW,CAAA;AAO5F,eAAO,MAAM,OAAO,cAAe,MAAM,SAAS,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,QAAQ,GAAG,OAAO,CAAC,KAAG,MACW,CAAA"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { Effect, Layer } from 'effect';
|
|
2
|
+
export const suite = (name, options = {}) => (...entries) => {
|
|
3
|
+
const { layer, setup, ...defaults } = options;
|
|
4
|
+
return {
|
|
5
|
+
_tag: 'Suite',
|
|
6
|
+
name,
|
|
7
|
+
layer: layer ?? Layer.empty,
|
|
8
|
+
setup: setup ?? Effect.undefined,
|
|
9
|
+
options: defaults,
|
|
10
|
+
benches: entries.flat(),
|
|
11
|
+
};
|
|
12
|
+
};
|
|
13
|
+
const makeBench = (name, prepare, { check, ...options }, params = {}) => ({ _tag: 'Bench', name, params, group: undefined, options, check, prepare });
|
|
14
|
+
/**
|
|
15
|
+
* An Effect value is re-run as is; a function is called for every operation, so building the Effect is measured too.
|
|
16
|
+
*/
|
|
17
|
+
export const make = (name, run, options = {}) => makeBench(name, ctx => Effect.map(Effect.context(), context => ({
|
|
18
|
+
_tag: 'Effect',
|
|
19
|
+
run: Effect.provideContext(Effect.isEffect(run) ? run : Effect.suspend(() => run(ctx)), context),
|
|
20
|
+
})), options);
|
|
21
|
+
export const sync = (name, run, options = {}) => makeBench(name, ctx => Effect.succeed({ _tag: 'Sync', run: () => run(ctx) }), options);
|
|
22
|
+
const combinations = (matrix) => Object.entries(matrix).reduce((acc, [key, values]) => acc.flatMap(combo => values.map(value => ({ ...combo, [key]: value }))), [{}]);
|
|
23
|
+
export const params = (name, matrix, { prepare, run, sync: runSync, ...options }) => combinations(matrix).map(combo => makeBench(name, ctx => Effect.gen(function* () {
|
|
24
|
+
const input = prepare === undefined ? combo : yield* prepare(combo, ctx);
|
|
25
|
+
if (runSync !== undefined)
|
|
26
|
+
return { _tag: 'Sync', run: () => runSync(input, ctx) };
|
|
27
|
+
const context = yield* Effect.context();
|
|
28
|
+
return { _tag: 'Effect', run: Effect.provideContext(run(input, ctx), context) };
|
|
29
|
+
}), options, combo));
|
|
30
|
+
export const group = (name, options) => (...entries) => entries.flat().map(bench => ({ ...bench, group: { name, baseline: options.baseline } }));
|
|
31
|
+
const paramsSuffix = (params) => {
|
|
32
|
+
const entries = Object.entries(params);
|
|
33
|
+
return entries.length === 0 ? '' : `[${entries.map(([key, value]) => `${key}=${value}`).join(',')}]`;
|
|
34
|
+
};
|
|
35
|
+
export const benchId = (suiteName, bench) => [suiteName, bench.group?.name, `${bench.name}${paramsSuffix(bench.params)}`].filter(Boolean).join('/');
|
|
36
|
+
//# sourceMappingURL=Bench.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Bench.js","sourceRoot":"","sources":["../../src/Bench.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,280 @@
|
|
|
1
|
+
import { Schema } from 'effect';
|
|
2
|
+
export declare const schemaVersion = 2;
|
|
3
|
+
export declare const Stats: Schema.Struct<{
|
|
4
|
+
readonly samples: Schema.Number;
|
|
5
|
+
readonly outliers: Schema.Number;
|
|
6
|
+
readonly meanNs: Schema.Number;
|
|
7
|
+
readonly medianNs: Schema.Number;
|
|
8
|
+
readonly p75Ns: Schema.Number;
|
|
9
|
+
readonly p99Ns: Schema.Number;
|
|
10
|
+
readonly minNs: Schema.Number;
|
|
11
|
+
readonly maxNs: Schema.Number;
|
|
12
|
+
readonly madNs: Schema.Number;
|
|
13
|
+
readonly rme: Schema.Number;
|
|
14
|
+
/** Null when the median is below what the clock can resolve. */
|
|
15
|
+
readonly opsPerSec: Schema.NullOr<Schema.Number>;
|
|
16
|
+
}>;
|
|
17
|
+
export type Stats = typeof Stats.Type;
|
|
18
|
+
export declare const Environment: Schema.Struct<{
|
|
19
|
+
readonly runtime: Schema.String;
|
|
20
|
+
readonly runtimeVersion: Schema.String;
|
|
21
|
+
readonly platform: Schema.String;
|
|
22
|
+
readonly arch: Schema.String;
|
|
23
|
+
readonly cpu: Schema.String;
|
|
24
|
+
readonly cpus: Schema.Number;
|
|
25
|
+
readonly gitSha: Schema.NullOr<Schema.String>;
|
|
26
|
+
readonly gitDirty: Schema.NullOr<Schema.Boolean>;
|
|
27
|
+
}>;
|
|
28
|
+
export type Environment = typeof Environment.Type;
|
|
29
|
+
export declare const Verdict: Schema.Literals<readonly ["faster", "slower", "same", "inconclusive"]>;
|
|
30
|
+
export type Verdict = typeof Verdict.Type;
|
|
31
|
+
export declare const Comparison: Schema.Struct<{
|
|
32
|
+
readonly baseline: Schema.String;
|
|
33
|
+
readonly baselineMedianNs: Schema.Number;
|
|
34
|
+
readonly change: Schema.Number;
|
|
35
|
+
readonly ci: Schema.Tuple<readonly [Schema.Number, Schema.Number]>;
|
|
36
|
+
readonly verdict: Schema.Literals<readonly ["faster", "slower", "same", "inconclusive"]>;
|
|
37
|
+
/** The baseline was recorded on a different runtime or machine. */
|
|
38
|
+
readonly stale: Schema.Boolean;
|
|
39
|
+
}>;
|
|
40
|
+
export type Comparison = typeof Comparison.Type;
|
|
41
|
+
export declare const BudgetCheck: Schema.Struct<{
|
|
42
|
+
readonly status: Schema.Literals<readonly ["ok", "exceeded"]>;
|
|
43
|
+
readonly violations: Schema.$Array<Schema.String>;
|
|
44
|
+
}>;
|
|
45
|
+
export type BudgetCheck = typeof BudgetCheck.Type;
|
|
46
|
+
export declare const Relative: Schema.Struct<{
|
|
47
|
+
readonly baselineId: Schema.String;
|
|
48
|
+
readonly ratio: Schema.Number;
|
|
49
|
+
}>;
|
|
50
|
+
export type Relative = typeof Relative.Type;
|
|
51
|
+
export declare const OkResult: Schema.Struct<{
|
|
52
|
+
readonly id: Schema.String;
|
|
53
|
+
readonly suite: Schema.String;
|
|
54
|
+
readonly name: Schema.String;
|
|
55
|
+
readonly group: Schema.NullOr<Schema.String>;
|
|
56
|
+
readonly params: Schema.$Record<Schema.String, Schema.Union<readonly [Schema.String, Schema.Number, Schema.Boolean]>>;
|
|
57
|
+
readonly tags: Schema.$Array<Schema.String>;
|
|
58
|
+
readonly status: Schema.Literal<"ok">;
|
|
59
|
+
readonly stats: Schema.Struct<{
|
|
60
|
+
readonly samples: Schema.Number;
|
|
61
|
+
readonly outliers: Schema.Number;
|
|
62
|
+
readonly meanNs: Schema.Number;
|
|
63
|
+
readonly medianNs: Schema.Number;
|
|
64
|
+
readonly p75Ns: Schema.Number;
|
|
65
|
+
readonly p99Ns: Schema.Number;
|
|
66
|
+
readonly minNs: Schema.Number;
|
|
67
|
+
readonly maxNs: Schema.Number;
|
|
68
|
+
readonly madNs: Schema.Number;
|
|
69
|
+
readonly rme: Schema.Number;
|
|
70
|
+
/** Null when the median is below what the clock can resolve. */
|
|
71
|
+
readonly opsPerSec: Schema.NullOr<Schema.Number>;
|
|
72
|
+
}>;
|
|
73
|
+
/** Fresh processes the samples came from; comparisons resample across them. */
|
|
74
|
+
readonly forks: Schema.Number;
|
|
75
|
+
readonly batchSize: Schema.Number;
|
|
76
|
+
readonly overheadNs: Schema.Number;
|
|
77
|
+
readonly heapDeltaBytes: Schema.NullOr<Schema.Number>;
|
|
78
|
+
readonly budget: Schema.NullOr<Schema.Struct<{
|
|
79
|
+
readonly status: Schema.Literals<readonly ["ok", "exceeded"]>;
|
|
80
|
+
readonly violations: Schema.$Array<Schema.String>;
|
|
81
|
+
}>>;
|
|
82
|
+
readonly comparison: Schema.NullOr<Schema.Struct<{
|
|
83
|
+
readonly baseline: Schema.String;
|
|
84
|
+
readonly baselineMedianNs: Schema.Number;
|
|
85
|
+
readonly change: Schema.Number;
|
|
86
|
+
readonly ci: Schema.Tuple<readonly [Schema.Number, Schema.Number]>;
|
|
87
|
+
readonly verdict: Schema.Literals<readonly ["faster", "slower", "same", "inconclusive"]>;
|
|
88
|
+
/** The baseline was recorded on a different runtime or machine. */
|
|
89
|
+
readonly stale: Schema.Boolean;
|
|
90
|
+
}>>;
|
|
91
|
+
readonly relative: Schema.NullOr<Schema.Struct<{
|
|
92
|
+
readonly baselineId: Schema.String;
|
|
93
|
+
readonly ratio: Schema.Number;
|
|
94
|
+
}>>;
|
|
95
|
+
}>;
|
|
96
|
+
export type OkResult = typeof OkResult.Type;
|
|
97
|
+
export declare const FailedResult: Schema.Struct<{
|
|
98
|
+
readonly id: Schema.String;
|
|
99
|
+
readonly suite: Schema.String;
|
|
100
|
+
readonly name: Schema.String;
|
|
101
|
+
readonly group: Schema.NullOr<Schema.String>;
|
|
102
|
+
readonly params: Schema.$Record<Schema.String, Schema.Union<readonly [Schema.String, Schema.Number, Schema.Boolean]>>;
|
|
103
|
+
readonly tags: Schema.$Array<Schema.String>;
|
|
104
|
+
readonly status: Schema.Literal<"failed">;
|
|
105
|
+
readonly phase: Schema.Literals<readonly ["setup", "prepare", "check", "run"]>;
|
|
106
|
+
readonly message: Schema.String;
|
|
107
|
+
}>;
|
|
108
|
+
export type FailedResult = typeof FailedResult.Type;
|
|
109
|
+
export declare const BenchResult: Schema.Union<readonly [Schema.Struct<{
|
|
110
|
+
readonly id: Schema.String;
|
|
111
|
+
readonly suite: Schema.String;
|
|
112
|
+
readonly name: Schema.String;
|
|
113
|
+
readonly group: Schema.NullOr<Schema.String>;
|
|
114
|
+
readonly params: Schema.$Record<Schema.String, Schema.Union<readonly [Schema.String, Schema.Number, Schema.Boolean]>>;
|
|
115
|
+
readonly tags: Schema.$Array<Schema.String>;
|
|
116
|
+
readonly status: Schema.Literal<"ok">;
|
|
117
|
+
readonly stats: Schema.Struct<{
|
|
118
|
+
readonly samples: Schema.Number;
|
|
119
|
+
readonly outliers: Schema.Number;
|
|
120
|
+
readonly meanNs: Schema.Number;
|
|
121
|
+
readonly medianNs: Schema.Number;
|
|
122
|
+
readonly p75Ns: Schema.Number;
|
|
123
|
+
readonly p99Ns: Schema.Number;
|
|
124
|
+
readonly minNs: Schema.Number;
|
|
125
|
+
readonly maxNs: Schema.Number;
|
|
126
|
+
readonly madNs: Schema.Number;
|
|
127
|
+
readonly rme: Schema.Number;
|
|
128
|
+
/** Null when the median is below what the clock can resolve. */
|
|
129
|
+
readonly opsPerSec: Schema.NullOr<Schema.Number>;
|
|
130
|
+
}>;
|
|
131
|
+
/** Fresh processes the samples came from; comparisons resample across them. */
|
|
132
|
+
readonly forks: Schema.Number;
|
|
133
|
+
readonly batchSize: Schema.Number;
|
|
134
|
+
readonly overheadNs: Schema.Number;
|
|
135
|
+
readonly heapDeltaBytes: Schema.NullOr<Schema.Number>;
|
|
136
|
+
readonly budget: Schema.NullOr<Schema.Struct<{
|
|
137
|
+
readonly status: Schema.Literals<readonly ["ok", "exceeded"]>;
|
|
138
|
+
readonly violations: Schema.$Array<Schema.String>;
|
|
139
|
+
}>>;
|
|
140
|
+
readonly comparison: Schema.NullOr<Schema.Struct<{
|
|
141
|
+
readonly baseline: Schema.String;
|
|
142
|
+
readonly baselineMedianNs: Schema.Number;
|
|
143
|
+
readonly change: Schema.Number;
|
|
144
|
+
readonly ci: Schema.Tuple<readonly [Schema.Number, Schema.Number]>;
|
|
145
|
+
readonly verdict: Schema.Literals<readonly ["faster", "slower", "same", "inconclusive"]>;
|
|
146
|
+
/** The baseline was recorded on a different runtime or machine. */
|
|
147
|
+
readonly stale: Schema.Boolean;
|
|
148
|
+
}>>;
|
|
149
|
+
readonly relative: Schema.NullOr<Schema.Struct<{
|
|
150
|
+
readonly baselineId: Schema.String;
|
|
151
|
+
readonly ratio: Schema.Number;
|
|
152
|
+
}>>;
|
|
153
|
+
}>, Schema.Struct<{
|
|
154
|
+
readonly id: Schema.String;
|
|
155
|
+
readonly suite: Schema.String;
|
|
156
|
+
readonly name: Schema.String;
|
|
157
|
+
readonly group: Schema.NullOr<Schema.String>;
|
|
158
|
+
readonly params: Schema.$Record<Schema.String, Schema.Union<readonly [Schema.String, Schema.Number, Schema.Boolean]>>;
|
|
159
|
+
readonly tags: Schema.$Array<Schema.String>;
|
|
160
|
+
readonly status: Schema.Literal<"failed">;
|
|
161
|
+
readonly phase: Schema.Literals<readonly ["setup", "prepare", "check", "run"]>;
|
|
162
|
+
readonly message: Schema.String;
|
|
163
|
+
}>]>;
|
|
164
|
+
/** One fork's measurement of a bench, before stats and comparisons. */
|
|
165
|
+
export declare const RawOk: Schema.Struct<{
|
|
166
|
+
readonly id: Schema.String;
|
|
167
|
+
readonly suite: Schema.String;
|
|
168
|
+
readonly name: Schema.String;
|
|
169
|
+
readonly group: Schema.NullOr<Schema.String>;
|
|
170
|
+
readonly params: Schema.$Record<Schema.String, Schema.Union<readonly [Schema.String, Schema.Number, Schema.Boolean]>>;
|
|
171
|
+
readonly tags: Schema.$Array<Schema.String>;
|
|
172
|
+
readonly status: Schema.Literal<"ok">;
|
|
173
|
+
/** Id of the group baseline this bench is reported against. */
|
|
174
|
+
readonly relativeTo: Schema.NullOr<Schema.String>;
|
|
175
|
+
readonly samplesNs: Schema.$Array<Schema.Number>;
|
|
176
|
+
readonly batchSize: Schema.Number;
|
|
177
|
+
readonly overheadNs: Schema.Number;
|
|
178
|
+
readonly heapDeltaBytes: Schema.NullOr<Schema.Number>;
|
|
179
|
+
readonly budgetNs: Schema.NullOr<Schema.Struct<{
|
|
180
|
+
readonly p50: Schema.NullOr<Schema.Number>;
|
|
181
|
+
readonly p99: Schema.NullOr<Schema.Number>;
|
|
182
|
+
}>>;
|
|
183
|
+
}>;
|
|
184
|
+
export type RawOk = typeof RawOk.Type;
|
|
185
|
+
export declare const RawResult: Schema.Union<readonly [Schema.Struct<{
|
|
186
|
+
readonly id: Schema.String;
|
|
187
|
+
readonly suite: Schema.String;
|
|
188
|
+
readonly name: Schema.String;
|
|
189
|
+
readonly group: Schema.NullOr<Schema.String>;
|
|
190
|
+
readonly params: Schema.$Record<Schema.String, Schema.Union<readonly [Schema.String, Schema.Number, Schema.Boolean]>>;
|
|
191
|
+
readonly tags: Schema.$Array<Schema.String>;
|
|
192
|
+
readonly status: Schema.Literal<"ok">;
|
|
193
|
+
/** Id of the group baseline this bench is reported against. */
|
|
194
|
+
readonly relativeTo: Schema.NullOr<Schema.String>;
|
|
195
|
+
readonly samplesNs: Schema.$Array<Schema.Number>;
|
|
196
|
+
readonly batchSize: Schema.Number;
|
|
197
|
+
readonly overheadNs: Schema.Number;
|
|
198
|
+
readonly heapDeltaBytes: Schema.NullOr<Schema.Number>;
|
|
199
|
+
readonly budgetNs: Schema.NullOr<Schema.Struct<{
|
|
200
|
+
readonly p50: Schema.NullOr<Schema.Number>;
|
|
201
|
+
readonly p99: Schema.NullOr<Schema.Number>;
|
|
202
|
+
}>>;
|
|
203
|
+
}>, Schema.Struct<{
|
|
204
|
+
readonly id: Schema.String;
|
|
205
|
+
readonly suite: Schema.String;
|
|
206
|
+
readonly name: Schema.String;
|
|
207
|
+
readonly group: Schema.NullOr<Schema.String>;
|
|
208
|
+
readonly params: Schema.$Record<Schema.String, Schema.Union<readonly [Schema.String, Schema.Number, Schema.Boolean]>>;
|
|
209
|
+
readonly tags: Schema.$Array<Schema.String>;
|
|
210
|
+
readonly status: Schema.Literal<"failed">;
|
|
211
|
+
readonly phase: Schema.Literals<readonly ["setup", "prepare", "check", "run"]>;
|
|
212
|
+
readonly message: Schema.String;
|
|
213
|
+
}>]>;
|
|
214
|
+
export type RawResult = typeof RawResult.Type;
|
|
215
|
+
export type BenchResult = typeof BenchResult.Type;
|
|
216
|
+
export declare const Summary: Schema.Struct<{
|
|
217
|
+
readonly total: Schema.Number;
|
|
218
|
+
readonly failed: Schema.Number;
|
|
219
|
+
readonly regressions: Schema.Number;
|
|
220
|
+
readonly budgetsExceeded: Schema.Number;
|
|
221
|
+
readonly stale: Schema.Number;
|
|
222
|
+
readonly exitCode: Schema.Number;
|
|
223
|
+
}>;
|
|
224
|
+
export type Summary = typeof Summary.Type;
|
|
225
|
+
export declare const BaselineEntry: Schema.Struct<{
|
|
226
|
+
readonly id: Schema.String;
|
|
227
|
+
/** Samples per fork. */
|
|
228
|
+
readonly forks: Schema.$Array<Schema.$Array<Schema.Number>>;
|
|
229
|
+
readonly stats: Schema.Struct<{
|
|
230
|
+
readonly samples: Schema.Number;
|
|
231
|
+
readonly outliers: Schema.Number;
|
|
232
|
+
readonly meanNs: Schema.Number;
|
|
233
|
+
readonly medianNs: Schema.Number;
|
|
234
|
+
readonly p75Ns: Schema.Number;
|
|
235
|
+
readonly p99Ns: Schema.Number;
|
|
236
|
+
readonly minNs: Schema.Number;
|
|
237
|
+
readonly maxNs: Schema.Number;
|
|
238
|
+
readonly madNs: Schema.Number;
|
|
239
|
+
readonly rme: Schema.Number;
|
|
240
|
+
/** Null when the median is below what the clock can resolve. */
|
|
241
|
+
readonly opsPerSec: Schema.NullOr<Schema.Number>;
|
|
242
|
+
}>;
|
|
243
|
+
}>;
|
|
244
|
+
export type BaselineEntry = typeof BaselineEntry.Type;
|
|
245
|
+
export declare const Baseline: Schema.Struct<{
|
|
246
|
+
readonly schemaVersion: Schema.Number;
|
|
247
|
+
readonly name: Schema.String;
|
|
248
|
+
readonly createdAt: Schema.String;
|
|
249
|
+
readonly environment: Schema.Struct<{
|
|
250
|
+
readonly runtime: Schema.String;
|
|
251
|
+
readonly runtimeVersion: Schema.String;
|
|
252
|
+
readonly platform: Schema.String;
|
|
253
|
+
readonly arch: Schema.String;
|
|
254
|
+
readonly cpu: Schema.String;
|
|
255
|
+
readonly cpus: Schema.Number;
|
|
256
|
+
readonly gitSha: Schema.NullOr<Schema.String>;
|
|
257
|
+
readonly gitDirty: Schema.NullOr<Schema.Boolean>;
|
|
258
|
+
}>;
|
|
259
|
+
readonly entries: Schema.$Array<Schema.Struct<{
|
|
260
|
+
readonly id: Schema.String;
|
|
261
|
+
/** Samples per fork. */
|
|
262
|
+
readonly forks: Schema.$Array<Schema.$Array<Schema.Number>>;
|
|
263
|
+
readonly stats: Schema.Struct<{
|
|
264
|
+
readonly samples: Schema.Number;
|
|
265
|
+
readonly outliers: Schema.Number;
|
|
266
|
+
readonly meanNs: Schema.Number;
|
|
267
|
+
readonly medianNs: Schema.Number;
|
|
268
|
+
readonly p75Ns: Schema.Number;
|
|
269
|
+
readonly p99Ns: Schema.Number;
|
|
270
|
+
readonly minNs: Schema.Number;
|
|
271
|
+
readonly maxNs: Schema.Number;
|
|
272
|
+
readonly madNs: Schema.Number;
|
|
273
|
+
readonly rme: Schema.Number;
|
|
274
|
+
/** Null when the median is below what the clock can resolve. */
|
|
275
|
+
readonly opsPerSec: Schema.NullOr<Schema.Number>;
|
|
276
|
+
}>;
|
|
277
|
+
}>>;
|
|
278
|
+
}>;
|
|
279
|
+
export type Baseline = typeof Baseline.Type;
|
|
280
|
+
//# sourceMappingURL=BenchResult.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BenchResult.d.ts","sourceRoot":"","sources":["../../src/BenchResult.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAE/B,eAAO,MAAM,aAAa,IAAI,CAAA;AAE9B,eAAO,MAAM,KAAK;;;;;;;;;;;IAWhB,gEAAgE;;EAEhE,CAAA;AACF,MAAM,MAAM,KAAK,GAAG,OAAO,KAAK,CAAC,IAAI,CAAA;AAErC,eAAO,MAAM,WAAW;;;;;;;;;EAStB,CAAA;AACF,MAAM,MAAM,WAAW,GAAG,OAAO,WAAW,CAAC,IAAI,CAAA;AAEjD,eAAO,MAAM,OAAO,wEAAgE,CAAA;AACpF,MAAM,MAAM,OAAO,GAAG,OAAO,OAAO,CAAC,IAAI,CAAA;AAEzC,eAAO,MAAM,UAAU;;;;;;IAMrB,mEAAmE;;EAEnE,CAAA;AACF,MAAM,MAAM,UAAU,GAAG,OAAO,UAAU,CAAC,IAAI,CAAA;AAE/C,eAAO,MAAM,WAAW;;;EAGtB,CAAA;AACF,MAAM,MAAM,WAAW,GAAG,OAAO,WAAW,CAAC,IAAI,CAAA;AAEjD,eAAO,MAAM,QAAQ;;;EAGnB,CAAA;AACF,MAAM,MAAM,QAAQ,GAAG,OAAO,QAAQ,CAAC,IAAI,CAAA;AAW3C,eAAO,MAAM,QAAQ;;;;;;;;;;;;;;;;;;;QApDnB,gEAAgE;;;IAwDhE,+EAA+E;;;;;;;;;;;;;;;QA9B/E,mEAAmE;;;;;;;EAsCnE,CAAA;AACF,MAAM,MAAM,QAAQ,GAAG,OAAO,QAAQ,CAAC,IAAI,CAAA;AAE3C,eAAO,MAAM,YAAY;;;;;;;;;;EAKvB,CAAA;AACF,MAAM,MAAM,YAAY,GAAG,OAAO,YAAY,CAAC,IAAI,CAAA;AAEnD,eAAO,MAAM,WAAW;;;;;;;;;;;;;;;;;;;QA3EtB,gEAAgE;;;IAwDhE,+EAA+E;;;;;;;;;;;;;;;QA9B/E,mEAAmE;;;;;;;;;;;;;;;;;IAiDJ,CAAA;AAEjE,uEAAuE;AACvE,eAAO,MAAM,KAAK;;;;;;;;IAGhB,+DAA+D;;;;;;;;;;EAO/D,CAAA;AACF,MAAM,MAAM,KAAK,GAAG,OAAO,KAAK,CAAC,IAAI,CAAA;AAErC,eAAO,MAAM,SAAS;;;;;;;;IAVpB,+DAA+D;;;;;;;;;;;;;;;;;;;;IAUL,CAAA;AAC5D,MAAM,MAAM,SAAS,GAAG,OAAO,SAAS,CAAC,IAAI,CAAA;AAC7C,MAAM,MAAM,WAAW,GAAG,OAAO,WAAW,CAAC,IAAI,CAAA;AAEjD,eAAO,MAAM,OAAO;;;;;;;EAOlB,CAAA;AACF,MAAM,MAAM,OAAO,GAAG,OAAO,OAAO,CAAC,IAAI,CAAA;AAEzC,eAAO,MAAM,aAAa;;IAExB,wBAAwB;;;;;;;;;;;;;QA3GxB,gEAAgE;;;EA8GhE,CAAA;AACF,MAAM,MAAM,aAAa,GAAG,OAAO,aAAa,CAAC,IAAI,CAAA;AAErD,eAAO,MAAM,QAAQ;;;;;;;;;;;;;;;;QANnB,wBAAwB;;;;;;;;;;;;;YA3GxB,gEAAgE;;;;EAuHhE,CAAA;AACF,MAAM,MAAM,QAAQ,GAAG,OAAO,QAAQ,CAAC,IAAI,CAAA"}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { Schema } from 'effect';
|
|
2
|
+
export const schemaVersion = 2;
|
|
3
|
+
export const Stats = Schema.Struct({
|
|
4
|
+
samples: Schema.Number,
|
|
5
|
+
outliers: Schema.Number,
|
|
6
|
+
meanNs: Schema.Number,
|
|
7
|
+
medianNs: Schema.Number,
|
|
8
|
+
p75Ns: Schema.Number,
|
|
9
|
+
p99Ns: Schema.Number,
|
|
10
|
+
minNs: Schema.Number,
|
|
11
|
+
maxNs: Schema.Number,
|
|
12
|
+
madNs: Schema.Number,
|
|
13
|
+
rme: Schema.Number,
|
|
14
|
+
/** Null when the median is below what the clock can resolve. */
|
|
15
|
+
opsPerSec: Schema.NullOr(Schema.Number),
|
|
16
|
+
});
|
|
17
|
+
export const Environment = Schema.Struct({
|
|
18
|
+
runtime: Schema.String,
|
|
19
|
+
runtimeVersion: Schema.String,
|
|
20
|
+
platform: Schema.String,
|
|
21
|
+
arch: Schema.String,
|
|
22
|
+
cpu: Schema.String,
|
|
23
|
+
cpus: Schema.Number,
|
|
24
|
+
gitSha: Schema.NullOr(Schema.String),
|
|
25
|
+
gitDirty: Schema.NullOr(Schema.Boolean),
|
|
26
|
+
});
|
|
27
|
+
export const Verdict = Schema.Literals(['faster', 'slower', 'same', 'inconclusive']);
|
|
28
|
+
export const Comparison = Schema.Struct({
|
|
29
|
+
baseline: Schema.String,
|
|
30
|
+
baselineMedianNs: Schema.Number,
|
|
31
|
+
change: Schema.Number,
|
|
32
|
+
ci: Schema.Tuple([Schema.Number, Schema.Number]),
|
|
33
|
+
verdict: Verdict,
|
|
34
|
+
/** The baseline was recorded on a different runtime or machine. */
|
|
35
|
+
stale: Schema.Boolean,
|
|
36
|
+
});
|
|
37
|
+
export const BudgetCheck = Schema.Struct({
|
|
38
|
+
status: Schema.Literals(['ok', 'exceeded']),
|
|
39
|
+
violations: Schema.Array(Schema.String),
|
|
40
|
+
});
|
|
41
|
+
export const Relative = Schema.Struct({
|
|
42
|
+
baselineId: Schema.String,
|
|
43
|
+
ratio: Schema.Number,
|
|
44
|
+
});
|
|
45
|
+
const identity = {
|
|
46
|
+
id: Schema.String,
|
|
47
|
+
suite: Schema.String,
|
|
48
|
+
name: Schema.String,
|
|
49
|
+
group: Schema.NullOr(Schema.String),
|
|
50
|
+
params: Schema.Record(Schema.String, Schema.Union([Schema.String, Schema.Number, Schema.Boolean])),
|
|
51
|
+
tags: Schema.Array(Schema.String),
|
|
52
|
+
};
|
|
53
|
+
export const OkResult = Schema.Struct({
|
|
54
|
+
status: Schema.Literal('ok'),
|
|
55
|
+
...identity,
|
|
56
|
+
stats: Stats,
|
|
57
|
+
/** Fresh processes the samples came from; comparisons resample across them. */
|
|
58
|
+
forks: Schema.Number,
|
|
59
|
+
batchSize: Schema.Number,
|
|
60
|
+
overheadNs: Schema.Number,
|
|
61
|
+
heapDeltaBytes: Schema.NullOr(Schema.Number),
|
|
62
|
+
budget: Schema.NullOr(BudgetCheck),
|
|
63
|
+
comparison: Schema.NullOr(Comparison),
|
|
64
|
+
relative: Schema.NullOr(Relative),
|
|
65
|
+
});
|
|
66
|
+
export const FailedResult = Schema.Struct({
|
|
67
|
+
status: Schema.Literal('failed'),
|
|
68
|
+
...identity,
|
|
69
|
+
phase: Schema.Literals(['setup', 'prepare', 'check', 'run']),
|
|
70
|
+
message: Schema.String,
|
|
71
|
+
});
|
|
72
|
+
export const BenchResult = Schema.Union([OkResult, FailedResult]);
|
|
73
|
+
/** One fork's measurement of a bench, before stats and comparisons. */
|
|
74
|
+
export const RawOk = Schema.Struct({
|
|
75
|
+
status: Schema.Literal('ok'),
|
|
76
|
+
...identity,
|
|
77
|
+
/** Id of the group baseline this bench is reported against. */
|
|
78
|
+
relativeTo: Schema.NullOr(Schema.String),
|
|
79
|
+
samplesNs: Schema.Array(Schema.Number),
|
|
80
|
+
batchSize: Schema.Number,
|
|
81
|
+
overheadNs: Schema.Number,
|
|
82
|
+
heapDeltaBytes: Schema.NullOr(Schema.Number),
|
|
83
|
+
budgetNs: Schema.NullOr(Schema.Struct({ p50: Schema.NullOr(Schema.Number), p99: Schema.NullOr(Schema.Number) })),
|
|
84
|
+
});
|
|
85
|
+
export const RawResult = Schema.Union([RawOk, FailedResult]);
|
|
86
|
+
export const Summary = Schema.Struct({
|
|
87
|
+
total: Schema.Number,
|
|
88
|
+
failed: Schema.Number,
|
|
89
|
+
regressions: Schema.Number,
|
|
90
|
+
budgetsExceeded: Schema.Number,
|
|
91
|
+
stale: Schema.Number,
|
|
92
|
+
exitCode: Schema.Number,
|
|
93
|
+
});
|
|
94
|
+
export const BaselineEntry = Schema.Struct({
|
|
95
|
+
id: Schema.String,
|
|
96
|
+
/** Samples per fork. */
|
|
97
|
+
forks: Schema.Array(Schema.Array(Schema.Number)),
|
|
98
|
+
stats: Stats,
|
|
99
|
+
});
|
|
100
|
+
export const Baseline = Schema.Struct({
|
|
101
|
+
schemaVersion: Schema.Number,
|
|
102
|
+
name: Schema.String,
|
|
103
|
+
createdAt: Schema.String,
|
|
104
|
+
environment: Environment,
|
|
105
|
+
entries: Schema.Array(BaselineEntry),
|
|
106
|
+
});
|
|
107
|
+
//# sourceMappingURL=BenchResult.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BenchResult.js","sourceRoot":"","sources":["../../src/BenchResult.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { Verdict } from './BenchResult.ts';
|
|
2
|
+
export interface CompareOptions {
|
|
3
|
+
/** Changes smaller than this fraction count as noise. */
|
|
4
|
+
readonly noiseThreshold: number;
|
|
5
|
+
readonly resamples?: number;
|
|
6
|
+
readonly seed?: number;
|
|
7
|
+
}
|
|
8
|
+
export interface Change {
|
|
9
|
+
readonly change: number;
|
|
10
|
+
readonly ci: readonly [number, number];
|
|
11
|
+
readonly verdict: Verdict;
|
|
12
|
+
}
|
|
13
|
+
export declare const verdictOf: ([low, high]: readonly [number, number], noiseThreshold: number) => Verdict;
|
|
14
|
+
/** Two-sided 97.5% quantile of Student's t, conservative between table rows. */
|
|
15
|
+
export declare const tQuantile: (df: number) => number;
|
|
16
|
+
/**
|
|
17
|
+
* Drift between processes (JIT state, CPU frequency) dwarfs noise within one run, so each fork's median is one
|
|
18
|
+
* observation: a pooled t-interval on log medians. Only when both sides have a single fork does it fall back to a
|
|
19
|
+
* bootstrap over samples, which sees within-run noise only.
|
|
20
|
+
*/
|
|
21
|
+
export declare const compare: (current: ReadonlyArray<ReadonlyArray<number>>, baseline: ReadonlyArray<ReadonlyArray<number>>, { noiseThreshold, resamples, seed }: CompareOptions) => Change;
|
|
22
|
+
//# sourceMappingURL=Compare.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Compare.d.ts","sourceRoot":"","sources":["../../src/Compare.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAA;AAG/C,MAAM,WAAW,cAAc;IAC7B,yDAAyD;IACzD,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAA;IAC/B,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAA;IAC3B,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CACvB;AAED,MAAM,WAAW,MAAM;IACrB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,EAAE,EAAE,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IACtC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;CAC1B;AASD,eAAO,MAAM,SAAS,gBAAiB,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,kBAAkB,MAAM,KAAG,OAOnE,CAAA;AAwCxB,gFAAgF;AAChF,eAAO,MAAM,SAAS,OAAQ,MAAM,KAAG,MAAgE,CAAA;AAOvG;;;;GAIG;AACH,eAAO,MAAM,OAAO,YACT,aAAa,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,YACnC,aAAa,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,uCACO,cAAc,KAClE,MAyBF,CAAA"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { median } from './Stats.js';
|
|
2
|
+
const mulberry32 = (seed) => () => {
|
|
3
|
+
seed = (seed + 0x6d2b79f5) | 0;
|
|
4
|
+
let t = Math.imul(seed ^ (seed >>> 15), 1 | seed);
|
|
5
|
+
t = (t + Math.imul(t ^ (t >>> 7), 61 | t)) ^ t;
|
|
6
|
+
return ((t ^ (t >>> 14)) >>> 0) / 4294967296;
|
|
7
|
+
};
|
|
8
|
+
export const verdictOf = ([low, high], noiseThreshold) => high < -noiseThreshold
|
|
9
|
+
? 'faster'
|
|
10
|
+
: low > noiseThreshold
|
|
11
|
+
? 'slower'
|
|
12
|
+
: low >= -noiseThreshold && high <= noiseThreshold
|
|
13
|
+
? 'same'
|
|
14
|
+
: 'inconclusive';
|
|
15
|
+
const pick = (values, random) => values[Math.floor(random() * values.length)];
|
|
16
|
+
const percentile95 = (sorted) => [
|
|
17
|
+
sorted[Math.floor(sorted.length * 0.025)],
|
|
18
|
+
sorted[Math.min(sorted.length - 1, Math.ceil(sorted.length * 0.975))],
|
|
19
|
+
];
|
|
20
|
+
const bootstrap = (current, baseline, resamples, seed) => {
|
|
21
|
+
const random = mulberry32(seed);
|
|
22
|
+
const resample = (values) => median(Array.from(values, () => pick(values, random)));
|
|
23
|
+
return percentile95(Array.from({ length: resamples }, () => resample(current) / resample(baseline) - 1).sort((a, b) => a - b));
|
|
24
|
+
};
|
|
25
|
+
const tTable = [
|
|
26
|
+
[1, 12.706],
|
|
27
|
+
[2, 4.303],
|
|
28
|
+
[3, 3.182],
|
|
29
|
+
[4, 2.776],
|
|
30
|
+
[5, 2.571],
|
|
31
|
+
[6, 2.447],
|
|
32
|
+
[7, 2.365],
|
|
33
|
+
[8, 2.306],
|
|
34
|
+
[9, 2.262],
|
|
35
|
+
[10, 2.228],
|
|
36
|
+
[12, 2.179],
|
|
37
|
+
[15, 2.131],
|
|
38
|
+
[20, 2.086],
|
|
39
|
+
[30, 2.042],
|
|
40
|
+
[60, 2.0],
|
|
41
|
+
];
|
|
42
|
+
/** Two-sided 97.5% quantile of Student's t, conservative between table rows. */
|
|
43
|
+
export const tQuantile = (df) => tTable.findLast(([rowDf]) => rowDf <= df)?.[1] ?? 1.96;
|
|
44
|
+
const variance = (values) => {
|
|
45
|
+
const mean = values.reduce((sum, value) => sum + value, 0) / values.length;
|
|
46
|
+
return values.reduce((sum, value) => sum + (value - mean) ** 2, 0) / (values.length - 1);
|
|
47
|
+
};
|
|
48
|
+
/**
|
|
49
|
+
* Drift between processes (JIT state, CPU frequency) dwarfs noise within one run, so each fork's median is one
|
|
50
|
+
* observation: a pooled t-interval on log medians. Only when both sides have a single fork does it fall back to a
|
|
51
|
+
* bootstrap over samples, which sees within-run noise only.
|
|
52
|
+
*/
|
|
53
|
+
export const compare = (current, baseline, { noiseThreshold, resamples = 2000, seed = 0x5eed }) => {
|
|
54
|
+
const change = median(current.flat()) / median(baseline.flat()) - 1;
|
|
55
|
+
const forkLogs = (forks) => forks.filter(fork => fork.length > 0).map(fork => Math.log(median(fork)));
|
|
56
|
+
const currentLogs = forkLogs(current);
|
|
57
|
+
const baselineLogs = forkLogs(baseline);
|
|
58
|
+
const df = Math.max(0, currentLogs.length - 1) + Math.max(0, baselineLogs.length - 1);
|
|
59
|
+
if (currentLogs.length === 0 || baselineLogs.length === 0 || !Number.isFinite(change)) {
|
|
60
|
+
return { change, ci: [change, change], verdict: 'inconclusive' };
|
|
61
|
+
}
|
|
62
|
+
if (df === 0) {
|
|
63
|
+
const ci = bootstrap(current.flat(), baseline.flat(), resamples, seed);
|
|
64
|
+
return { change, ci, verdict: verdictOf(ci, noiseThreshold) };
|
|
65
|
+
}
|
|
66
|
+
const pooled = ((currentLogs.length - 1) * (currentLogs.length > 1 ? variance(currentLogs) : 0) +
|
|
67
|
+
(baselineLogs.length - 1) * (baselineLogs.length > 1 ? variance(baselineLogs) : 0)) /
|
|
68
|
+
df;
|
|
69
|
+
const mean = (values) => values.reduce((sum, value) => sum + value, 0) / values.length;
|
|
70
|
+
const diff = mean(currentLogs) - mean(baselineLogs);
|
|
71
|
+
const halfWidth = tQuantile(df) * Math.sqrt(pooled * (1 / currentLogs.length + 1 / baselineLogs.length));
|
|
72
|
+
const ci = [Math.exp(diff - halfWidth) - 1, Math.exp(diff + halfWidth) - 1];
|
|
73
|
+
return { change, ci, verdict: verdictOf(ci, noiseThreshold) };
|
|
74
|
+
};
|
|
75
|
+
//# sourceMappingURL=Compare.js.map
|