modern 发表于 2009-12-2 20:21:03

Google protobuf使用中的小陷阱

在使用Protobuf中,发现对大数据包进行反序列化的的时候,
在数据包大于1m之后,随着数据包大小的线性增长,
反序列化的时间的增长幅度近乎斜率为2,这显然是难以忍受的。
下面是测试数据
500k 0.5s
1m2.2s
2m 8s
3m 12s

于是在对Protobuf不断进行测试后发现,
在由于在被编译平proto文件中进行了类似如下设置如:
required string sname = 1 ;
required string sAddr= 2 ;
因此认为在对象构造的时候,sname字段将自动初始化为"lily",sAddr将自动初始化为"";
序列化与反序列放心的去使用通用的版本如ParseFromArray,
而非带有Partial字样的版本如ParsePartialFromArray。

后查看生成的代码发现实际上并不是这样,sname字段确实自动初始化为"lily",sAddr确没有被初始化。
因此在反序列化的时候由于检查字段缺失,会造成相当明显的时间损失。
经测试,即使近缺少这样一个字段的初始化,造成4-5倍的时间的损失是很平常的。
很不幸,我将这样的类定义在了一个list(repeated字段)里面,因此带来的时间损失更为严重。

测试手动对生成代码中未默认初始化的字段进行赋值,其他默认已经初始化的字段不做任何设置,
之后进行反序列化,下面是测试结果:
2M 0.32s
4m 0.65s
8m 1.2s
40m 7s
基本上反序列化的时间是随数据包增大程线性增长的,这是我们预期的结果。

结论,在编译proto的时候,如果string类型默认设置为"",一定要记得手动初始化。
目前使用版本为protoc-2.1.0-win32,也许接下来的版本会修正该bug。

wgm001 发表于 2009-12-23 10:06:06

不错,学习了。。。。

Derek 发表于 2011-1-18 11:46:25

学习学习!
页: [1]
查看完整版本: Google protobuf使用中的小陷阱