使用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判断操作系统类型代码分享
Nov 22 Python
python实现TF-IDF算法解析
Jan 02 Python
Python Tkinter实现简易计算器功能
Jan 30 Python
Python基于分析Ajax请求实现抓取今日头条街拍图集功能示例
Jul 19 Python
Python基本数据结构与用法详解【列表、元组、集合、字典】
Mar 23 Python
python计算波峰波谷值的方法(极值点)
Feb 18 Python
自定义实现 PyQt5 下拉复选框 ComboCheckBox的完整代码
Mar 30 Python
Python tkinter实现简单加法计算器代码实例
May 13 Python
python如何编写win程序
Jun 08 Python
一文详述 Python 中的 property 语法
Sep 01 Python
python使用scapy模块实现ping扫描的过程详解
Jan 21 Python
在 Python 中利用 Pool 进行多线程
Apr 24 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
最简单的jQuery程序 入门者学习
2009/07/09 Javascript
JS打开新窗口的2种方式
2013/04/18 Javascript
jquery防止重复执行动画避免页面混乱
2014/04/22 Javascript
常用的javascript设计模式
2017/01/11 Javascript
BootStrap Select清除选中的状态恢复默认状态
2017/06/20 Javascript
Javascript中parseInt的正确使用方式
2018/10/17 Javascript
详解小程序不同页面之间通讯的解决方案
2018/11/23 Javascript
详解express使用vue-router的history踩坑
2019/06/05 Javascript
在mpvue框架中使用Vant WeappUI组件库的注意事项【推进】
2019/06/09 Javascript
vue 集成jTopo 处理方法
2019/08/07 Javascript
VUE.js实现动态设置输入框disabled属性
2019/10/28 Javascript
vue实现打地鼠小游戏
2020/08/21 Javascript
在Python中使用__slots__方法的详细教程
2015/04/28 Python
利用 python 对目录下的文件进行过滤删除
2017/12/27 Python
python jieba分词并统计词频后输出结果到Excel和txt文档方法
2018/02/11 Python
pytorch + visdom 处理简单分类问题的示例
2018/06/04 Python
解决python中画图时x,y轴名称出现中文乱码的问题
2019/01/29 Python
python异常触发及自定义异常类解析
2019/08/06 Python
python文件操作的简单方法总结
2019/11/07 Python
Python(PyS60)实现简单语音整点报时
2019/11/18 Python
python进行OpenCV实战之画图(直线、矩形、圆形)
2020/08/27 Python
Python3利用scapy局域网实现自动多线程arp扫描功能
2021/01/21 Python
美国职棒大联盟官方网上商店:MLBShop.com
2017/11/12 全球购物
Groupon西班牙官方网站:在线优惠券和交易,节省高达70%
2021/03/13 全球购物
上海方立数码笔试题
2013/10/18 面试题
新闻专业个人求职信
2013/12/19 职场文书
《美丽的田园》教学反思
2014/03/01 职场文书
市场营销调查计划书
2014/05/02 职场文书
工程学毕业生自荐信
2014/06/14 职场文书
民主评议党员登记表自我评价
2014/10/20 职场文书
2014年小学安全工作总结
2014/12/04 职场文书
单位租车协议书
2015/01/29 职场文书
2015年检验科工作总结
2015/04/27 职场文书
刑事上诉状(无罪)
2015/05/23 职场文书
合同补充协议书
2016/03/24 职场文书
详解在SQLPlus中实现上下键翻查历史命令的功能
2022/03/18 SQL Server