在Go项目里,序列化常用于网络传输和持久化存储。不同的序列化格式在速度和体积上差异明显,使用Golang的基准测试能帮我们客观比较它们。下面直接通过示例来看如何实现。

准备测试用的数据结构
先定义一个简单的用户结构体,用于各种序列化方案的编码和解码。
package main
type User struct {
ID int64 `json:"id" protobuf:"varint,1,opt,name=id"`
Name string `json:"name" protobuf:"bytes,2,opt,name=name"`
Age int32 `json:"age" protobuf:"varint,3,opt,name=age"`
}
编写各序列化方案的Benchmark
我们使用标准库的testing包来写基准函数。以下示例对比了JSON、Gob和Protocol Buffers。
JSON与Gob基准测试
import (
"encoding/gob"
"encoding/json"
"testing"
)
func BenchmarkJSONMarshal(b *testing.B) {
u := User{ID: 1, Name: "test", Age: 20}
b.ResetTimer()
for i := 0; i < b.N; i++ {
_, err := json.Marshal(u)
if err != nil {
b.Fatal(err)
}
}
}
func BenchmarkGobMarshal(b *testing.B) {
u := User{ID: 1, Name: "test", Age: 20}
b.ResetTimer()
for i := 0; i < b.N; i++ {
// gob需要注册类型并使用buffer
var buf bytes.Buffer
enc := gob.NewEncoder(&buf)
err := enc.Encode(u)
if err != nil {
b.Fatal(err)
}
}
}
Protocol Buffers基准测试
使用protobuf前需要通过protoc生成Go代码,假设已生成user.pb.go。
import (
"testing"
pb "ippipp.com/project/userpb"
)
func BenchmarkProtoMarshal(b *testing.B) {
u := &pb.User{Id: 1, Name: "test", Age: 20}
b.ResetTimer()
for i := 0; i < b.N; i++ {
_, err := proto.Marshal(u)
if err != nil {
b.Fatal(err)
}
}
}
运行与对比Benchmark
在终端执行以下命令运行所有基准测试并查看结果:
go test -bench=. -benchmem
输出类似下表,可直观对比不同方案:
| 方案 | 每操作耗时 | 内存分配 |
|---|---|---|
| JSON | 约 200ns/op | 约 120B/op |
| Gob | 约 300ns/op | 约 200B/op |
| Protobuf | 约 80ns/op | 约 40B/op |
结论与建议
通过Golang的benchmark,我们可以清楚看到Protobuf在速度和体积上通常优于JSON和Gob。如果服务间通信追求高性能,建议选用Protobuf;若只是简单配置读写,JSON更易调试。实际选型应结合跑分数据与业务场景。