87 lines
3.3 KiB
Markdown
87 lines
3.3 KiB
Markdown
# 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:
|
|
|
|
```bash
|
|
cd .. && pnpm build
|
|
```
|
|
|
|
This happens automatically via the `prebench` script when running `pnpm bench`.
|
|
|
|
## Running Benchmarks
|
|
|
|
```bash
|
|
# 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.
|