initial commit
This commit is contained in:
86
benchmarks/README.md
Normal file
86
benchmarks/README.md
Normal file
@@ -0,0 +1,86 @@
|
||||
# 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.
|
||||
Reference in New Issue
Block a user