使用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-基础-入门 简介
Aug 09 Python
python登陆asp网站页面的实现代码
Jan 14 Python
Python内置函数Type()函数一个有趣的用法
Feb 18 Python
Python查找相似单词的方法
Mar 05 Python
python网络编程之文件下载实例分析
May 20 Python
windows下python安装paramiko模块和pycrypto模块(简单三步)
Jul 06 Python
django 实现简单的插入视频
Apr 07 Python
Pytorch 使用opnecv读入图像由HWC转为BCHW格式方式
Jun 02 Python
浅谈Keras中shuffle和validation_split的顺序
Jun 19 Python
python之语音识别speech模块
Sep 09 Python
Python实现曲线拟合的最小二乘法
Feb 19 Python
如何利用python和DOS获取wifi密码
Mar 31 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解答方法
2012/02/04 PHP
php计算程序运行时间的简单例子分享
2014/05/10 PHP
php写的AES加密解密类分享
2014/06/20 PHP
叫你如何修改Nginx与PHP的文件上传大小限制
2014/09/10 PHP
总结PHP中数值计算的注意事项
2016/08/14 PHP
php实现生成带二维码图片并强制下载功能
2018/02/24 PHP
php从数据库读取数据,并以json格式返回数据的方法
2018/08/21 PHP
PDO实现学生管理系统
2020/03/21 PHP
PHP解密支付宝小程序的加密数据、手机号的示例代码
2021/02/26 PHP
JS 文件传参及处理技巧分析
2010/05/13 Javascript
从面试题学习Javascript 面向对象(创建对象)
2012/03/30 Javascript
JavaScript闭包函数访问外部变量的方法
2014/08/27 Javascript
使用jQuery实现WordPress中的Ctrl+Enter和@评论回复
2016/05/21 Javascript
JavaScript 判断一个对象{}是否为空对象的简单方法
2016/10/09 Javascript
vue项目中使用scss的方法步骤
2019/05/16 Javascript
vue npm install 安装某个指定的版本操作
2020/08/11 Javascript
详解datagrid使用方法(重要)
2020/11/06 Javascript
JS操作JSON常用方法(10w阅读)
2020/12/06 Javascript
[40:19]完美世界DOTA2联赛PWL S3 Rebirth vs CPG 第二场 12.18
2020/12/19 DOTA
Python判断某个用户对某个文件的权限
2016/10/13 Python
Python 详解基本语法_函数_返回值
2017/01/22 Python
python中通过预先编译正则表达式提高效率
2017/09/25 Python
Python 函数基础知识汇总
2018/03/09 Python
Python单向链表和双向链表原理与用法实例详解
2018/08/31 Python
Python实现按逗号分隔列表的方法
2018/10/23 Python
PyQt5实现QLineEdit添加clicked信号的方法
2019/06/25 Python
Django实现微信小程序支付的示例代码
2020/09/03 Python
微软台湾官方网站:Microsoft台湾
2018/08/15 全球购物
企业管理专业个人求职信范文
2013/09/24 职场文书
专科应届生求职信
2013/11/24 职场文书
求职个人评价范文
2014/04/09 职场文书
冬季安全检查方案
2014/05/23 职场文书
小学数学课题方案
2014/06/15 职场文书
新生开学寄语大全
2015/05/28 职场文书
Java各种比较对象的方式的对比总结
2021/06/20 Java/Android
解决IIS7下无法绑定https主机的问题
2022/04/29 Servers