内容简介:Protocal Buffers是谷歌开发的一种数据描述语言,能够将结构化数据序列化,可用于数据存储、通信协议等方面。因此它的官方网址为:
Protocal Buffers是谷歌开发的一种数据描述语言,能够将结构化数据序列化,可用于数据存储、通信协议等方面。 Protobuf 是跨语言的,并且自带了一个编译器( protoc
),只需要用它进行编译,可以编译成 Java、 python 、C++、C#、Go 等代码,然后就可以直接使用,不需要再写其他代码,自带有解析的代码。
因此 Protobuf 的使用非常方便,并且还有一个重要的特点:它比 Json 格式更快,且占用空间更小。
它的官方网址为: https://github.com/protocolbuffers/protobuf
Protobuf的安装
Protobuf的安装总共分为两步:
- 安装 Protobuf 的自带编译器:
protoc
- 安装对应语言版本的客户端
Step1:安装Protobuf自带的编译器
Protobuf自带编译器的安装可以自己在本机上通过源代码编译安装,也可以直接下载官方相应的编译好的二进制包,开箱即用。官方编译好的包下载地址为: https://github.com/protocolbuffers/protobuf/releases/tag/v3.7.1
如上图所示,这个页面有各种语言的 protobuf 包进行下载,分别表示如下:
-
all
表示所有语言的包,后面cpp
表示 C++ 语言,csharp
表示 C# 语言 - 各语言包之后是各平台编译的二进制包,对应有 Linux、MacOS 和 Windows 操作系统的编译结果
- 最后是源码
这里如果下载了相应语言的 protobuf 包,需要通过编译安装方式进行安装,以 Python 为例:
# 下载相应的python版本:protobuf-python-3.7.1.zip wget https://github.com/protocolbuffers/protobuf/releases/download/v3.7.1/protobuf-python-3.7.1.zip # 解压缩 unzip protobuf-python-3.7.1.zip cd protobuf-3.7.1 # 编译安装protoc ./configure sudo make && sudo make install # 安装python语言客户端 cd python python setup.py build --cpp_implementation python setup.py test --cpp_implementation python setup.py install --cpp_implementation
如果上面编译报错的话,可能需要升级 gcc 的版本:
yum install centos-release-scl -y yum install devtoolset-7 -y scl enable devtoolset-7 bash gcc --version
同时还需要注意的是,上面实际上 既编译安装了protobuf的编译器protoc,又安装了protobuf的python语言客户端 。
还有一点非常重要:安装 python 语言客户端的时候,如果没有指定 --cpp_implementation
这个参数,那么安装的是 纯python版本
的解析器,这个解析速度并不快,甚至比 json 还要慢,因此安装的时候一定要带这个参数,相当于是以 C++ 的运行时来解析 protobuf 格式的数据,会比纯 python 方式快 10
倍以上。
如果这里不想自己编译,那就直接下载官方编译好的包:
# 下载官方编译好的包 wget https://github.com/protocolbuffers/protobuf/releases/download/v3.7.1/protoc-3.7.1-linux-x86_64.zip # 新建目录 mkdir protobuf # 解压到指定目录 unzip protoc-3.7.1-linux-x86_64.zip -d protobuf # 进入目录 cd protobuf/bin # 查看版本 ./protoc --version
此时,进入 bin
目录下就可以看到已经编译好的 protoc
可执行文件了。
Step2:安装Protobuf语言客户端
安装 python 的客户端,直接用 pip
命令即可安装:
sudo /usr/local/bin/pip3 install protobuf
这里通过 pip
命令安装默认是加了 --cpp_implementation
C++ 运行时参数的,注意仅在 protobuf 3.2
及以上版本是默认加的,其他旧版本是纯 python 的,没有加该参数进行优化。
Protobuf的使用
protobuf 2与 protobuf 3 的语法相差比较大,具体可参考 这篇文章 。下面以 protobuf 3 为例进行说明。
新建proto文件
proto
文件是用来指定数据格式的,示例 addressbook.proto
如下:
syntax = "proto3"; package tutorial; message Person { string name = 1; int32 id = 2; string email = 3; enum PhoneType { MOBILE = 0; HOME = 1; WORK = 2; } message PhoneNumber { string number = 1; PhoneType type = 2; } PhoneNumber phones = 4; }
用protoc编译器生成对应的语言类
输入如下内容,可以看到如下结果:
protoc --help
也就是说通过这个二进制的可执行命令可以将前面定义的数据格式 addressbook.proto
生成各种语言的引用包。
# 在当前目录下生成addressbook.proto对应的python格式的引用文件 protoc --python_out=. addressbook.proto
可以看到在当前文件夹下面生成了一个 addressbook_pb2.py
文件,后面在python程序中引用这个文件,就可以进行相应的序列化和反序列化操作了。
需要注意的是, protoc 编译器的版本与相应语言解析 protobuf 的客户端版本最好一致,不然会有一些莫名的 bug 。
Protobuf与Json性能的比较
性能比较采用的 工具 是 line_profiler
,它可以逐行打印函数每一行运行所花费的时间。
安装该工具:
sudo /usr/local/bin/pip3 install line_profiler
然后写测试脚本 test.py
如下:
import json import addressbook_pb2 # 对这个函数进行性能测试,在前面加一个装饰器 @profile def parse_json(input_data): # json序列化 data_json = json.dumps(input_data) # json反序列化 result = json.loads(data_json) return result @profile def parse_protobuf(input_data): # protobuf序列化 data_protobuf = input_data.SerializeToString() # protobuf反序列化 result_protobuf.ParseFromString(data_protobuf) return result_protobuf if __name__ == "__main__": # 构造json格式数据 data = { "name": "xiaowang", "id": 1, "email": "123@qq.com", "phones": { "number": "156888888" } } # 构造protobuf格式数据 person = addressbook_pb2.Person() person.name = data["name"] person.id = data["id"] person.email = data["email"] person.phones.number = data["phones"]["number"] person.phones.type = 0 # 初始化解析protobuf解析类 result_protobuf = addressbook_pb2.Person() # 每个函数执行1000次 for number in range(1000): parse_json(data) parse_protobuf(person)
输入如下命令执行该脚本:
kernprof -l -v test.py
得到结果如下:
可以看到无论是序列化还是反序列化, protobuf 都比 json 快 5
倍左右。
Protobuf使用注意事项
如果定义了两个 proto 文件,里面写的是同样的 package ,且有同样的变量名,那么在 python 同时引用这两个 pb2.py 文件的时候会报错。
例如再新建一个 addressbook1.proto
文件,内容如下:
syntax = "proto3"; package tutorial; message Person { string name = 1; int32 id = 2; string email = 3; }
同样
protoc --python_out=. addressbook1.proto
生成一个 addressbook1_pb2.py
文件。在python中同时引用这两个文件,会报错如下:
解决办法是: 如果有两个proto文件里面有相同的变量名,在package里面写不一样的包名即可 。这样重新生成的 pb2.py 文件,再同时引用的时候就不会报错了:
【版权声明】
本文首发于戚名钰的博客,欢迎转载,但是必须保留本文的署名戚名钰(包含链接)。如您有任何商业合作或者授权方面的协商,请给我留言:qimingyu.security@foxmail.com
欢迎关注我的微信公众号:科技锐新
本文永久链接: http://qimingyu.github.io/2019/05/02/Protobuf的使用及性能对比测试/
以上所述就是小编给大家介绍的《Protobuf的使用及性能对比测试》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- Kubernetes 存储性能对比
- 快排和堆排性能对比
- 性能压测工具选型对比
- 性能对比:ReentrantLock vs Synchronized
- Mobx 与 Redux 的性能对比
- Firefox 和 Chrome 性能测试对比
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。