Skip to content

Commit 7120fd9

Browse files
committed
docs: add measured benchmarks to README
Median of three full bench runs against Zod v4.4.3 on the native tier, with the workload per op and the reproduction command. The 4 KB safeParseJson comparison is reported at 0.99x, the one release-gate cell that did not pass on this run.
1 parent f14aa81 commit 7120fd9

1 file changed

Lines changed: 42 additions & 0 deletions

File tree

README.md

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
[![License](https://img.shields.io/badge/license-MIT-blue.svg)](#license)
99
[![Node](https://img.shields.io/badge/node-%3E%3D20.17-informational.svg)](https://nodejs.org)
1010

11+
[Benchmarks](#benchmarks) •
1112
[Behavior contract](docs/CONTRACT.md) •
1213
[Divergences](docs/DIVERGENCE.md) •
1314
[Dependency rationale](docs/DEPENDENCIES.md)
@@ -96,6 +97,47 @@ normal use.
9697

9798
The suite runs all four lanes. Each passes 5,679 tests across 435 files.
9899

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+
99141
## Repository layout
100142

101143
| Path | Contents |

0 commit comments

Comments
 (0)