• 技术文章 >后端开发 >Python教程

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

    2016-06-06 11:25:09原创1179
    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 *
    声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn核实处理。
    专题推荐:Python
    上一篇:在Python中实现贪婪排名算法的教程 下一篇:全面剖析Python的Django框架中的项目部署技巧
    20期PHP线上班

    相关文章推荐

    精选22门好课,价值3725元,开通VIP免费学习!• python虚拟环境配置与管理• 一文搞懂怎么在python中读取和写入CSV文件• 总结分享Python冷门的技巧• Python爬虫超详细讲解• 一文搞懂Python爬虫解析器BeautifulSoup4
    1/1

    PHP中文网