为什么专门开一个坑,来使用pb。放弃本在各平台上都支持得很好的json而使用pb的一个归根到底的理由,就是希望在保证强类型和跨平台的情况下,能够更轻,更快,更简单。既然是奔着这个目标去的,到底多快我需要一个合理的解释。

在使用pure python官方库的的情况下,对比了pb和json标准库,还有simplejson库的速度。

使用的.proto文件文件如下:

syntax = "proto2";

package hello_word;

message SayHi {
required int32 id = 1;
required string something = 2;
optional string extra_info = 3;
}

python文件可以根据这个生成对应的SayHi obejct。

测试各库序列化速度的代码如下所示:

# coding: utf-8
import timeit # 序列化
x = """
say_hi.SerializeToString()
""" y = """
json.dumps(ppa)
""" z = """
simplejson.dumps(pl)
""" print min(timeit.repeat(stmt=x, setup="import say_hi_pb2;"
"say_hi = say_hi_pb2.SayHi();"
"say_hi.id = 13423;"
"say_hi.something = 'axiba';"
"say_hi.extra_info = 'xiba';", repeat=5, number=100000)) print min(timeit.repeat(stmt=y, setup="import json; "
"ppa={"
"'id': 13423,"
"'something': 'axiba',"
"'extra_info': 'xiba',"
"};", repeat=5, number=100000)) print min(timeit.repeat(stmt=z, setup="import simplejson; "
"pl={"
"'id': 13423,"
"'something': 'axiba',"
"'extra_info': 'xiba',"
"};", repeat=5, number=100000)) 输出:

1.08438277245
0.398800134659
0.707333087921

测试各库反序列化速度的代码如下所示:

# coding: utf-8
import timeit # 反序列化
x = """
say_hi.ParseFromString(p)
"""
y = """
json.loads(p1)
"""
z = """
simplejson.loads(p2)
""" print min(timeit.repeat(stmt=x, setup="import say_hi_pb2;"
"say_hi = say_hi_pb2.SayHi();"
"say_hi.id = 13423;"
"say_hi.something = 'axiba';"
"say_hi.extra_info = 'xiba';"
"p = say_hi.SerializeToString()", repeat=5, number=100000)) print min(timeit.repeat(stmt=y, setup="import json; "
"ppa={"
"'id': 13423,"
"'something': 'axiba',"
"'extra_info': 'xiba',"
"};"
"p1 = json.dumps(ppa)", repeat=5, number=100000)) print min(timeit.repeat(stmt=z, setup="import simplejson; "
"pl={"
"'id': 13423,"
"'something': 'axiba',"
"'extra_info': 'xiba',"
"};"
"p2 = simplejson.dumps(pl)", repeat=5, number=100000))
输出:

0.924090862274
0.492631912231
0.283575057983

从上面的数据可以看出,在我使用的版本3.1.0.post1的情况下,纯python实现pb序列化的速度略慢于json原生库两倍多,比simplejson库慢百分之30。在反序列化的速度测试中,依然是pb速度最慢两倍慢于原生json库,慢于simplejson库3倍多。这样看起来差距似乎被优化得不那么大了。记得以前在使用pb2.x库的时候,python序列化常慢于simplejson 3倍以上是非常正常的事情。各分析性能的文章都可以看到 too slow这个描述。由于二进制存储,以及pb独特的编码二进制的方式,从大小的角度来说,pb远远小于json,但是速度连json都快不过,我们有什么理由放弃使用方便可依赖的json转而使用pb呢?这的确没有什么说服力。

然而,pb官方提供了一个c++实现 runtime for python,按照实践一中的方法,安装好最新的pb库,并且按照文档编译好,然后安装python 的c++实现,就可以让pb使用c++实现进行序列化反序列。其他生成代码之类的所有不用变,调用代码也不用变,只需要安装好就可以了。安装好之后可以看到

Using /Users/piperck/Desktop/grpc/lib/python2.7/site-packages
Finished processing dependencies for protobuf==3.1.0

再次使用pip list查看我们的pb的时候可以发现,已经被该库替代。

