使用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下Fabric的简单部署方法
Jul 14 Python
Linux下将Python的Django项目部署到Apache服务器
Dec 24 Python
Python实现的简单模板引擎功能示例
Sep 02 Python
Python探索之静态方法和类方法的区别详解
Oct 27 Python
高效使用Python字典的清单
Apr 04 Python
Python图片转换成矩阵,矩阵数据转换成图片的实例
Jul 02 Python
浅析python的优势和不足之处
Nov 20 Python
使用coverage统计python web项目代码覆盖率的方法详解
Aug 05 Python
如何使用repr调试python程序
Feb 28 Python
Django分组聚合查询实例分享
Apr 29 Python
Python如何读取、写入JSON数据
Jul 28 Python
python绘制简单直方图(质量分布图)的方法
Apr 21 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语法(2)
2006/10/09 PHP
PHP IDE phpstorm 常用快捷键
2015/05/18 PHP
PHP中你应该知道的require()文件包含的正确用法
2015/06/12 PHP
一个很简单的jquery+xml+ajax的无刷新树结构(无css,后台是c#)
2010/06/02 Javascript
jQuery 表单验证扩展(四)
2010/10/20 Javascript
12个超实用的JQuery代码片段
2015/11/02 Javascript
Bootstrap 3 进度条的实现
2017/02/22 Javascript
JS验证全角与半角及相互转化的介绍
2017/05/18 Javascript
浅谈Node.js 子进程与应用场景
2018/01/24 Javascript
微信小程序提取公用函数到util.js及使用方法示例
2019/01/10 Javascript
JavaScript数据结构之栈实例用法
2019/01/18 Javascript
Vue自定义指令上报Google Analytics事件统计的方法
2019/02/25 Javascript
可能被忽略的一些JavaScript数组方法细节
2019/02/28 Javascript
更优雅的微信小程序骨架屏实现详解
2019/08/07 Javascript
layer iframe 设置关闭按钮的方法
2019/09/12 Javascript
基于Echarts图表在div动态切换时不显示的解决方式
2020/07/20 Javascript
vue element 关闭当前tab 跳转到上一路由操作
2020/07/22 Javascript
js+canvas绘制图形验证码
2020/09/21 Javascript
[01:03:13]VG vs Pain 2018国际邀请赛小组赛BO2 第一场 8.18
2018/08/19 DOTA
[45:16]完美世界DOTA2联赛循环赛 IO vs FTD BO2第二场 11.05
2020/11/06 DOTA
Python中的getopt函数使用详解
2015/07/28 Python
Win7下搭建python开发环境图文教程(安装Python、pip、解释器)
2016/05/17 Python
python去掉行尾的换行符方法
2017/01/04 Python
Python爬虫实例_利用百度地图API批量获取城市所有的POI点
2018/01/10 Python
python实现员工管理系统
2018/01/11 Python
python thrift搭建服务端和客户端测试程序
2018/01/17 Python
Python实现 版本号对比功能的实例代码
2019/04/18 Python
Python如何使用BeautifulSoup爬取网页信息
2019/11/26 Python
Python数据持久化存储实现方法分析
2019/12/21 Python
python argparse模块通过后台传递参数实例
2020/04/20 Python
Html5大文件断点续传实现方法
2015/12/05 HTML / CSS
房展策划方案
2014/06/07 职场文书
六查六看个人剖析材料
2014/10/14 职场文书
公司领导班子召开党的群众路线教育实践活动总结大会新闻稿
2014/10/21 职场文书
单位实习介绍信
2015/05/05 职场文书
asyncio异步编程之Task对象详解
2022/03/13 Python