使用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中的RSS处理
Apr 13 Python
实例说明Python中比较运算符的使用
May 13 Python
Django中的CACHE_BACKEND参数和站点级Cache设置
Jul 23 Python
将Python代码嵌入C++程序进行编写的实例
Jul 31 Python
使用Python下载歌词并嵌入歌曲文件中的实现代码
Nov 13 Python
python遍历 truple list dictionary的几种方法总结
Sep 11 Python
python的random模块及加权随机算法的python实现方法
Jan 04 Python
Python-OpenCV基本操作方法详解
Apr 02 Python
Python常用的json标准库
Feb 19 Python
wxPython绘图模块wxPyPlot实现数据可视化
Nov 19 Python
Python3.x+pyqtgraph实现数据可视化教程
Mar 14 Python
使用tkinter实现三子棋游戏
Feb 25 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 chmod 函数与批量修改文件目录权限
2010/05/10 PHP
codeigniter框架批量插入数据
2014/01/09 PHP
php cookie名使用点号(句号)会被转换
2014/10/23 PHP
php获取当前url地址的方法小结
2017/01/10 PHP
jQuery图片播放8款精美插件分享
2013/02/17 Javascript
简单的Jquery遮罩层代码实例
2013/11/14 Javascript
jquery 实现返回顶部功能
2014/11/17 Javascript
JQuery实现鼠标滚轮滑动到页面节点
2015/07/28 Javascript
JavaScript的变量声明提升问题浅析(Hoisting)
2016/11/30 Javascript
Angular 4 指令快速入门教程
2017/06/07 Javascript
浅谈layui 数据表格前后台传值的问题
2019/09/12 Javascript
[03:36]DOTA2完美大师赛coL战队趣味视频——我演你猜
2017/11/23 DOTA
[57:24]LGD vs VGJ.T 2018国际邀请赛小组赛BO2 第二场 8.16
2018/08/17 DOTA
详解C++编程中一元运算符的重载
2016/01/19 Python
python+selenium实现登录账户后自动点击的示例
2017/12/22 Python
python3使用SMTP发送HTML格式邮件
2018/06/19 Python
python处理csv中的空值方法
2018/06/22 Python
pytorch 更改预训练模型网络结构的方法
2019/08/19 Python
python 实现目录复制的三种小结
2019/12/04 Python
Python接口测试get请求过程详解
2020/02/28 Python
pyqt5 QlistView列表显示的实现示例
2020/03/24 Python
PyTorch中clone()、detach()及相关扩展详解
2020/12/09 Python
利用css3 translate完美实现表头固定效果
2017/02/28 HTML / CSS
HTML5混合开发二维码扫描以及调用本地摄像头
2017/12/27 HTML / CSS
捷克钓鱼用品网上商店:Parys.cz
2018/06/15 全球购物
美国珠宝店:Helzberg Diamonds
2018/10/24 全球购物
叙述DBMS对数据控制功能有哪些
2016/06/12 面试题
记者岗位职责
2014/01/06 职场文书
单位授权委托书范本
2014/09/26 职场文书
卖房授权委托书样本
2014/10/05 职场文书
2014年采购员工作总结
2014/11/18 职场文书
商铺租房协议书范本
2014/12/04 职场文书
北京天坛导游词
2015/02/12 职场文书
学期个人自我总结
2015/02/13 职场文书
Oracle笔记
2021/04/05 Oracle
俄罗斯十大城市人口排名,第三首都仅排第六,第二是北方首都
2022/03/20 杂记