序列化库在网络传输,RPC,数据库访问等环境中经常用到,它的性能的好坏直接影响着整个产品的性能。
本文列出了几种高性能的Go语言的序列化库,并通过一个简单的无循环引用的数据结构测试它们的性能。
测试代码: gosercomp at github
03/14/2016 更新。 增加Thrift/Avro/Gencode的性能比较。
测试的 Serializers
以golang自带的encoding/json和encoding/xml为基准,测试以下性能比较好的几种序列化库。
- encoding/json
- encoding/xml
- github.com/youtube/vitess/go/bson
- github.com/tinylib/msgp
- github.com/golang/protobuf
- github.com/gogo/protobuf
- github.com/google/flatbuffers
- Apache/Thrift
- Apache/Avro
排除的 Serializers
基于 alecthomas 已有的测试,下面的库由于性能的原因没有进行测试。
- encoding/gob
- github.com/alecthomas/binary
- github.com/davecgh/go-xdr/xdr
- github.com/ugorji/go/codec
- labix.org/v2/mgo/bson
- github.com/DeDiS/protobuf
- gopkg.in/vmihailenco/msgpack.v2
测试环境
add ./bin
into the PATH
environment variable.
- 对于
github.com/youtube/vitess/go/bson
,你可能需要安装goimports
和codegen
:
|
|
- 对于
MessagePack
,你需要安装库以及利用go generate
生成相关的类:
|
|
- 对于
ProtoBuf
,你需要安装protoc编译器,以及protoc库以及生成相关的类:
|
|
- 对于
gogo/protobuf
,你需要安装库以及生成相关的类:
|
|
- 对于
flatbuffers
,你需要安装thrift编译器, 以及flatbuffers库:
|
|
- 对于
thrift
,你需要安装flatbuffers编译器, 以及thrift库:
|
|
- 对于
Avro
,你需要安装goavro库:
|
|
- 对于
gencode
,你需要安装gencode库,并使用gencode库的工具产生数据对象:
|
|
事实上,这里通过
go generate
生成相关的类,你也可以通过命令行生成,请参考data.go
中的注释。 但是你需要安装相关的工具,如Thrift,并把它们加入到环境变量Path中
运行下面的命令测试:
|
|
测试数据
所有的测试基于以下的struct,自动生成的struct, 比如protobuf也和此结构基本一致。
|
|
性能测试结果
以下性能的测试结果是在我的T430u/Windows 10上的测试结果。
|
|
多次测试结果差不多。 从结果上上来看, MessagePack,gogo/protobuf,和flatbuffers差不多,这三个优秀的库在序列化和反序列化上各有千秋,而且都是跨语言的。 从便利性上来讲,你可以选择MessagePack和gogo/protobuf都可以,两者都有大厂在用。 flatbuffers有点反人类,因为它的操作很底层,而且从结果上来看,序列化的性能要差一点。但是它有一个好处,那就是如果你只需要特定的字段, 你无须将所有的字段都反序列化。从结果上看,不反序列化字段每个调用只用了9.54纳秒,这是因为字段只有在被访问的时候才从byte数组转化为相应的类型。 因此在特殊的场景下,它可以提高N被的性能。但是序列化的代码的面相太难看了。
新增加了gencode的测试,它表现相当出色,而且生成的字节也非常的小。
官方的Protobuf是通过反射(reflect)实现序列化反序列化的,所以效率不是很高。而gogo/protobuf则是在代码生成的时候提供了Marshal/UnMarshal的方法,它不采用反射的方式,所以性能上比官方的库要好很多。