使用Protocol Buffers的C语言拓展提速Python程序的示例


Posted in Python onApril 16, 2015

 Protocol Buffers (类似XML的一种数据描述语言)最新版本2.3里,protoc—py_out命令只生成原生的Python代码。 尽管PB(Protocol Buffers)可以为C++语言生成快速解析和序列化代码,但是这种方式对于Python不适用,并且手动生成的已包装的代码需要非常大的维护工作。在讨论组里,这是一个常见的功能要求,由于一个必备的客户端组件—AppEngine(根据团队介绍名称为AppEngine),生成原生的Python代码有更高的优先级。

幸运的是, PB 2.4版本中本地化代码已被提名,在 svn的分支中已经可以下载,因此你能够使用快速的 PB有一段时间了。 (我们使用 r352版本有一段时间了,还没有遇到任何问题。) PB团队一直不愿轻易指定任何发布日期,在我的威胁下, Kenton Varda提到日期初步定在 2011年初。

我没有在其它地方看见过这个文档,希望它能对其他人有所帮助.

如何做能让它快起来

安装好新的PB库之后并使用 protoc --py_out=...  重新构建好你的PB之后,你需要在运行你的Python程序之前进行环境变量 PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION=cpp 的设置,以便于选择C++的,或者PB默认使用的Python实现.

就这样了!这至少就能在可以动态转化/序列化消息的PB运行时库用通用的C++代码了. (注意我们还没有生成任何C++代码.)

它能有多快呢? 我编写了一个简单的程序来获得性能在我们的应用程序中的提升感观:
 

nruns = 1000nwarmups = 100xs = ... # your protobufsdef ser(): return [x.SerializeToString() for x in xs]def parse(ys): for y in ys: pb.Email().ParseFromString(y)
 
t = timeit.Timer(lambda:None)
t.timeit(nwarmups)print 'noop:', t.timeit(nruns) / nruns
 
t = timeit.Timer(ser)
t.timeit(nwarmups)print 'ser:', t.timeit(nruns) / nruns / len(xs)
 
ys = ser()
t = timeit.Timer(lambda: parse(ys))
t.timeit(nwarmups)print 'parse:', t.timeit(nruns) / nruns / len(xs)print 'msg size:', sum(len(y) for y in ys) / len(ys)

以秒为单位,这段程序在我的桌面上给出了如下几个时间结果:
 

$ python sandbox/pbbench.py out.ini
ser: 0.000434461673101
parse: 0.000602062404156
msg size: 10730
 
$ PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION=cpp \
> python sandbox/pbbench.py out.ini
ser: 2.86788344383e-05
parse: 7.63910810153e-05
msg size: 10730

这显示出在序列化和转化方面分别有15和8被的速度提升。不坏!但还可以更快.

如何做让它更快

现在我们实际上只是特地针对你的PB生成了一个C++实现,而我们从来没有使用过运行时反射。首先,为你的Python项目添加一个C扩展,不如,通过修改如下的 setup.py:
 

setup(
  ...
  ext_modules=[Extension('podpb',
sources=['cpp/podpb.c','cpp/main.pb.cc'], libraries=['protobuf'])],
  ...
  )

使用 protoc --cpp_out=cpp 生成main.pb.c, 并按如下所示创建 podpb.c 来设置一个空的 Python C 模块:
 

#include <Python.h>
 
static PyMethodDef PodMethods[] = {
 {NULL, NULL, 0, NULL}    /* Sentinel */};
 
PyMODINIT_FUNC
initpodpb(void)
{
 PyObject *m;
 
 m = Py_InitModule("podpb", PodMethods); if (m == NULL)  return;
}

现在就运行 python setup.py build 命令会构建所有的东西. 只要将C模块(在这里是podpb)导入到你的项目中,PB 运行时库就将会自动使用 C++ 实现了.

现在我们就分别有了68倍x 和 13倍 的速度提升. 吼吼.
 

$ PYTHONPATH=build/lib.linux-x86_64-2.6/:$PYTHONPATH \
> PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION=cpp \
> python sandbox/pbbench.py out.ini
ser: 6.39575719833e-06
parse: 4.55250144005e-05
msg size: 10730

我这篇文章发布到很多地方,大事完全忘了它的存在。同时 connex.io 和 Greplin 发布了他们的原生的 Python实现,cypb和fast-python-pb。cypb在PB的邮件列表中公布过,可以运行,但仍需要提升到可用的状态。fast-python-pb目前只支持string int32, int64 双精度浮点和子消息成员。除了这些项目,其他的我都不了解。你也可以查看我的orginal thread PB邮列表来了解到这些。

