使用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 相关文章推荐
在Debian下配置Python+Django+Nginx+uWSGI+MySQL的教程
Apr 25 Python
Python基于PycURL实现POST的方法
Jul 25 Python
详解Python中的元组与逻辑运算符
Oct 13 Python
如何在Python中编写并发程序
Feb 27 Python
举例讲解Python的lambda语句声明匿名函数的用法
Jul 01 Python
python使用xlrd与xlwt对excel的读写和格式设定
Jan 21 Python
浅谈python可视化包Bokeh
Feb 07 Python
分享一下Python数据分析常用的8款工具
Apr 29 Python
Python对称的二叉树多种思路实现方法
Feb 28 Python
Django自定义列表 models字段显示方式
Apr 03 Python
Java多线程实现四种方式原理详解
Jun 02 Python
Python如何自动获取目标网站最新通知
Jun 18 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
GD输出汉字的函数的分析
2006/10/09 PHP
PHP 字符串编码截取函数(兼容utf-8和gb2312)
2009/05/02 PHP
yii2中结合gridview如何使用modal弹窗实例代码详解
2016/06/12 PHP
CI(CodeIgniter)框架实现图片上传的方法
2017/03/24 PHP
麦鸡的TAB切换功能结合了javascript和css
2007/12/17 Javascript
javascript 建设银行登陆键盘
2008/06/10 Javascript
JavaScript将相对地址转换为绝对地址示例代码
2013/07/19 Javascript
jquery 插件实现瀑布流图片展示实例
2015/04/03 Javascript
jQuery控制div实现随滚动条滚动效果
2016/06/07 Javascript
canvas实现十二星座星空图
2017/02/14 Javascript
基于Bootstrap 3 JQuery及RegExp的表单验证功能
2017/02/16 Javascript
js eval函数使用,js对象和字符串互转实例
2017/03/06 Javascript
JS实现简易的图片拖拽排序实例代码
2017/06/09 Javascript
Grunt针对静态文件的压缩,版本控制打包的实例讲解
2017/09/29 Javascript
zTree节点文字过多的处理方法
2017/11/24 Javascript
javascript实现计算指定范围内的质数示例
2018/12/29 Javascript
JS多个异步请求 按顺序执行next实现解析
2019/09/16 Javascript
layer关闭弹出窗口触发表单提交问题的处理方法
2019/09/25 Javascript
layui时间控件选择时间范围的实现方法
2019/09/28 Javascript
Python中json格式数据的编码与解码方法详解
2016/07/01 Python
Python Mock模块原理及使用方法详解
2020/07/07 Python
利用python对excel中一列的时间数据更改格式操作
2020/07/14 Python
python获取天气接口给指定微信好友发天气预报
2020/12/28 Python
HTML5中在title标题标签里设置小图标的方法
2020/06/23 HTML / CSS
英国计算机产品零售商:Novatech(定制个人电脑、笔记本电脑、工作站和服务器)
2018/01/28 全球购物
巴西服装和鞋子购物网站:Marisa
2018/10/25 全球购物
美国班级戒指、帽子和礼服、毕业产品、年鉴:Balfour
2018/11/01 全球购物
国际贸易专业推荐信
2013/11/15 职场文书
车间操作工岗位职责
2013/12/19 职场文书
公司寄语大全
2014/04/10 职场文书
搞笑的爱情检讨书
2014/10/01 职场文书
公司行政管理制度范本
2015/08/05 职场文书
《酸的和甜的》教学反思
2016/02/18 职场文书
详解Django的MVT设计模式
2021/04/29 Python
刚学完怎么用Python实现定时任务,转头就跑去撩妹!
2021/06/05 Python
Spring Boot 使用 Spring-Retry 进行重试框架
2022/04/24 Java/Android