|
8 | 8 | [](#license) |
9 | 9 | [](https://nodejs.org) |
10 | 10 |
|
| 11 | +[Benchmarks](#benchmarks) • |
11 | 12 | [Behavior contract](docs/CONTRACT.md) • |
12 | 13 | [Divergences](docs/DIVERGENCE.md) • |
13 | 14 | [Dependency rationale](docs/DEPENDENCIES.md) |
@@ -96,6 +97,47 @@ normal use. |
96 | 97 |
|
97 | 98 | The suite runs all four lanes. Each passes 5,679 tests across 435 files. |
98 | 99 |
|
| 100 | +## Benchmarks |
| 101 | + |
| 102 | +Measured against Zod v4.4.3 on the native tier, with valid inputs. Each figure |
| 103 | +is the median of three full runs. The harness lives in `packages/bench`; the |
| 104 | +comparison set is fixed in `packages/bench/gate.mjs`. |
| 105 | + |
| 106 | +| Suite | Workload per op | zodrs (ops/s) | zod4 (ops/s) | Ratio | |
| 107 | +|---|---|---:|---:|---:| |
| 108 | +| `z.string().parse` | 10,000 strings | 34,252 | 1,875 | 18.27x | |
| 109 | +| `z.number().parse` | 10,000 numbers | 8,116 | 1,570 | 5.17x | |
| 110 | +| `z.array().parse` | 1,000 arrays of 3 strings | 12,217 | 4,188 | 2.92x | |
| 111 | +| `z.union().parse` | 1 value, 3-member union | 3,438,230 | 1,495,908 | 2.30x | |
| 112 | +| `z.discriminatedUnion().parse` | 100 objects | 87,666 | 39,411 | 2.22x | |
| 113 | +| `z.object().safeParse` | 1,000 3-field objects | 15,740 | 7,251 | 2.17x | |
| 114 | +| `z.string().datetime().parse` | 10,000 ISO strings | 820 | 441 | 1.86x | |
| 115 | +| `z.object()` initialization | build 1,000 schemas | 12 | 7 | 1.71x | |
| 116 | +| `z.object().parse` | 1,000 3-field objects | 19,812 | 17,871 | 1.11x | |
| 117 | +| `safeParseJson` | one 4 KB nested payload | 21,433 | 21,699 | 0.99x | |
| 118 | + |
| 119 | +An op is a whole suite workload, not one value, and the workloads differ. Read |
| 120 | +each row across its two engine columns; do not compare rows to each other. |
| 121 | + |
| 122 | +The `safeParseJson` row measures `zodrs.safeParseJson(buffer)` against |
| 123 | +`zod4.safeParse(JSON.parse(json))`. At 0.99x it is a tie, and it is the one |
| 124 | +cell of the release gate that did not pass on this run: the gate requires |
| 125 | +every comparison to reach at least 1.00x. |
| 126 | + |
| 127 | +Reproduce the full gate with three runs into distinct directories, then the |
| 128 | +median-of-three comparison: |
| 129 | + |
| 130 | +```bash |
| 131 | +SUITES=object,object-safe,string,number,datetime,union,discriminated-union,array,init |
| 132 | +for i in 1 2 3; do |
| 133 | + BENCH_RESULTS_DIR=/tmp/bench$i pnpm -C packages/bench run run "$SUITES" |
| 134 | +done |
| 135 | +node packages/bench/gate.mjs /tmp/bench1 /tmp/bench2 /tmp/bench3 |
| 136 | +``` |
| 137 | + |
| 138 | +Numbers above: Node 24.18.0, Linux x64, Xeon Gold 6138, Tinybench 6.1.3. |
| 139 | +Absolute throughput depends on the machine; rerun the gate on yours. |
| 140 | + |
99 | 141 | ## Repository layout |
100 | 142 |
|
101 | 143 | | Path | Contents | |
|
0 commit comments