AI Pulse

Go 1.27 序列化旧结构体反慢1.5倍,官方称性能持平实测不然

Go 1.27 序列化旧结构体反慢1.5倍,官方称性能持平实测不然

三种配置

Go 1.27 在标准库里默认提供了一个新的 JSON 包:encoding/json/v2。它跟旧的 encoding/json 不能直接替换。两者在 Unicode 验证、大小写敏感等方面有差异,迁移前要确认兼容性。

新引擎没有彻底取代旧的。原来的 encoding/json 也基于新引擎重写,但可用 GOEXPERIMENT=nojsonv2 切回旧引擎。这样就有三种可测配置。原始实现是旧 API 配旧引擎。Go 1.27 默认状态是旧 API 配新引擎。第三种是直接使用 json/v2。

测试在 Apple M4 Max 和 Intel Xeon Gold 6548N 上运行,用 Go 1.27.0,单核,取八次中位数。测试数据是 simdjson 常用的三个文档。twitter.json 632 kB,短字符串 key 的嵌套对象。citm_catalog.json 1.73 MB,数字 key 的嵌套对象。canada.json 2.25 MB,单一的大型坐标数组。

只升级,不改代码

把旧 API 跑在新引擎上,unmarshal 有快有慢。twitter.json 从 172 提到 203 MB/s。citm_catalog.json 从 186 提到 241 MB/s。canada.json 从 128 降到 106 MB/s。marshal 在 twitter.json 上从 198 提到 374 MB/s,接近两倍。

所以只升级 Go 版本、不改一行代码,marshal 通常会变快。unmarshal 则看数据结构,大型数组场景会慢下来。

新 API 的取舍

切到 encoding/json/v2,效果更明显。相比原始实现,unmarshal 快 1.5 到 2.3 倍,marshal 快 1.2 到 3 倍。相比 Go 1.27 默认的旧 API,unmarshal 再快 1.8 到 2 倍。marshal 只提升 1.0 到 1.7 倍,因为 json/v2 在 marshal 时做了更少的事。

情况并非单向。作者还测试了 10,000 个小结构体的往返编解码。unmarshal 仍然是新 API 快,marshal 却回到了旧 API 配旧引擎更快。新 API 在这个场景里比原始实现慢约 1.5 倍。新引擎把性能集中在解析和动态类型数据(any)上。序列化固定结构的数据时,反而不如旧引擎。

官方声明与实测

Go 1.27 发布说明声称 marshal 性能大致与此前实现持平。这次测试显示并非如此。对动态数据确实持平甚至更快,但对有类型结构体,差距达到 1.5 倍。

以解析为主的负载,json/v2 全面加速。大量序列化有固定结构的对象时,旧引擎仍然最快。

阅读原文
📚 相关主题 Go编程开发性能测试

订阅 AI Pulse

每天 08:00 · 12:30 · 18:30 · 23:50 更新