使用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 相关文章推荐
Python3 能振兴 Python的原因分析
Nov 28 Python
Python fileinput模块使用介绍
Nov 30 Python
python制作爬虫并将抓取结果保存到excel中
Apr 06 Python
Python中datetime模块参考手册
Jan 13 Python
Python实现统计给定列表中指定数字出现次数的方法
Apr 11 Python
Python实现蒙特卡洛算法小实验过程详解
Jul 12 Python
纯python进行矩阵的相乘运算的方法示例
Jul 17 Python
Python二次规划和线性规划使用实例
Dec 09 Python
Python基于类路径字符串获取静态属性
Mar 12 Python
Keras构建神经网络踩坑(解决model.predict预测值全为0.0的问题)
Jul 07 Python
Python爬虫抓取论坛关键字过程解析
Oct 19 Python
Python读写锁实现实现代码解析
Nov 28 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
cache_lite试用
2007/02/14 PHP
php简单对象与数组的转换函数代码(php多层数组和对象的转换)
2011/05/18 PHP
解析php利用正则表达式解决采集内容排版的问题
2013/06/20 PHP
PHP网页游戏学习之Xnova(ogame)源码解读(十五)
2014/06/30 PHP
yii实现CheckBox复选框在同一行显示的方法
2014/12/03 PHP
PHP中创建和验证哈希的简单方法实探
2015/07/06 PHP
PHP Redis扩展无法加载的问题解决方法
2019/08/22 PHP
jquery中对表单的基本操作代码
2010/07/29 Javascript
jQuery实现可拖动的浮动层完整代码
2013/05/27 Javascript
纯css+js写的一个简单的tab标签页带样式
2014/01/28 Javascript
document.compatMode的CSS1compat使用介绍
2014/04/03 Javascript
JavaScript中字符串与Unicode编码互相转换的实现方法
2015/12/18 Javascript
AngularJS ng-repeat数组有重复值的解决方法
2016/10/23 Javascript
jquery中each循环的简单回滚操作
2017/05/05 jQuery
VueJS事件处理器v-on的使用方法
2017/09/27 Javascript
如何将你的AngularJS1.x应用迁移至React的方法
2018/02/01 Javascript
详解webpack运行Babel教程
2018/06/13 Javascript
vue加载完成后的回调函数方法
2018/09/07 Javascript
基于jquery实现九宫格拼图小游戏
2018/11/30 jQuery
解决使用layui对select append元素无效或者未及时更新的问题
2019/09/18 Javascript
vue实现折线图 可按时间查询
2020/08/21 Javascript
[51:32]Optic vs Serenity 2018国际邀请赛淘汰赛BO3 第一场 8.22
2018/08/23 DOTA
Python中if __name__ == &quot;__main__&quot;详细解释
2014/10/21 Python
python中反射用法实例
2015/03/27 Python
python django事务transaction源码分析详解
2017/03/17 Python
Python中.py文件打包成exe可执行文件详解
2017/03/22 Python
Python数据拟合与广义线性回归算法学习
2017/12/22 Python
python 同时读取多个文件的例子
2019/07/16 Python
python使用正则来处理各种匹配问题
2019/12/22 Python
详解向scrapy中的spider传递参数的几种方法(2种)
2020/09/28 Python
HTML5地理定位与第三方工具百度地图的应用
2016/11/17 HTML / CSS
澳大利亚宠物食品和药物在线:Jumbo Pets
2018/03/24 全球购物
总经理助理岗位职责
2015/01/31 职场文书
2015年医院护理部工作总结
2015/04/23 职场文书
2015新教师教学工作总结
2015/07/22 职场文书
MySQL中utf8mb4排序规则示例
2021/08/02 MySQL