首页 > 代码库 > Protocol buffers--python 实践(二) protocol buffers vs json

Protocol buffers--python 实践(二) protocol buffers vs json

为什么专门开一个坑,来使用pb。放弃本在各平台上都支持得很好的json而使用pb的一个归根到底的理由,就是希望在保证强类型和跨平台的情况下,能够更轻,更快,更简单。既然是奔着这个目标去的,到底多快我需要一个合理的解释。

 

在使用pure python官方库的的情况下,对比了pb和json标准库,还有simplejson库的速度。

使用的.proto文件文件如下:

syntax = "proto2";

package hello_word;

message SayHi {
    required int32 id = 1;
    required string something = 2;
    optional string extra_info = 3;
}

python文件可以根据这个生成对应的SayHi obejct。

 

测试各库序列化速度的代码如下所示:

# coding: utf-8
import timeit


# 序列化
x = """
say_hi.SerializeToString()
"""

y = """
json.dumps(ppa)
"""

z = """
simplejson.dumps(pl)
"""

print min(timeit.repeat(stmt=x, setup="import say_hi_pb2;"
                                  "say_hi = say_hi_pb2.SayHi();"
                                  "say_hi.id = 13423;"
                                  "say_hi.something = ‘axiba‘;"
                                  "say_hi.extra_info = ‘xiba‘;", repeat=5, number=100000))

print min(timeit.repeat(stmt=y, setup="import json; "
                                  "ppa={"
                                  "‘id‘: 13423,"
                                  "‘something‘: ‘axiba‘,"
                                  "‘extra_info‘: ‘xiba‘,"
                                  "};", repeat=5, number=100000))

print min(timeit.repeat(stmt=z, setup="import simplejson; "
                                  "pl={"
                                  "‘id‘: 13423,"
                                  "‘something‘: ‘axiba‘,"
                                  "‘extra_info‘: ‘xiba‘,"
                                  "};", repeat=5, number=100000))

输出:

1.08438277245
0.398800134659
0.707333087921

测试各库反序列化速度的代码如下所示:

# coding: utf-8
import timeit

# 反序列化
x = """
say_hi.ParseFromString(p)
"""
y = """
json.loads(p1)
"""
z = """
simplejson.loads(p2)
"""


print min(timeit.repeat(stmt=x, setup="import say_hi_pb2;"
                                  "say_hi = say_hi_pb2.SayHi();"
                                  "say_hi.id = 13423;"
                                  "say_hi.something = ‘axiba‘;"
                                  "say_hi.extra_info = ‘xiba‘;"
                                  "p = say_hi.SerializeToString()", repeat=5, number=100000))

print min(timeit.repeat(stmt=y, setup="import json; "
                                  "ppa={"
                                  "‘id‘: 13423,"
                                  "‘something‘: ‘axiba‘,"
                                  "‘extra_info‘: ‘xiba‘,"
                                  "};"
                                  "p1 = json.dumps(ppa)", repeat=5, number=100000))

print min(timeit.repeat(stmt=z, setup="import simplejson; "
                                  "pl={"
                                  "‘id‘: 13423,"
                                  "‘something‘: ‘axiba‘,"
                                  "‘extra_info‘: ‘xiba‘,"
                                  "};"
                                  "p2 = simplejson.dumps(pl)", repeat=5, number=100000))
输出:

0.924090862274
0.492631912231
0.283575057983

从上面的数据可以看出,在我使用的版本3.1.0.post1的情况下,纯python实现pb序列化的速度略慢于json原生库两倍多,比simplejson库慢百分之30。在反序列化的速度测试中,依然是pb速度最慢两倍慢于原生json库,慢于simplejson库3倍多。这样看起来差距似乎被优化得不那么大了。记得以前在使用pb2.x库的时候,python序列化常慢于simplejson 3倍以上是非常正常的事情。各分析性能的文章都可以看到 too slow这个描述。由于二进制存储,以及pb独特的编码二进制的方式,从大小的角度来说,pb远远小于json,但是速度连json都快不过,我们有什么理由放弃使用方便可依赖的json转而使用pb呢?这的确没有什么说服力。

 

然而,pb官方提供了一个c++实现 runtime for python,按照实践一中的方法,安装好最新的pb库,并且按照文档编译好,然后安装python 的c++实现,就可以让pb使用c++实现进行序列化反序列。其他生成代码之类的所有不用变,调用代码也不用变,只需要安装好就可以了。安装好之后可以看到

Using /Users/piperck/Desktop/grpc/lib/python2.7/site-packages
Finished processing dependencies for protobuf==3.1.0

再次使用pip list查看我们的pb的时候可以发现,已经被该库替代。

 

让我们来重新运行一下 序列化和反序列化的代码:

序列化输出:
0.085785150528
0.403172016144
0.755691051483

反序列化输出:
0.090231180191
0.499733924866
0.297739028931

可以看到几乎比pure python的实现快近10倍。如果把序列化和反序列按照一次计算进行计算的话,也比我们通常使用的simplejson库快上4到5倍。再频繁调用序列化反序列化的应用中,可以说还是比较大的性能提升了,可以使得你的代码更轻更快,而且强类型映射可以检查错误。

 

别以为到这里就完了。还有一个更快速的库,但是现在只支持proto2,叫Pyrobuf Library。基于cPython实现,根据作者的说法,他要比c++ backend for python 还要快上2-4倍。这个由于我安装了半天没有安装上,貌似是cPython库的配置稍为有点问题,如果大家对速度有更快的要求,可以查看reference给出的第二个链接,去探索一下。

 

Reference:

https://github.com/google/protobuf/tree/master/python  pb-github库

https://github.com/appnexus/pyrobuf  Pyrobuf Library

 

<style>p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 32.0px "Helvetica Neue"; color: #333333; background-color: #ffffff } span.s1 { }</style>

Protocol buffers--python 实践(二) protocol buffers vs json