Files
native-monad/benchmarks/README.md
2026-03-30 08:34:35 +02:00

3.3 KiB

native-monad benchmarks

Comprehensive benchmark suite comparing native-monad against popular TypeScript monad libraries.

Competitor Libraries

Library Result type Option type Async
neverthrow Result<T,E> ResultAsync
ts-results-es Result<T,E> Option<T>
oxide.ts Result<T,E> Option<T>
fp-ts Either<E,A> Option<A> TaskEither
true-myth Result<T,E> Maybe<T>

Prerequisites

The parent project must be built before running benchmarks:

cd .. && pnpm build

This happens automatically via the prebench script when running pnpm bench.

Running Benchmarks

# Install dependencies (first time only)
pnpm install

# Run all benchmarks
pnpm bench

# Run by type
pnpm bench:result
pnpm bench:option
pnpm bench:query
pnpm bench:scenarios

# Run a single file
npx vitest bench result/construction.bench.ts --run

Reading Output

Vitest bench outputs a table per describe group:

Column Meaning
hz Operations per second
min Fastest single iteration (ms)
max Slowest single iteration (ms)
mean Average iteration time (ms)
p75 75th percentile iteration time (ms)
p99 99th percentile iteration time (ms)
rme Relative margin of error (%)

After all groups, a Summary section shows the fastest library per group and relative slowdown factors.

Benchmark Structure

result/           — Result/Either type benchmarks
option/           — Option/Maybe type benchmarks
query/            — Query (three-state) benchmarks + nested equivalents
scenarios/        — Real-world patterns (parsing, validation, error propagation)
helpers/          — Shared config, data generators, imports

Each benchmark file covers a specific operation category:

  • construction.bench.ts — Creating Ok/Err/Some/None instances
  • instance-methods.bench.ts — map, flatMap, mapErr, match, filter
  • type-guards.bench.ts — isOk/isErr/isSome/isNone
  • conversion.bench.ts — toNullable, toUndefined, toString
  • collection.bench.ts — all, partition, compact, some, every
  • chaining.bench.ts — Multi-step pipelines
  • from-wrapping.bench.ts — Try-catch wrapping
  • async.bench.ts — Promise-based operations

Caveats

  • Microbenchmarks measure isolated operations. Real-world performance depends on usage patterns, GC pressure, and JIT behavior in context.
  • Async benchmarks have higher variance due to event loop scheduling. Results use extended warmup/time to compensate.
  • fp-ts uses a fundamentally different paradigm (pipe + standalone functions vs class methods). The benchmarks use each library's idiomatic API for fair comparison.
  • bench.skip appears when a library lacks an equivalent operation — no fabricated workarounds.
  • Collection benchmarks test at sizes 100 and 10K to show scaling behavior.