使用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怎么学好python?
Oct 07 Python
python循环监控远程端口的方法
Mar 14 Python
Windows下Eclipse+PyDev配置Python+PyQt4开发环境
May 17 Python
利用Python批量生成任意尺寸的图片
Aug 29 Python
Python深度优先算法生成迷宫
Jan 22 Python
django框架实现一次性上传多个文件功能示例【批量上传】
Jun 19 Python
Python寻找路径和查找文件路径的示例
Jul 10 Python
TensorFlow基于MNIST数据集实现车牌识别(初步演示版)
Aug 05 Python
numpy np.newaxis 的实用分享
Nov 30 Python
Pycharm同步远程服务器调试的方法步骤
Nov 04 Python
python3 re返回形式总结
Nov 20 Python
AI:如何训练机器学习的模型
Apr 16 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
Centos下升级php5.2到php5.4全记录(编译安装)
2015/04/03 PHP
PHP简单实现冒泡排序的方法
2016/12/26 PHP
解决Laravel5.x的php artisan migrate数据库迁移创建操作报错SQLSTATE[42000]
2020/04/06 PHP
JS下拉框内容左右移动效果的具体实现
2013/07/10 Javascript
jQuery响应鼠标事件并隐藏与显示input默认值
2014/08/24 Javascript
jQuery+PHP打造滑动开关效果
2014/12/16 Javascript
JS基于Mootools实现的个性菜单效果代码
2015/10/21 Javascript
JS触摸屏网页版仿app弹窗型滚动列表选择器/日期选择器
2016/10/30 Javascript
javascript中href和replace的比较(详解)
2016/11/25 Javascript
微信小程序 闭包写法详细介绍
2016/12/14 Javascript
jQuery插件Echarts实现的双轴图效果示例【附demo源码下载】
2017/03/04 Javascript
JavaScript数据结构之二叉树的遍历算法示例
2017/04/13 Javascript
vue-cli+webpack在生成的项目中使用bootstrap实例代码
2017/05/26 Javascript
bootstrap datetimepicker控件位置异常的解决方法
2017/11/23 Javascript
简单的Vue SSR的示例代码
2018/01/12 Javascript
JS实现的邮箱提示补全效果示例
2018/01/30 Javascript
Element UI 自定义正则表达式验证方法
2018/09/04 Javascript
node中的cookie的具体使用
2018/09/13 Javascript
JS实现图片拖拽交换效果
2018/11/30 Javascript
javascript实现自由编辑图片代码详解
2019/06/21 Javascript
Nodejs 识别图片类型的方法
2019/08/15 NodeJs
微信小程序webview与h5通过postMessage实现实时通讯的实现
2019/08/20 Javascript
Js图片点击切换轮播实现代码
2020/07/27 Javascript
[02:47]DOTA2英雄基础教程 野性怒吼兽王
2013/12/05 DOTA
[01:03:22]LGD vs OG 2018国际邀请赛淘汰赛BO3 第一场 8.25
2018/08/29 DOTA
python将图片文件转换成base64编码的方法
2015/03/14 Python
Python中使用ElementTree解析XML示例
2015/06/02 Python
python字典多键值及重复键值的使用方法(详解)
2016/10/31 Python
解读! Python在人工智能中的作用
2017/11/14 Python
Python实现的字典值比较功能示例
2018/01/08 Python
windows下安装Python虚拟环境virtualenvwrapper-win
2019/06/14 Python
简单了解python的break、continue、pass
2019/07/08 Python
基于python requests selenium爬取excel vba过程解析
2020/08/12 Python
启动仪式策划方案
2014/06/14 职场文书
小学生思想品德评语
2014/12/31 职场文书
ConditionalOnProperty配置swagger不生效问题及解决
2022/06/14 Java/Android