要验证 json 序列化性能,需编写基准测试并对比不同库的表现。具体步骤为:1. 使用 func benchmarkxxx(b *testing.b) 定义测试函数,例如测试标准库 encoding/json 的 marshal 函数;2. 通过运行 go test -bench=. -benchmem 命令获取执行时间(ns/op)、内存分配(b/op)及 gc 压力(allocs/op)等指标;3. 对比多个库如 json-iterator/go、easyjson 或 simdjson-go 在上述指标上的表现;4. 根据实际需求选择库:追求极致性能选 easyjson 或 simdjson-go,兼容性优先选 json-iterator/go,要求维护成本低则用标准库。选择时还需考虑数据结构复杂度、字段内容及测试细节如是否使用 -benchmem 参数等。
验证 JSON 序列化性能,其实就是在测试不同 Go 语言中 JSON 编解码库在处理结构体转为 JSON 字符串时的速度和资源消耗。常见的做法是用 Go 自带的
testing/benchmark
工具写基准测试(benchmark),然后对比多个第三方库如
json-iterator/go
、
easyjson
或者
simdjson-go
等的表现。
如何编写一个基本的 Benchmark 测试
你可以通过
func BenchmarkXXX(b *testing.B)
的方式来定义一个基准测试函数。比如测试标准库
encoding/json
:
func BenchmarkJsonMarshal(b *testing.B) { type User struct { Name string Age int } u := User{Name: "Alice", Age: 30} for i := 0; i < b.N; i++ { _, _ = json.Marshal(u) } }
这个测试会运行多次(b.N 是自适应的次数),最终输出每次操作的平均耗时(ns/op)、内存分配次数和大小等信息。
立即学习“go语言免费学习笔记(深入)”;
如果你要测试多个库,可以分别写不同的 benchmark 函数,例如
BenchmarkJsonIterMarshal
、
BenchmarkEasyJsonMarshal
等。
常见对比指标有哪些?
做性能对比时,不能只看“时间”,还要关注以下几点:
- 执行时间(ns/op):越小越好,代表单次操作的平均耗时。
- 内存分配(B/op):序列化过程中申请了多少内存,越少越好。
- GC 压力(allocs/op):每次操作产生了多少次内存分配,影响 GC 频率。
- 代码可读性 & 易用性:有些库虽然快,但需要预生成代码或者使用非标准接口。
举个例子:
BenchmarkJsonMarshal-8 500000 250 ns/op 96 B/op 2 allocs/op BenchmarkJsoniterMarshal-8 1000000 150 ns/op 0 B/op 0 allocs/op
从上面可以看出,
jsoniter
比标准库更快,而且没有产生额外的内存分配。
怎么选库?简单建议如下:
- 如果你追求极致性能,且数据结构相对固定,可以用
easyjson
或
simdjson-go
,它们通常比标准库快很多。
- 如果希望兼容性好又不想改太多代码,推荐
json-iterator/go
,它几乎可以直接替换标准库。
- 如果你的项目本身对性能要求不高,直接用标准库即可,维护成本最低。
几个实际选择场景:
- API 接口返回大量结构体 → 优先考虑低内存分配的库。
- 内部日志或消息中间件 → 可以接受稍慢一点,但更稳定的库。
- 数据量小且调用频率低 → 标准库足够。
一些容易忽略的小细节
- 要注意测试对象是否是“零值”结构体,有些库在处理空字段时优化更好。
- 如果结构体中有指针嵌套或者 Interface{},不同库的表现差异可能更大。
- 使用
-benchmem
参数才能看到内存分配情况,否则默认不显示。
比如运行命令:
go test -bench=. -benchmem
另外,别忘了在跑 benchmark 之前先
go test -run=XXX
来跳过单元测试,避免干扰结果。
基本上就这些了。写 benchmark 不难,但要想测得准确、有参考价值,还是得多注意细节。