让我们来重新运行一下 序列化和反序列化的代码:

序列化输出:
0.085785150528
0.403172016144
0.755691051483 反序列化输出:
0.090231180191
0.499733924866
0.297739028931

可以看到几乎比pure python的实现快近10倍。如果把序列化和反序列按照一次计算进行计算的话,也比我们通常使用的simplejson库快上4到5倍。再频繁调用序列化反序列化的应用中,可以说还是比较大的性能提升了,可以使得你的代码更轻更快,而且强类型映射可以检查错误。

别以为到这里就完了。还有一个更快速的库,但是现在只支持proto2,叫Pyrobuf Library。基于cPython实现,根据作者的说法,他要比c++ backend for python 还要快上2-4倍。让我们来尝试一下。

首先安装一下:

pip install pyrobuf

如果不行可以尝试使用:

pip install pyrobuf -v -v -v --upgrade --force --no-cache

安装好之后,按照官网的提示,使用pyrobuf 的 cli命令行界面,对.proto文件进行编译,得到.pxd和.pyx文件,还有.o和.c还有.so的文件(注意他们需要在同一个文件夹下)。

一切完成之后书写代码 测试速度:

import timeit

o = """
p.SerializeToString()
""" print min(timeit.repeat(stmt=o, setup=
"from hello_world_say_hi_proto import SayHi;"
"p = SayHi();"
"p.id = 3;"
"p.something = 'axiba';"
"p.extra_info = 'xiba'", repeat=5, number=100000)) o = """
p.ParseFromString(oi)
""" print min(timeit.repeat(stmt=o, setup=
"from hello_world_say_hi_proto import SayHi;"
"p = SayHi();"
"p.id = 3;"
"p.something = 'axiba';"
"p.extra_info = 'xiba';"
"oi = p.SerializeToString()", repeat=5, number=100000)) 输出:

0.069412946701
0.0525119304657

对比上面使用c++ backend的pb来看,反序列化勉强快到2倍,而序列化几乎没有什么特别大的优势。可能得益于使用最新版pb3.10的关系,在google的不断优化下,已经没有那么大差距了吧。因为使用cPython比较麻烦,还会多出不少编译文件。所以没什么提升的情况下,按照个人的需求使用吧。

Reference:

https://github.com/google/protobuf/tree/master/python  pb-github库

https://github.com/appnexus/pyrobuf  Pyrobuf Library

http://techblog.appnexus.com/blog/2015/12/22/pyrobuf-a-faster-python-protobuf-library-written-in-cython/  pyrobuf-a-faster-python-protobuf-library-written-in-cython

