使用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入门教程
Feb 08 Python
Python中设置变量作为默认值时容易遇到的错误
Apr 03 Python
Python类的定义、继承及类对象使用方法简明教程
May 08 Python
python爬虫 正则表达式使用技巧及爬取个人博客的实例讲解
Oct 20 Python
python实现LBP方法提取图像纹理特征实现分类的步骤
Jul 11 Python
用Python调用win命令行提高工作效率的实例
Aug 14 Python
安装python及pycharm的教程图解
Oct 10 Python
浅析matlab中imadjust函数
Feb 27 Python
PyQt5事件处理之定时在控件上显示信息的代码
Mar 25 Python
python requests.get带header
May 05 Python
python垃圾回收机制原理分析
Apr 13 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读取mysql乱码,用set names XXX解决的原理分享
2011/12/29 PHP
Zend Framework前端控制器用法示例
2016/12/11 PHP
浅谈PHP接入(第三方登录)QQ登录 OAuth2.0 过程中遇到的坑
2017/10/13 PHP
thinkPHP5实现数据库添加内容的方法
2017/10/25 PHP
PHP文件操作简单介绍及函数汇总
2020/12/11 PHP
(转载)JavaScript中匿名函数,函数直接量和闭包
2007/05/08 Javascript
用于判断用户注册时,密码强度的JS代码
2009/01/01 Javascript
jQuery事件绑定.on()简要概述及应用
2013/02/07 Javascript
Jquery中的层次选择器与find()的区别示例介绍
2014/02/20 Javascript
简化版手机端照片预览组件
2015/04/13 Javascript
浅析location.href跨窗口调用函数
2016/11/22 Javascript
学习vue.js中class与style绑定
2016/12/03 Javascript
Javascript es7中比较实用的两个方法示例
2017/07/21 Javascript
javascript 缓冲运动框架的实现
2017/09/29 Javascript
vue项目中常见问题及解决方案(推荐)
2019/10/21 Javascript
JS如何实现动态添加的元素绑定事件
2019/11/12 Javascript
解决node.js含有%百分号时发送get请求时浏览器地址自动编码的问题
2019/11/20 Javascript
Python读写Json涉及到中文的处理方法
2016/09/12 Python
详解python进行mp3格式判断
2016/12/23 Python
Python定义一个跨越多行的字符串的多种方法小结
2018/07/19 Python
Python3的介绍、安装和命令行的认识(推荐)
2018/10/20 Python
Django中ORM外键和表的关系详解
2019/05/20 Python
Django框架模板文件使用及模板文件加载顺序分析
2019/05/23 Python
python实现桌面气泡提示功能
2019/07/29 Python
关于python导入模块import与常见的模块详解
2019/08/28 Python
提升python处理速度原理及方法实例
2019/12/25 Python
Python之Django自动实现html代码(下拉框,数据选择)
2020/03/13 Python
HTTP状态码详解
2021/03/18 杂记
Eastbay官网:美国最大的运动鞋网络零售商
2016/07/27 全球购物
GAP阿联酋官网:GAP UAE
2017/11/30 全球购物
Diesel美国网上商店:意大利牛仔时装品牌
2020/12/10 全球购物
教师专业技术工作总结2015
2015/05/13 职场文书
2015小学新教师个人工作总结
2015/10/14 职场文书
如果用一句诗总结你的上半年,你会用哪句呢?
2019/07/16 职场文书
导游词之重庆渣滓洞
2020/01/08 职场文书
pyqt5蒙版遮罩mask,setmask的使用
2021/06/11 Python