Protobuf的使用及性能对比测试

栏目: 服务器 · 发布时间: 4年前

内容简介: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的使用及性能对比测试

如上图所示,这个页面有各种语言的 protobuf 包进行下载,分别表示如下:

  • all 表示所有语言的包,后面 cpp 表示 C++ 语言, csharp 表示 C# 语言
  • 各语言包之后是各平台编译的二进制包,对应有 Linux、MacOSWindows 操作系统的编译结果
  • 最后是源码

这里如果下载了相应语言的 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

Protobuf的使用及性能对比测试

也就是说通过这个二进制的可执行命令可以将前面定义的数据格式 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的使用及性能对比测试

可以看到无论是序列化还是反序列化, protobuf 都比 json5 倍左右。

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中同时引用这两个文件,会报错如下:

Protobuf的使用及性能对比测试

解决办法是: 如果有两个proto文件里面有相同的变量名,在package里面写不一样的包名即可 。这样重新生成的 pb2.py 文件,再同时引用的时候就不会报错了:

Protobuf的使用及性能对比测试

【版权声明】

本文首发于戚名钰的博客,欢迎转载,但是必须保留本文的署名戚名钰(包含链接)。如您有任何商业合作或者授权方面的协商,请给我留言:qimingyu.security@foxmail.com

欢迎关注我的微信公众号:科技锐新

Protobuf的使用及性能对比测试

本文永久链接: http://qimingyu.github.io/2019/05/02/Protobuf的使用及性能对比测试/


以上所述就是小编给大家介绍的《Protobuf的使用及性能对比测试》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

知识的边界

知识的边界

[美] 戴维·温伯格 / 胡泳、高美 / 山西人民出版社 / 2014-12-1 / 42.00元

大数据时代反思知识 因为事实不再是事实,专家随处可见 所有确定性都被连根拔起,话题再无边界,没有人对任何事情能达成一致。 在互联网的引领下,知识现在已经具有了社交性,流动且开放。温伯格向我们展示了这些特点如何可以为我们所用。 ——马克•贝尼奥夫(云计算之父,著有《云攻略》) 这本富有洞见的著作,奠定了温伯格作为数字时代最重要的思想家之一的地位。如果你想要理解信息洪流涌......一起来看看 《知识的边界》 这本书的介绍吧!

HTML 编码/解码
HTML 编码/解码

HTML 编码/解码

MD5 加密
MD5 加密

MD5 加密工具

UNIX 时间戳转换
UNIX 时间戳转换

UNIX 时间戳转换