Zod 突然“会编译”了:速度快 9 倍、内存少近 90%,代价是 new Function?

Zod 4.5版本以Schema编译为核心突破,将验证速度提升3-9倍,内存占用降至原1/9左右,并新增z.compile()、z.withParser()等关键功能。该功能可将任意Schema转换为预编译验证器,无需额外打包步骤,在进程内完成编译,且编译结果与原Schema行为完全一致,支持延迟编译与缓存绑定以降低内存占用。经MoltarparseSafe基准测试,编译版Zod性能达到每秒4750万次操作,已超过Typia与Valibot,且处理无效输入性能可达safeParse成功值的35倍。但需注意,Zod依赖的new Function可能存在环境限制,虽可借助z.withParser()替代,但该方法不生成解析器。4.6版本进一步优化,如恢复部分功能、新增z.validate()等,其性能快照需结合实际工作负载综合判断,开发者需结合具体场景选择最佳方案。

--91likeyou---

希望将编译应用于所有 Schema 的团队,可以在入口文件顶部添加 import "zod/compile",或者运行 node --import zod/compile app.js。此后,每个 Schema 都会在首次解析数据时进行延迟编译。

通过缓存绑定方法,而不是为每个实例分别分配方法,一个空的 z.string() 现在只会保留 784 字节堆内存,而此前需要 7.5KB,内存占用大约降至原来的九分之一。safeParse() 在验证失败时也不再捕获堆栈跟踪,使拒绝无效输入的成本降低约 7.5 倍。除性能提升外,4.5 还恢复了 z.deepPartial(),并新增 .exactPartial()、z.creditCard()、z.input()/z.output()、递归 Schema 中的循环数据支持,以及八种新的错误信息语言区域。

与此最直接相关的 4.6 新功能是 .validate()。它只返回布尔值,不会构建解析结果或 ZodError,并且可以在发现第一个问题时停止验证。启用编译后,官方数据显示,在处理无效输入时,它的性能最高可达到 .safeParse().success 的 35 倍。这并不代表通用解析性能提升了 35 倍;当开发者需要转换后的输出或详细错误信息时,它也不能替代现有方法。

4.6 还增加了对类实例属性的验证、z.fromJSONSchema() 中的六个额外验证关键字,以及 z.iban()。对于内容安全策略禁止使用 z.compile() 所依赖的 new Function 的环境,开发者可以使用 z.withParser() 安装外部生成的解析器,但该方法本身不会生成解析器。

更重要的是,4.6 修复了 4.5 中的一项回归问题。该问题会让递归 Schema 持续持有已经解析的数据,并可能导致内存耗尽。

开发者 Mehul Mohan 将对象和数组上约十倍的性能提升称为“一次真正的性能突破”。

在该版本引用的 Moltar parseSafe 基准测试中,编译后的 Zod 达到每秒 4750 万次操作,略微领先每秒 4530 万次的 Typia,并将 Valibot(每秒 180 万次)和 ArkType(每秒 15.2 万次)远远甩在身后。考虑到 ArkType 长期以来一直宣传其性能比 Zod 快许多倍,这一结果尤其引人关注。不过,在随 4.5 发布的纯布尔断言基准测试中,Typia 和 ArkType 仍领先于编译后的 Zod。这些数字只是该版本发布时的性能快照,并不是针对 4.6 新增 .validate() 路径进行的最新对比;最快的选择仍然取决于具体工作负载。

Moltarbench 测试结果,来自版本发布文章。

Zod 是一个开源、以 TypeScript 为核心的验证库,用于定义 Schema,并在完整推断静态类型的同时解析不可信数据。它是 JavaScript 生态中采用范围最广的验证工具之一,获得了 tRPC、React Hook Form 和许多后端框架的一等支持,目前每周下载量已超过 3000 万次。

:

🔥 热词:#dex2oat编译会让应用的内存变大吗 · #arm编译内存seg fault