structuredClone 比 JSON 往返还慢一倍

举报
yd_293143657 发表于 2026/11/14 00:36:06 2026/11/14
【摘要】 线上一个订单快照函数,20 万条记录用 JSON.parse(JSON.stringify(x)) 深拷贝,一次 379 ms,高峰期把这个接口压到 4 秒。有人建议换 structuredClone,实测 683 ms,慢了一倍。最后手写逐字段拷贝,16 ms。 实验20 万个对象,每个 5 个字段(含 1 个字符串数组、1 个嵌套对象),各跑 3 轮取最快:写法耗时复制后堆增量JSON ...

线上一个订单快照函数,20 万条记录用 JSON.parse(JSON.stringify(x)) 深拷贝,一次 379 ms,高峰期把这个接口压到 4 秒。有人建议换 structuredClone,实测 683 ms,慢了一倍。最后手写逐字段拷贝,16 ms。

实验

20 万个对象,每个 5 个字段(含 1 个字符串数组、1 个嵌套对象),各跑 3 轮取最快:

写法 耗时 复制后堆增量
JSON 往返 379.5 ms 38.2 MB
structuredClone 682.8 ms 51.9 MB
手写逐字段 16.3 ms 30.5 MB

手写比 JSON 快 23 倍。这不是手写优化得好,是另外两种被迫做通用工作。

为什么 structuredClone 最慢

它走的是结构化克隆算法:每个值都要查类型、按表分派,还必须支持循环引用、Map/Set、ArrayBuffer、Transferable、Blob/File,于是它不能假设「你这就是一个普通对象数组」。每个节点走一套通用分支,还要维护一张 seen 映射表来处理循环引用——这也是它内存多出 12 MB 的原因。

JSON 往返看起来很笨(先变字符串再解析),但 JSON.stringify / JSON.parse 都是原生实现:序列化是顺序写 buffer,解析有专门的快速路径。代价是多付一次编码加一次解码的字节搬运。

手写版本没有分派:字段形状固定,偏移已知,循环体里就是几条赋值。

数值数据反过来

数据 方式 耗时
Float64Array 400 万 structuredClone 17.8 ms
Float64Array 400 万 slice() 8.3 ms
普通数组 400 万 structuredClone 202.5 ms
普通数组 400 万 JSON 往返 436.3 ms

typed array 的克隆是整块 memcpy,两种方案都快;普通数组装 400 万个数字,JSON 要写 400 万段十进制文本再逐个解析。同一份数据,容器选错,深拷贝慢 25 倍。

语义:不是所有东西都能用 JSON 拷

值类型 JSON 往返 structuredClone
Date 变成字符串 保留 Date
undefined 字段 整个字段消失 保留
Map / Set 变成空对象 保留
BigInt 抛 TypeError 保留
类实例 丢原型 丢原型
循环引用 抛 TypeError 支持
函数 / Symbol 静默丢弃 抛 DataCloneError

注意最后两行:structuredClone 不是什么都拷得动,函数直接抛错;JSON 是悄悄扔掉。两种失败方式各有坑——丢字段让下游拿到 undefined,抛错至少当场炸。

两者都不保留原型,克隆后 instanceof 一律为 false。要保留类型只能手写,或者自己写工厂函数。

结论

  1. 拷贝固定形状的业务对象,手写逐字段。20 万条 16 ms 与 379 ms 是数量级差别。
  2. 需要通用深拷贝、数据里有 Date/Map/循环引用,用 structuredClone,接受它慢,别放在热路径上。
  3. 只做传输、能接受类型丢失,JSON 往返仍是兼容性最好的选择。
  4. 大块数字用 Float64Array,克隆就是 memcpy,slice() 还比 structuredClone 快一倍。
  5. 判断标准不是哪个 API 更现代,而是要拷的是不是同一形状的对象。

数据来自 Node 24.22.1 / Windows,--expose-gc --max-old-space-size=8192。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。