178 lines
6.1 KiB
TypeScript
178 lines
6.1 KiB
TypeScript
import { bench, describe } from 'vitest';
|
|
import { STANDARD, EXTENDED } from '../helpers/bench-options.js';
|
|
import { SIZES, errorIndices } from '../helpers/data-generators.js';
|
|
import {
|
|
ok,
|
|
err,
|
|
Result,
|
|
ntOk,
|
|
ntErr,
|
|
NtResult,
|
|
TsOk,
|
|
TsErr,
|
|
TsResult,
|
|
OxOk,
|
|
OxErr,
|
|
E,
|
|
pipe,
|
|
TmResult,
|
|
} from '../helpers/imports.js';
|
|
import * as RA from 'fp-ts/ReadonlyArray';
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Result.all — all Ok
|
|
// ---------------------------------------------------------------------------
|
|
|
|
for (const size of SIZES) {
|
|
const opts = size >= 10_000 ? EXTENDED : STANDARD;
|
|
|
|
const nmAll = Array.from({ length: size }, (_, i) => ok(i));
|
|
const ntAll = Array.from({ length: size }, (_, i) => ntOk(i));
|
|
const tsAll = Array.from({ length: size }, (_, i) => TsOk<number, string>(i));
|
|
const oxAll = Array.from({ length: size }, (_, i) => OxOk(i));
|
|
const fpAll = Array.from({ length: size }, (_, i) => E.right(i));
|
|
const tmAll = Array.from({ length: size }, (_, i) => TmResult.ok<number, string>(i));
|
|
|
|
describe(`Result.all — ${size} items, all Ok`, () => {
|
|
bench('native-monad', () => { Result.all(nmAll); }, opts);
|
|
bench('neverthrow', () => { NtResult.combine(ntAll); }, opts);
|
|
bench('ts-results-es', () => { TsResult.all(...tsAll); }, opts);
|
|
// oxide.ts: no built-in all/combine
|
|
bench('fp-ts', () => { pipe(fpAll, RA.sequence(E.Applicative)); }, opts);
|
|
// true-myth: no built-in all
|
|
bench('true-myth (manual)', () => {
|
|
const values: number[] = [];
|
|
for (const r of tmAll) {
|
|
if (TmResult.isErr(r)) return r;
|
|
values.push((r as { value: number }).value);
|
|
}
|
|
return TmResult.ok(values);
|
|
}, opts);
|
|
});
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Result.all — 20% Err (short-circuit)
|
|
// ---------------------------------------------------------------------------
|
|
|
|
for (const size of SIZES) {
|
|
const opts = size >= 10_000 ? EXTENDED : STANDARD;
|
|
const errIdx = errorIndices(size, 0.2);
|
|
|
|
const nmMixed = Array.from({ length: size }, (_, i) =>
|
|
errIdx.has(i) ? err('fail') : ok(i),
|
|
);
|
|
const ntMixed = Array.from({ length: size }, (_, i) =>
|
|
errIdx.has(i) ? ntErr('fail') : ntOk(i),
|
|
);
|
|
const tsMixed = Array.from({ length: size }, (_, i) =>
|
|
errIdx.has(i) ? TsErr<number, string>('fail') : TsOk<number, string>(i),
|
|
);
|
|
const fpMixed = Array.from({ length: size }, (_, i) =>
|
|
errIdx.has(i) ? E.left('fail' as const) : E.right(i),
|
|
);
|
|
const tmMixed = Array.from({ length: size }, (_, i) =>
|
|
errIdx.has(i) ? TmResult.err<number, string>('fail') : TmResult.ok<number, string>(i),
|
|
);
|
|
|
|
describe(`Result.all — ${size} items, 20% Err (short-circuit)`, () => {
|
|
bench('native-monad', () => { Result.all(nmMixed); }, opts);
|
|
bench('neverthrow', () => { NtResult.combine(ntMixed as any); }, opts);
|
|
bench('ts-results-es', () => { TsResult.all(...tsMixed); }, opts);
|
|
bench('fp-ts', () => { pipe(fpMixed, RA.sequence(E.Applicative)); }, opts);
|
|
bench('true-myth (manual)', () => {
|
|
const values: number[] = [];
|
|
for (const r of tmMixed) {
|
|
if (TmResult.isErr(r)) return r;
|
|
values.push((r as { value: number }).value);
|
|
}
|
|
return TmResult.ok(values);
|
|
}, opts);
|
|
});
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Result.partition
|
|
// ---------------------------------------------------------------------------
|
|
|
|
for (const size of SIZES) {
|
|
const opts = size >= 10_000 ? EXTENDED : STANDARD;
|
|
const errIdx = errorIndices(size, 0.2);
|
|
|
|
const nmMixed = Array.from({ length: size }, (_, i) =>
|
|
errIdx.has(i) ? err('fail') : ok(i),
|
|
);
|
|
const ntMixed = Array.from({ length: size }, (_, i) =>
|
|
errIdx.has(i) ? ntErr('fail') : ntOk(i),
|
|
);
|
|
const fpMixed = Array.from({ length: size }, (_, i) =>
|
|
errIdx.has(i) ? E.left('fail' as const) : E.right(i),
|
|
);
|
|
|
|
describe(`Result.partition — ${size} items`, () => {
|
|
bench('native-monad', () => { Result.partition(nmMixed); }, opts);
|
|
bench('neverthrow (manual)', () => {
|
|
const values: number[] = [];
|
|
const errors: string[] = [];
|
|
for (const r of ntMixed) {
|
|
if (r.isOk()) values.push(r.value);
|
|
else errors.push(r.error);
|
|
}
|
|
return { values, errors };
|
|
}, opts);
|
|
bench('fp-ts', () => { RA.separate(fpMixed); }, opts);
|
|
});
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Result.compact
|
|
// ---------------------------------------------------------------------------
|
|
|
|
for (const size of SIZES) {
|
|
const opts = size >= 10_000 ? EXTENDED : STANDARD;
|
|
const errIdx = errorIndices(size, 0.2);
|
|
|
|
const nmMixed = Array.from({ length: size }, (_, i) =>
|
|
errIdx.has(i) ? err('fail') : ok(i),
|
|
);
|
|
const ntMixed = Array.from({ length: size }, (_, i) =>
|
|
errIdx.has(i) ? ntErr('fail') : ntOk(i),
|
|
);
|
|
|
|
describe(`Result.compact — ${size} items`, () => {
|
|
bench('native-monad', () => { Result.compact(nmMixed); }, opts);
|
|
bench('neverthrow (manual)', () => {
|
|
const values: number[] = [];
|
|
for (const r of ntMixed) {
|
|
if (r.isOk()) values.push(r.value);
|
|
}
|
|
return values;
|
|
}, opts);
|
|
});
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Result.some / Result.every
|
|
// ---------------------------------------------------------------------------
|
|
|
|
for (const size of [100, 1_000]) {
|
|
const errIdx = errorIndices(size, 0.2);
|
|
|
|
const nmMixed = Array.from({ length: size }, (_, i) =>
|
|
errIdx.has(i) ? err('fail') : ok(i),
|
|
);
|
|
const ntMixed = Array.from({ length: size }, (_, i) =>
|
|
errIdx.has(i) ? ntErr('fail') : ntOk(i),
|
|
);
|
|
|
|
describe(`Result.some — ${size} items`, () => {
|
|
bench('native-monad', () => { Result.some(nmMixed); }, STANDARD);
|
|
bench('neverthrow (manual)', () => { ntMixed.some(r => r.isOk()); }, STANDARD);
|
|
});
|
|
|
|
describe(`Result.every — ${size} items`, () => {
|
|
bench('native-monad', () => { Result.every(nmMixed); }, STANDARD);
|
|
bench('neverthrow (manual)', () => { ntMixed.every(r => r.isOk()); }, STANDARD);
|
|
});
|
|
}
|