initial commit
This commit is contained in:
153
benchmarks/result/chaining.bench.ts
Normal file
153
benchmarks/result/chaining.bench.ts
Normal file
@@ -0,0 +1,153 @@
|
||||
import { bench, describe } from 'vitest';
|
||||
import { STANDARD } from '../helpers/bench-options.js';
|
||||
import {
|
||||
ok,
|
||||
err,
|
||||
ntOk,
|
||||
ntErr,
|
||||
TsOk,
|
||||
TsErr,
|
||||
OxOk,
|
||||
OxErr,
|
||||
E,
|
||||
pipe,
|
||||
TmResult,
|
||||
} from '../helpers/imports.js';
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// 5-step pipeline — success path
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
describe('Result chaining — 5-step pipeline (all succeed)', () => {
|
||||
bench('native-monad', () => {
|
||||
ok(42)
|
||||
.map(x => x * 2)
|
||||
.flatMap(x => (x > 0 ? ok(x) : err('negative')))
|
||||
.map(x => ({ value: x }))
|
||||
.flatMap(x => ok({ ...x, label: 'result' }))
|
||||
.map(x => JSON.stringify(x));
|
||||
}, STANDARD);
|
||||
|
||||
bench('neverthrow', () => {
|
||||
ntOk(42)
|
||||
.map(x => x * 2)
|
||||
.andThen(x => (x > 0 ? ntOk(x) : ntErr('negative')))
|
||||
.map(x => ({ value: x }))
|
||||
.andThen(x => ntOk({ ...x, label: 'result' }))
|
||||
.map(x => JSON.stringify(x));
|
||||
}, STANDARD);
|
||||
|
||||
bench('ts-results-es', () => {
|
||||
TsOk<number, string>(42)
|
||||
.map(x => x * 2)
|
||||
.andThen(x => (x > 0 ? TsOk(x) : TsErr('negative')))
|
||||
.map(x => ({ value: x }))
|
||||
.andThen(x => TsOk<{ value: number; label: string }, string>({ ...x, label: 'result' }))
|
||||
.map(x => JSON.stringify(x));
|
||||
}, STANDARD);
|
||||
|
||||
bench('oxide.ts', () => {
|
||||
OxOk(42)
|
||||
.map(x => x * 2)
|
||||
.andThen(x => (x > 0 ? OxOk(x) : OxErr('negative')))
|
||||
.map(x => ({ value: x }))
|
||||
.andThen(x => OxOk({ ...x, label: 'result' }))
|
||||
.map(x => JSON.stringify(x));
|
||||
}, STANDARD);
|
||||
|
||||
bench('fp-ts', () => {
|
||||
pipe(
|
||||
E.right(42),
|
||||
E.map(x => x * 2),
|
||||
E.flatMap(x => (x > 0 ? E.right(x) : E.left('negative'))),
|
||||
E.map(x => ({ value: x })),
|
||||
E.flatMap(x => E.right({ ...x, label: 'result' })),
|
||||
E.map(x => JSON.stringify(x)),
|
||||
);
|
||||
}, STANDARD);
|
||||
|
||||
bench('true-myth', () => {
|
||||
TmResult.ok<number, string>(42)
|
||||
.map(x => x * 2)
|
||||
.andThen(x => (x > 0 ? TmResult.ok(x) : TmResult.err('negative')))
|
||||
.map(x => ({ value: x }))
|
||||
.andThen(x => TmResult.ok({ ...x, label: 'result' }))
|
||||
.map(x => JSON.stringify(x));
|
||||
}, STANDARD);
|
||||
});
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// 10-step pipeline — error at step 1 (9 no-ops)
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
describe('Result chaining — error at step 1, 9 no-op maps', () => {
|
||||
const nmErr = err('fail');
|
||||
const ntErrVal = ntErr('fail');
|
||||
const tsErr = TsErr<number, string>('fail');
|
||||
const oxErr = OxErr('fail');
|
||||
const fpErr = E.left('fail');
|
||||
const tmErr = TmResult.err<number, string>('fail');
|
||||
const fn = (x: number) => x + 1;
|
||||
|
||||
bench('native-monad', () => {
|
||||
nmErr.map(fn).map(fn).map(fn).map(fn).map(fn).map(fn).map(fn).map(fn).map(fn);
|
||||
}, STANDARD);
|
||||
|
||||
bench('neverthrow', () => {
|
||||
ntErrVal.map(fn).map(fn).map(fn).map(fn).map(fn).map(fn).map(fn).map(fn).map(fn);
|
||||
}, STANDARD);
|
||||
|
||||
bench('ts-results-es', () => {
|
||||
tsErr.map(fn).map(fn).map(fn).map(fn).map(fn).map(fn).map(fn).map(fn).map(fn);
|
||||
}, STANDARD);
|
||||
|
||||
bench('oxide.ts', () => {
|
||||
oxErr.map(fn).map(fn).map(fn).map(fn).map(fn).map(fn).map(fn).map(fn).map(fn);
|
||||
}, STANDARD);
|
||||
|
||||
bench('fp-ts', () => {
|
||||
pipe(fpErr, E.map(fn), E.map(fn), E.map(fn), E.map(fn), E.map(fn), E.map(fn), E.map(fn), E.map(fn), E.map(fn));
|
||||
}, STANDARD);
|
||||
|
||||
bench('true-myth', () => {
|
||||
tmErr.map(fn).map(fn).map(fn).map(fn).map(fn).map(fn).map(fn).map(fn).map(fn);
|
||||
}, STANDARD);
|
||||
});
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// 20-step deep map chain — success path
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
describe('Result chaining — 20 maps on Ok', () => {
|
||||
const fn = (x: number) => x + 1;
|
||||
|
||||
bench('native-monad', () => {
|
||||
let r = ok(0);
|
||||
for (let i = 0; i < 20; i++) r = r.map(fn);
|
||||
}, STANDARD);
|
||||
|
||||
bench('neverthrow', () => {
|
||||
let r = ntOk(0);
|
||||
for (let i = 0; i < 20; i++) r = r.map(fn);
|
||||
}, STANDARD);
|
||||
|
||||
bench('ts-results-es', () => {
|
||||
let r = TsOk<number, string>(0);
|
||||
for (let i = 0; i < 20; i++) r = r.map(fn) as any;
|
||||
}, STANDARD);
|
||||
|
||||
bench('oxide.ts', () => {
|
||||
let r = OxOk(0);
|
||||
for (let i = 0; i < 20; i++) r = r.map(fn) as any;
|
||||
}, STANDARD);
|
||||
|
||||
bench('fp-ts', () => {
|
||||
let r = E.right(0) as E.Either<string, number>;
|
||||
for (let i = 0; i < 20; i++) r = pipe(r, E.map(fn));
|
||||
}, STANDARD);
|
||||
|
||||
bench('true-myth', () => {
|
||||
let r = TmResult.ok<number, string>(0);
|
||||
for (let i = 0; i < 20; i++) r = r.map(fn) as any;
|
||||
}, STANDARD);
|
||||
});
|
||||
Reference in New Issue
Block a user