Skip to content

Commit 39f8c45

Browse files
authored
faster initialization (#5352)
* WIP * WIP * WIP * Fix lint * WIP
1 parent d3da530 commit 39f8c45

20 files changed

+229
-187
lines changed

biome.jsonc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@
7676
"experiments",
7777
"node_modules",
7878
".next",
79-
"packages/bench",
79+
8080
"packages/treeshake",
8181
".source"
8282
]

packages/bench/_temp.ts

Lines changed: 0 additions & 4 deletions
This file was deleted.

packages/bench/benchUtil.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
import * as zodNext from "../zod/src/index.js";
2-
import * as zod4 from "zod4";
31
import * as zod3 from "zod3";
2+
import * as zod4 from "zod4";
3+
import * as zodNext from "../zod/src/index.js";
44

5-
export {zod3, zod4, zodNext}
5+
export { zod3, zod4, zodNext };
66
export function makeSchema<T>(factory: (z: typeof zod4) => T) {
77
return {
88
zod3: factory(zod3 as any) as T,
Lines changed: 35 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,11 @@
11
import { makeData, randomPick, randomString } from "./benchUtil.js";
22
import { metabench } from "./metabench.js";
33

4-
54
import * as z3 from "zod/v3";
65
import * as z4 from "zod/v4";
76
import * as z4lib from "zod4/v4";
87

9-
10-
const z3fields ={
8+
const z3fields = {
119
data1: z3.string(),
1210
data2: z3.string(),
1311
data3: z3.string(),
@@ -18,42 +16,42 @@ const z3fields ={
1816
// data8: z3.string(),
1917
// data9: z3.string(),
2018
// data10: z3.string(),
21-
}
19+
};
2220
const z3Union = z3.union([
2321
z3.object({
2422
type: z3.literal("a"),
25-
...z3fields
23+
...z3fields,
2624
}),
2725
z3.object({
2826
type: z3.literal("b"),
29-
...z3fields
27+
...z3fields,
3028
}),
3129
z3.object({
3230
type: z3.literal("c"),
33-
...z3fields
31+
...z3fields,
3432
}),
3533
z3.object({
3634
type: z3.literal("d"),
37-
...z3fields
35+
...z3fields,
3836
}),
3937
z3.object({
4038
type: z3.literal("e"),
41-
...z3fields
39+
...z3fields,
4240
}),
4341
z3.object({
4442
type: z3.literal("f"),
45-
...z3fields
43+
...z3fields,
4644
}),
4745
z3.object({
4846
type: z3.literal("g"),
49-
...z3fields
47+
...z3fields,
5048
}),
5149
]);
5250

5351
const z3DiscUnion = z3.discriminatedUnion("type", z3Union._def.options);
5452

55-
function makeSchema(z: typeof z4){
56-
const z4fields = {
53+
function makeSchema(z: typeof z4) {
54+
const z4fields = {
5755
data1: z.string(),
5856
data2: z.string(),
5957
data3: z.string(),
@@ -64,56 +62,47 @@ function makeSchema(z: typeof z4){
6462
// data8: z.string(),
6563
// data9: z.string(),
6664
// data10: z.string(),
67-
}
65+
};
6866
const z4Union = z.union([
6967
z.object({
7068
type: z.literal("a"),
71-
...z4fields
69+
...z4fields,
7270
}),
7371
z.object({
7472
type: z.literal("b"),
75-
...z4fields
73+
...z4fields,
7674
}),
7775
z.object({
7876
type: z.literal("c"),
79-
...z4fields
77+
...z4fields,
8078
}),
8179
z.object({
8280
type: z.literal("d"),
83-
...z4fields
81+
...z4fields,
8482
}),
8583
z.object({
8684
type: z.literal("e"),
87-
...z4fields
85+
...z4fields,
8886
}),
8987
z.object({
9088
type: z.literal("f"),
91-
...z4fields
89+
...z4fields,
9290
}),
9391
z.object({
9492
type: z.literal("g"),
95-
...z4fields
93+
...z4fields,
9694
}),
9795
]);
9896
return z4Union;
99-
10097
}
10198

10299
const z4Union = makeSchema(z4);
103-
const z4LibUnion = makeSchema(z4lib as any);
104-
const z4LibDiscUnion = z4lib.discriminatedUnion("type", z4LibUnion._def.options as any);
100+
const z4LibUnion = makeSchema(z4lib as any);
101+
const z4LibDiscUnion = z4lib.discriminatedUnion("type", z4LibUnion._def.options as any);
105102
const z4DiscUnion = z4.discriminatedUnion("type", z4Union.def.options);
106103

107-
const DATA = makeData(100, () => ({
108-
type: randomPick([
109-
"a",
110-
"b",
111-
"c",
112-
"d",
113-
"e",
114-
"f",
115-
"g"
116-
]),
104+
const DATA = makeData(100, () => ({
105+
type: randomPick(["a", "b", "c", "d", "e", "f", "g"]),
117106
data1: randomString(10),
118107
data2: randomString(10),
119108
data3: randomString(10),
@@ -124,18 +113,16 @@ const DATA = makeData(100, () => ({
124113
// data8: randomString(10),
125114
// data9: randomString(10),
126115
// data10: randomString(10),
127-
}));
116+
}));
128117

129-
console.dir(DATA[0], {depth: null});
130-
console.dir(z3Union.parse(DATA[0]), {depth: null});
131-
console.dir(z3DiscUnion.parse(DATA[0]), {depth: null});
132-
console.dir(z4Union.parse(DATA[0]), {depth: null});
133-
console.dir(z4DiscUnion.parse(DATA[0]), {depth: null});
134-
console.dir(z4LibUnion.parse(DATA[0]), {depth: null});
135-
console.dir(z4LibDiscUnion.parse(DATA[0]), {depth: null});
118+
console.dir(DATA[0], { depth: null });
119+
console.dir(z3Union.parse(DATA[0]), { depth: null });
120+
console.dir(z3DiscUnion.parse(DATA[0]), { depth: null });
121+
console.dir(z4Union.parse(DATA[0]), { depth: null });
122+
console.dir(z4DiscUnion.parse(DATA[0]), { depth: null });
123+
console.dir(z4LibUnion.parse(DATA[0]), { depth: null });
124+
console.dir(z4LibDiscUnion.parse(DATA[0]), { depth: null });
136125

137-
138-
const args= {jitless: true}
139126
const bench = metabench("z.discriminatedUnion().parse", {
140127
// z3() {
141128
// for (const item of DATA) {
@@ -162,11 +149,11 @@ const bench = metabench("z.discriminatedUnion().parse", {
162149
z4DiscUnion.parse(item);
163150
}
164151
},
165-
"zod 4 (before)"(){
152+
"zod 4 (before)"() {
166153
for (const item of DATA) {
167154
z4LibDiscUnion.parse(item);
168155
}
169-
}
170-
})
171-
156+
},
157+
});
158+
172159
await bench.run();

packages/bench/error-handling.ts

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import { makeData } from "./benchUtil.js";
22
import { metabench } from "./metabench.js";
33

4-
import * as z4 from "zod/v4";
54
import * as z from "zod/v3";
5+
import * as z4 from "zod/v4";
66

77
const a = z4.object({ a: z4.string() });
88
const b = z.object({ a: z.string() });
@@ -12,14 +12,22 @@ const DATA = makeData(10000, () => ({ b: `${Math.random()}` }));
1212
const bench = metabench("safeparse error", {
1313
zod4() {
1414
for (const _ of DATA) {
15-
try{a.safeParse(_);} catch(e){e;}
15+
try {
16+
a.safeParse(_);
17+
} catch (_e) {
18+
_e;
19+
}
1620
}
1721
},
1822
zod4new() {
1923
for (const _ of DATA) {
20-
try{b.safeParse(_);} catch(e){e;}
24+
try {
25+
b.safeParse(_);
26+
} catch (_e) {
27+
_e;
28+
}
2129
}
22-
}
30+
},
2331
});
2432

2533
await bench.run();

packages/bench/init.ts

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
import * as z4 from "zod";
2+
import * as z3 from "zod3";
3+
import * as z4lib from "zod4";
4+
import { metabench } from "./metabench.js";
5+
6+
const DATA = Array.from({ length: 1000 }, () =>
7+
Object.freeze({
8+
number: 1,
9+
negNumber: -1,
10+
maxNumber: Number.MAX_VALUE,
11+
string: "string",
12+
longString:
13+
"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Vivendum intellegat et qui, ei denique consequuntur vix. Semper aeterno percipit ut his, sea ex utinam referrentur repudiandae. No epicuri hendrerit consetetur sit, sit dicta adipiscing ex, in facete detracto deterruisset duo. Quot populo ad qui. Sit fugit nostrum et. Ad per diam dicant interesset, lorem iusto sensibus ut sed. No dicam aperiam vis. Pri posse graeco definitiones cu, id eam populo quaestio adipiscing, usu quod malorum te. Ex nam agam veri, dicunt efficiantur ad qui, ad legere adversarium sit. Commune platonem mel id, brute adipiscing duo an. Vivendum intellegat et qui, ei denique consequuntur vix. Offendit eleifend moderatius ex vix, quem odio mazim et qui, purto expetendis cotidieque quo cu, veri persius vituperata ei nec. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.",
14+
boolean: true,
15+
deeplyNested: {
16+
foo: "bar",
17+
num: 1,
18+
bool: false,
19+
},
20+
})
21+
);
22+
23+
const bench = metabench("z.object() schema initialization (1000 schemas)", {
24+
zod3() {
25+
const schemas = [];
26+
for (let i = 0; i < 1000; i++) {
27+
const z3Schema = z3.strictObject({
28+
number: z3.number(),
29+
negNumber: z3.number(),
30+
maxNumber: z3.number(),
31+
string: z3.string(),
32+
longString: z3.string(),
33+
boolean: z3.boolean(),
34+
deeplyNested: z3.strictObject({
35+
foo: z3.string(),
36+
num: z3.number(),
37+
bool: z3.boolean(),
38+
}),
39+
});
40+
schemas.push(z3Schema);
41+
}
42+
// Use the last schema to avoid dead code elimination
43+
schemas[999].parse(DATA[0]);
44+
},
45+
zod4lib() {
46+
const schemas = [];
47+
for (let i = 0; i < 1000; i++) {
48+
const z4LibSchema = z4lib.strictObject({
49+
number: z4lib.number(),
50+
negNumber: z4lib.number(),
51+
maxNumber: z4lib.number(),
52+
string: z4lib.string(),
53+
longString: z4lib.string(),
54+
boolean: z4lib.boolean(),
55+
deeplyNested: z4lib.strictObject({
56+
foo: z4lib.string(),
57+
num: z4lib.number(),
58+
bool: z4lib.boolean(),
59+
}),
60+
});
61+
schemas.push(z4LibSchema);
62+
}
63+
// Use the last schema to avoid dead code elimination
64+
schemas[999].parse(DATA[0]);
65+
},
66+
zod4() {
67+
const schemas = [];
68+
for (let i = 0; i < 1000; i++) {
69+
const z4Schema = z4.strictObject({
70+
number: z4.number(),
71+
negNumber: z4.number(),
72+
maxNumber: z4.number(),
73+
string: z4.string(),
74+
longString: z4.string(),
75+
boolean: z4.boolean(),
76+
deeplyNested: z4.strictObject({
77+
foo: z4.string(),
78+
num: z4.number(),
79+
bool: z4.boolean(),
80+
}),
81+
});
82+
schemas.push(z4Schema);
83+
}
84+
// Use the last schema to avoid dead code elimination
85+
schemas[999].parse(DATA[0]);
86+
},
87+
});
88+
89+
await bench.run();

0 commit comments

Comments
 (0)