博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Protocol buffers--python 实践(二) protocol buffers vs json
阅读量:5967 次
发布时间:2019-06-19

本文共 5310 字,大约阅读时间需要 17 分钟。

为什么专门开一个坑,来使用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-8import 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-8import 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.0857851505280.4031720161440.755691051483反序列化输出:0.0902311801910.4997339248660.297739028931

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

 

别以为到这里就完了。还有一个更快速的库,但是现在只支持proto2,叫Pyrobuf Library。基于cPython实现,根据作者的说法,他要比c++ backend for python 还要快上2-4倍。让我们来尝试一下。

首先安装一下: 

pip install pyrobuf

如果不行可以尝试使用:

pip install pyrobuf -v -v -v --upgrade --force --no-cache

安装好之后,按照官网的提示,使用pyrobuf 的 cli命令行界面,对.proto文件进行编译,得到.pxd和.pyx文件,还有.o和.c还有.so的文件(注意他们需要在同一个文件夹下)。

 一切完成之后书写代码 测试速度:

import timeito = """p.SerializeToString()"""print min(timeit.repeat(stmt=o, setup=                        "from hello_world_say_hi_proto import SayHi;"                        "p = SayHi();"                        "p.id = 3;"                        "p.something = 'axiba';"                        "p.extra_info = 'xiba'", repeat=5, number=100000))o = """p.ParseFromString(oi)"""print min(timeit.repeat(stmt=o, setup=                        "from hello_world_say_hi_proto import SayHi;"                        "p = SayHi();"                        "p.id = 3;"                        "p.something = 'axiba';"                        "p.extra_info = 'xiba';"                        "oi = p.SerializeToString()", repeat=5, number=100000)) 输出:

0.069412946701

0.0525119304657

对比上面使用c++ backend的pb来看,反序列化勉强快到2倍,而序列化几乎没有什么特别大的优势。可能得益于使用最新版pb3.10的关系,在google的不断优化下,已经没有那么大差距了吧。因为使用cPython比较麻烦,还会多出不少编译文件。所以没什么提升的情况下,按照个人的需求使用吧。

 

Reference:

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

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

http://techblog.appnexus.com/blog/2015/12/22/pyrobuf-a-faster-python-protobuf-library-written-in-cython/  pyrobuf-a-faster-python-protobuf-library-written-in-cython

 

转载地址:http://hxmax.baihongyu.com/

你可能感兴趣的文章
git配置别名
查看>>
SpringMVC配置文件
查看>>
划分数系列问题
查看>>
springboot整合jersey
查看>>
sql定时自动备份(定时作业)
查看>>
Excel 2013 表格自用技巧
查看>>
浅析支付系统的整体架构
查看>>
二位数组
查看>>
unix文件权限
查看>>
Python 模拟鼠键
查看>>
2017-2018-2 20155224『网络对抗技术』Exp7:网络欺诈防范
查看>>
Source Code Review
查看>>
分享一下我安装启动Jmeter出错时的解决办法
查看>>
java 调用process
查看>>
用a标签实现submit提交按钮的效果
查看>>
毕向东_Java基础视频教程第20天_IO流(1~4)
查看>>
几图理解BeautifulSoup
查看>>
HashMap内部是如何实现的(转)
查看>>
交互设计[3]--点石成金
查看>>
java实现双向循环链表
查看>>