使用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抓取百度查询结果的方法
Jul 08 Python
Python模糊查询本地文件夹去除文件后缀的实例(7行代码)
Nov 09 Python
Python 利用内置set函数对字符串和列表进行去重的方法
Jun 29 Python
python 反向输出字符串的方法
Jul 16 Python
python3.6实现学生信息管理系统
Feb 21 Python
初探利用Python进行图文识别(OCR)
Feb 26 Python
python实现证件照换底功能
Aug 20 Python
python GUI库图形界面开发之PyQt5滚动条控件QScrollBar详细使用方法与实例
Mar 06 Python
pycharm设置python文件模板信息过程图解
Mar 10 Python
django 解决扩展自带User表遇到的问题
May 14 Python
Pytorch 如何实现常用正则化
May 27 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
VOLVO车载收音机
2021/03/02 无线电
咖啡的植物学知识
2021/03/03 咖啡文化
PHP 5.0对象模型深度探索之属性和方法
2008/03/27 PHP
深入php常用函数的使用汇总
2013/06/08 PHP
Js callBack 返回前一页的js方法
2008/11/30 Javascript
Javascript解决常见浏览器兼容问题的12种方法
2010/01/04 Javascript
jQuery创建平滑的页面滚动(顶部或底部)
2013/02/26 Javascript
基于jquery的has()方法以及与find()方法以及filter()方法的区别详解
2013/04/26 Javascript
js冒泡法和数组转换成字符串示例代码
2013/08/14 Javascript
深入理解关于javascript中apply()和call()方法的区别
2016/04/12 Javascript
JavaScript中关键字 in 的使用方法详解
2016/10/17 Javascript
jQuery插件之validation插件
2017/03/29 jQuery
js 数字、字符串、布尔值的转换方法(必看)
2017/04/07 Javascript
AngularJS实现注册表单验证功能
2017/10/16 Javascript
浅谈react受控组件与非受控组件(小结)
2018/02/09 Javascript
cocos2dx+lua实现橡皮擦功能
2018/12/20 Javascript
JavaScript简单实现的仿微博留言功能示例
2019/01/17 Javascript
vue中axios封装使用的完整教程
2021/03/03 Vue.js
python PIL模块与随机生成中文验证码
2016/02/27 Python
Django管理员账号和密码忘记的完美解决方法
2018/12/06 Python
python批量读取文件名并写入txt文件中
2020/09/05 Python
python通过实例讲解反射机制
2019/10/17 Python
Python函数的默认参数设计示例详解
2019/12/01 Python
Python 中@property的用法详解
2020/01/15 Python
使用Django xadmin 实现修改时间选择器为不可输入状态
2020/03/30 Python
Python 创建TCP服务器的方法
2020/07/28 Python
戴尔加拿大官网:Dell加拿大
2016/09/17 全球购物
Hotter Shoes英国官网:英伦风格,舒适的鞋子
2017/12/28 全球购物
锐步英国官网:Reebok英国
2019/11/29 全球购物
奢华时尚的创新平台:Baltini
2020/10/03 全球购物
消防安全检查制度
2014/02/04 职场文书
小学生竞选班长演讲稿
2014/04/24 职场文书
试用期员工工作自我评价
2014/09/10 职场文书
春风化雨观后感
2015/06/11 职场文书
银行安全保卫工作总结
2015/08/10 职场文书
安全学习心得体会范文
2016/01/18 职场文书