使用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实现k均值算法示例(k均值聚类算法)
Mar 16 Python
Django中对通过测试的用户进行限制访问的方法
Jul 23 Python
Python中用字符串调用函数或方法示例代码
Aug 04 Python
python装饰器实例大详解
Oct 25 Python
python之matplotlib学习绘制动态更新图实例代码
Jan 23 Python
Python即时网络爬虫项目启动说明详解
Feb 23 Python
在django中图片上传的格式校验及大小方法
Jul 28 Python
pycharm重命名文件的方法步骤
Jul 29 Python
基于python二叉树的构造和打印例子
Aug 09 Python
使用python实现回文数的四种方法小结
Nov 24 Python
PyQt5+Pycharm安装和配置图文教程详解
Mar 24 Python
解决启动django,浏览器显示“服务器拒绝访问”的问题
May 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中抽象类、接口的区别与选择分析
2016/03/29 PHP
PHP+MySql+jQuery实现的&quot;顶&quot;和&quot;踩&quot;投票功能
2016/05/21 PHP
阿里云Win2016安装Apache和PHP环境图文教程
2018/03/11 PHP
关于extjs4如何获取grid修改后的数据的问题
2013/08/07 Javascript
前台js调用后台方法示例
2013/12/02 Javascript
JavaScript将数据转换成整数的方法
2014/01/04 Javascript
Nodejs学习笔记之Stream模块
2015/01/13 NodeJs
javascript实现对表格元素进行排序操作
2015/11/18 Javascript
jquery插件格式实例分析
2016/06/16 Javascript
JS中script标签defer和async属性的区别详解
2016/08/12 Javascript
bootstrap fileinput 插件使用项目总结(经验)
2017/02/22 Javascript
微信小程序 列表的上拉加载和下拉刷新的实现
2017/04/01 Javascript
JS中mouseup事件丢失的原因与解决办法
2017/06/14 Javascript
探索webpack模块及webpack3新特性
2017/09/18 Javascript
JavaScript图片处理与合成总结
2018/03/04 Javascript
微信小程序scroll-view仿拼多多横向滑动滚动条
2020/04/21 Javascript
快速解决Vue项目在IE浏览器中显示空白的问题
2018/09/04 Javascript
node之本地服务器图片上传的方法示例
2019/03/26 Javascript
Python批处理删除和重命名文件夹的实例
2018/07/11 Python
django 实现电子支付功能的示例代码
2018/07/25 Python
Python使用ffmpy将amr格式的音频转化为mp3格式的例子
2019/08/08 Python
python字符串,元组,列表,字典互转代码实例详解
2020/02/14 Python
关于Python解包知识点总结
2020/05/05 Python
国外平面设计第一市场:99designs
2016/10/25 全球购物
简约控的天堂:The Undone
2016/12/21 全球购物
咖啡蛋糕店创业计划书
2014/01/28 职场文书
施工员岗位职责
2014/03/16 职场文书
我的中国梦演讲稿初中篇
2014/08/19 职场文书
公务员爱岗敬业演讲稿
2014/08/26 职场文书
2014酒店客房部工作总结
2014/12/16 职场文书
收银员岗位职责
2015/02/03 职场文书
2015年招生工作总结
2015/05/04 职场文书
2015年暑期社会实践总结
2015/07/13 职场文书
公司员工奖惩制度
2015/08/04 职场文书
如何做好工作总结!
2019/04/10 职场文书
JS + HTML 罗盘式时钟的实现
2021/05/21 Javascript