Python 相关文章推荐
Python中用于去除空格的三个函数的使用小结
Apr 07 Python
Python使用scrapy采集时伪装成HTTP/1.1的方法
Apr 08 Python
python清除指定目录内所有文件中script的方法
Jun 30 Python
使用python爬虫实现网络股票信息爬取的demo
Jan 05 Python
Windows下安装Django框架的方法简明教程
Mar 28 Python
利用Python实现原创工具的Logo与Help
Dec 03 Python
Python实现DDos攻击实例详解
Feb 02 Python
Django 拆分model和view的实现方法
Aug 16 Python
python实现七段数码管和倒计时效果
Nov 23 Python
基于pygame实现童年掌机打砖块游戏
Feb 25 Python
python手机号前7位归属地爬虫代码实例
Mar 31 Python
python实现学生信息管理系统源码
Feb 22 Python
使用Python编写一个模仿CPU工作的程序
Apr 16 #Python
利用Python中的mock库对Python代码进行模拟测试
Apr 16 #Python
使用Python脚本来控制Windows Azure的简单教程
Apr 16 #Python
在Python下利用OpenCV来旋转图像的教程
Apr 16 #Python
在Python中使用Neo4j数据库的教程
Apr 16 #Python
使用Python的Zato发送AMQP消息的教程
Apr 16 #Python
scrapy自定义pipeline类实现将采集数据保存到mongodb的方法
Apr 16 #Python
You might like
求PHP数组最大值,最小值的代码
2011/10/31 PHP
浅析THINKPHP的addAll支持的最大数据量
2015/02/03 PHP
PHP多维数组元素操作类的方法
2016/11/14 PHP
Yii框架弹出窗口组件CJuiDialog用法分析
2017/01/07 PHP
phpstudy默认不支持64位php的解决方法
2017/02/20 PHP
PHP实现的解汉诺塔问题算法示例
2018/08/06 PHP
JSON扫盲帖 JSON.as类教程
2009/02/16 Javascript
同一个表单 根据要求递交到不同页面的实现方法小结
2009/08/05 Javascript
用js实现层随着内容大小动态渐变改变 推荐
2009/12/19 Javascript
jQuery实现 注册时选择阅读条款 左右移动
2013/04/11 Javascript
javascript计算用户打开网页的停留时间
2014/01/09 Javascript
JS实现鼠标滑过折叠与展开菜单效果代码
2015/09/06 Javascript
jQuery实现批量判断表单中文本框非空的方法(2种方法)
2015/12/09 Javascript
JavaScript 2048 游戏实例代码(简单易懂)
2016/03/25 Javascript
javascript 常用验证函数总结
2016/06/28 Javascript
原生js实现addclass,removeclass,toggleclasss实例
2016/11/24 Javascript
jQuery第一次运行页面默认触发点击事件的实例
2018/01/10 jQuery
如何用RxJS实现Redux Form
2018/12/29 Javascript
jQuery实现适用于移动端的跑马灯抽奖特效示例
2019/01/18 jQuery
JS中的一些常用的函数式编程术语
2019/06/15 Javascript
Python的Django中django-userena组件的简单使用教程
2015/05/30 Python
python目录与文件名操作例子
2016/08/28 Python
python使用turtle绘制分形树
2018/06/22 Python
python matplotlib库绘制散点图例题解析
2019/08/10 Python
Python Multiprocessing多进程 使用tqdm显示进度条的实现
2019/08/13 Python
详解Python在使用JSON时需要注意的编码问题
2019/12/06 Python
python 识别登录验证码图片功能的实现代码(完整代码)
2020/07/03 Python
详解python的super()的作用和原理
2020/10/29 Python
Python自动化办公Excel模块openpyxl原理及用法解析
2020/11/05 Python
HTML5是什么 HTML5是什么意思 HTML5简介
2012/10/26 HTML / CSS
大学生毕业自我鉴定
2013/11/06 职场文书
管理部副部长岗位职责范文
2014/03/09 职场文书
宣传活动总结范文
2014/07/01 职场文书
初中军训感想
2015/08/07 职场文书
Python OpenCV超详细讲解读取图像视频和网络摄像头
2022/04/02 Python
Golang 切片(Slice)实现增删改查
2022/04/22 Golang