c语言程序提速,使用Protocol Buffers的C语言拓展提速Python程序的示例

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

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邮列表来了解到这些。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Protocol Buffers(简称protobuf)是一种轻便高效的数据存储和交换格式,它的语法简单,可以使用.proto文件定义数据结构,可以通过类似编译的过程将.proto文件编译成相应语言的类文件,从而方便地进行序列化和反序列化操作。protobuf支持多种编程语言,包括Java、C++、Python等。 下面是一个protobuf的使用示例: 假设我们要定义一个Person的数据类型,包括name、id、email三个属性,可以在.proto文件中定义如下: ``` syntax = "proto3"; package tutorial; message Person { string name = 1; int32 id = 2; string email = 3; } ``` 这里的syntax指定了使用protobuf版本,1表示proto2,2表示proto3。package指定了所属的包名,message定义了数据类型,其中name、id、email分别是属性名,1、2、3是属性的标识号,用于序列化和反序列化时识别不同属性。 接下来,我们可以使用protobuf的编译器将.proto文件编译成Java类文件,具体命令如下: ``` protoc --java_out=./ Person.proto ``` 其中,--java_out表示输出Java类文件,./表示输出到当前目录下。 编译完成后,我们就可以在Java程序使用Person类了,如下所示: ``` import tutorial.Person; Person.Builder personBuilder = Person.newBuilder(); personBuilder.setName("Tom"); personBuilder.setId(1001); personBuilder.setEmail("tom@example.com"); Person person = personBuilder.build(); ``` 这里首先导入了Person类,然后使用Person.Builder创建一个Person对象,设置其属性值,最后通过build方法生成一个不可变的Person对象。 我们还可以将Person对象序列化成二进制格式,便于网络传输或者存储到文件中,如下所示: ``` byte[] bytes = person.toByteArray(); ``` 这里的toByteArray方法将Person对象序列化成一个byte数组。 反之,我们也可以将二进制数据反序列化成Person对象,如下所示: ``` Person person = Person.parseFrom(bytes); ``` 这里的parseFrom方法将byte数组反序列化成一个Person对象。 以上就是protobuf的基本使用示例,通过protobuf,我们可以轻松地定义和序列化数据类型,方便地进行网络传输和数据存储。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值