使用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中zip()方法应用实例分析
Apr 16 Python
Python使用QQ邮箱发送Email的方法实例
Feb 09 Python
Python绘制3d螺旋曲线图实例代码
Dec 20 Python
Python结合ImageMagick实现多张图片合并为一个pdf文件的方法
Apr 24 Python
django静态文件加载的方法
May 20 Python
Python 实现「食行生鲜」签到领积分功能
Sep 26 Python
python模块之subprocess模块级方法的使用
Mar 26 Python
手把手教你Python yLab的绘制折线图的画法
Oct 23 Python
python-docx文件定位读取过程(尝试替换)
Feb 13 Python
PyInstaller运行原理及常用操作详解
Jun 13 Python
Python从文件中读取数据的方法步骤
Nov 18 Python
Python中tkinter的用户登录管理的实现
Apr 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
fetchAll()与mysql_fetch_array()的区别详解
2013/06/05 PHP
PHP使用range协议实现输出文件断点续传代码实例
2014/07/04 PHP
基于thinkPHP框架实现留言板的方法
2016/10/17 PHP
动态表单验证的操作方法和TP框架里面的ajax表单验证
2017/07/19 PHP
解决laravel session失效的问题
2019/10/14 PHP
分享几种好用的PHP自定义加密函数(可逆/不可逆)
2020/09/15 PHP
用js实现预览待上传的本地图片
2007/03/15 Javascript
jquery animate 动画效果使用说明
2009/11/04 Javascript
Javascript 面向对象 重载
2010/05/13 Javascript
JQuery实现简单验证码提示解决方案
2012/12/20 Javascript
Eval and new funciton not the same thing
2012/12/27 Javascript
js身份证判断方法支持15位和18位
2014/03/18 Javascript
JavaScript中使用Callback控制流程介绍
2015/03/16 Javascript
javascript表格的渲染组件
2015/07/03 Javascript
基于jquery实现表格内容筛选功能实例解析
2016/05/09 Javascript
倾力总结40条常见的移动端Web页面问题解决方案
2016/05/24 Javascript
jQuery解决IE6、7、8不能使用 JSON.stringify 函数的问题
2016/05/31 Javascript
jQuery Easyui Tabs扩展根据自定义属性打开页签
2016/08/15 Javascript
浅谈js原生拖放
2016/11/21 Javascript
详解vue 计算属性与方法跟侦听器区别(面试考点)
2018/04/23 Javascript
vue项目引入字体.ttf的方法
2018/09/28 Javascript
使用flow来规范javascript的变量类型
2019/09/12 Javascript
探索node之事件循环的实现
2020/10/30 Javascript
python 切换root 执行命令的方法
2019/01/19 Python
python中web框架的自定义创建
2019/09/08 Python
Python时间差中seconds和total_seconds的区别详解
2019/12/26 Python
Python控制台输出时刷新当前行内容而不是输出新行的实现
2020/02/21 Python
html5 canvas-2.用canvas制作一个猜字母的小游戏
2013/01/07 HTML / CSS
草莓网美国官网:Strawberrynet USA
2016/12/11 全球购物
中东奢侈品购物网站:Ounass
2020/09/02 全球购物
.NET面试题:什么是值类型和引用类型
2016/01/12 面试题
文科生自我鉴定
2014/02/15 职场文书
写得不错的求职信范文
2014/07/11 职场文书
2014年作风建设工作总结
2014/10/29 职场文书
小学生毕业评语
2014/12/26 职场文书
nginx 配置缓存
2022/05/11 Servers