Protocol buffers--python 实践(二) protocol buffers vs json的更多相关文章

  1. 机器学习算法与Python实践之(二)支持向量机(SVM)初级

    机器学习算法与Python实践之(二)支持向量机(SVM)初级 机器学习算法与Python实践之(二)支持向量机(SVM)初级 zouxy09@qq.com http://blog.csdn.net/ ...

  2. P4语言编程快速开始 实践二

    参考:P4语言编程快速开始 上一篇系列博客:P4语言编程快速开始 实践二 Demo 2 本Demo所做的修改及实现的功能: 为simple_router添加一个计数器(counter),该计数器附加( ...

  3. WebSocket原理与实践(二)---WebSocket协议

    WebSocket原理与实践(二)---WebSocket协议 WebSocket协议是为了解决web即时应用中服务器与客户端浏览器全双工通信问题而设计的.协议定义ws和wss协议,分别为普通请求和基 ...

  4. Python实践:开篇

    一.概述 Python实践 是应用Python解决实际问题的案例集合,这些案例中的Python应用通常 功能各异.大小不一. 该系列文章是本人应用Python的实践总结,会不定期更新. 二.目录 Py ...

  5. Python实践之(七)逻辑回归(Logistic Regression)

    机器学习算法与Python实践之(七)逻辑回归(Logistic Regression) zouxy09@qq.com http://blog.csdn.net/zouxy09 机器学习算法与Pyth ...

  6. 机器学习算法与Python实践之(四)支持向量机(SVM)实现

    机器学习算法与Python实践之(四)支持向量机(SVM)实现 机器学习算法与Python实践之(四)支持向量机(SVM)实现 zouxy09@qq.com http://blog.csdn.net/ ...

  7. 机器学习算法与Python实践之(三)支持向量机(SVM)进阶

    机器学习算法与Python实践之(三)支持向量机(SVM)进阶 机器学习算法与Python实践之(三)支持向量机(SVM)进阶 zouxy09@qq.com http://blog.csdn.net/ ...

  8. 机器学习算法与Python实践之(五)k均值聚类(k-means)

    机器学习算法与Python实践这个系列主要是参考<机器学习实战>这本书.因为自己想学习Python,然后也想对一些机器学习算法加深下了解,所以就想通过Python来实现几个比较常用的机器学 ...

  9. (转) K-Means聚类的Python实践

    本文转自: http://python.jobbole.com/87343/ K-Means聚类的Python实践 2017/02/11 · 实践项目 · K-means, 机器学习 分享到:1 原文 ...

  10. 机器学习算法与Python实践之(六)二分k均值聚类

    http://blog.csdn.net/zouxy09/article/details/17590137 机器学习算法与Python实践之(六)二分k均值聚类 zouxy09@qq.com http ...

随机推荐

  1. [matlab] 21.灰色预测、线性回归分析模型与最小二乘回归 (转载)

    灰色预测的主要特点是只需要4个数据,就能解决历史数据少,序列的完整性以及可靠性低的问题,能将无规律的原始数据进行生成得到规律性较强的生成序列,易于检验 但缺点是只适合中短期的预测,且只适合指数级增长的 ...

  2. [TJOI2017]城市

    嘟嘟嘟 这题刚开始想复杂了,想什么dp去了,其实没那么难. 考虑断掉一条边,记分离出来的两棵子树为A和B,那么合并后的树的直径可能有三种情况: 1.A的直径. 2.B的直径 3.A的半径+边权+B的半 ...

  3. sql 查询所有子节点示例

    每天学习一点点 编程PDF电子书.视频教程免费下载:http://www.shitanlife.com/code <!-- 查询机构的所有子机构 --> <select id=&qu ...

  4. P1638 逛画展(直尺法)

    这道题是直尺法的模板题: #include<iostream> using namespace std; ; ; int n, m, a[maxn], vis[M]; int main() ...

  5. hadoop学习笔记贰 --HDFS及YARN的启动

    1.初始化HDFS :hadoop namenode -format 看到如下字样,说明初始化成功. 启动HDFS,start-dfs.sh 终于启动成功了,原来是core-site.xml  中配置 ...

  6. Ubuntu 14.04 LTS 安装 NVIDIA 显卡驱动后的屏幕亮度调节问题

    安装 Ubuntu,对于 NVIDIA 显卡,默认情况下会使用第三方开源驱动,并且一般情况下,第三方开源驱动和系统兼容性更好.由于 NVIDIA 显卡驱动不是开放的,所以对 Linux 系统的原生支持 ...

  7. Django适合做大用户量的系统吗?

    分几点来答: 1. 首先,这其实是个技术选型题. 做技术选型的时候不能单纯的考虑性能,应该优先考虑业务类型,以及团队水平.另外的话,框架只是其中一环,还有配套呢. 如果是数据驱动型,尤其是要用到关系型 ...

  8. dubbo源码阅读

    http://seekheap.com/posts/dubbo/dubbo-src-01-overview-and-debug-environment.html 先占坑

  9. [Spark][Python][Application]非交互式运行Spark Application 的例子

    非交互式运行Spark Application 的例子 $ cat Count.py import sys from pyspark import SparkContext if __name__ = ...

  10. 读写分离子系统 - C# SQL分发子系统 - Entity Framework支持

    A2D Framework增加了EF支持,加上原先支持ADO.NET: 支持EF方式 支持ADO.NET方式 这次来讲如何让Entity Framework变成nb的读写分离 1. 先设计EF模型, ...