李梦,丰田rav4,寒假生活-雷竞技注册_雷竞技注册官网_雷竞技电竞

频道:小编推荐 日期: 浏览:228

Protocol Buffers (ProtocolBuffer/ protobuf )是Google公司开发的一种数据描绘言语,相似于XML能够将结构化数据序列化,可用于数据存储、通信协议等方面。现阶段支撑C++、JAVA、Python等三种编程言语。

为什么不只用XML?同XML比较,Protocol buffers在序列化j9d95结构化数据方面有许多长处(google官方提出):

  • 更李梦,丰田rav4,寒假日子-雷竞技注册_雷竞技注册官网_雷竞技电竞简略
  • 数据描绘文件只帕西亚需本来的1/10至1/3
  • 解析速度是本来的20倍至100倍
  • 减少了二义性
  • 生成了更简略在编程中运用的数据拜访类

protocol buffers简介

protocol buffer是google的一个开源项目,它是用于结构化数据串行化的灵敏、高效、主动的办法,例如XML,不过它比xml更小、更快、也更简略。你能够界说自己的数据结构,然后运用代码生成器生成的代码来读写这个数据结构。你乃至能够在无需重新部署程序的情况下更新数据结构

protocol buffers是怎么作业的

在.proto文件界说音讯,message是.proto文件最小的逻辑单元,由一系列name-value键值对构成。下面的.proto文件黄境清界说了一个"人"的音讯:

message Person {
required string name = 1;
required int32 id = 2;
optional string email = 3;
enum PhoneType {
MOBILE = 0;
HOME = 1;
WORK = 2;
}
message PhoneNumber {
required string number李梦,丰田rav4,寒假日子-雷竞技注册_雷竞技注册官网_雷竞技电竞 = 1;
optional PhoneType type = 2 [default = HOME];
}
repeated PhoneNumber phone = 4;
}

message音讯包括一个或多个编号仅有的字段,每个字段由字段约束,字段类型,字段名和编号四部分组成,字段约束分为:opt南京天洑软件有限公司ional(可选的)、required(有必要的)以及repeated(重复的)。界说好音讯后,运用ProtoBuf编译器生成C++对应的.h和.cc文件,源文件供给了message音讯的序列化和反序列化等办法:

# 序列化数据
Perso欧美白叟n person;
person.set_name("John Doe");
person.set_id(1234);
person.set_email("jdoe@example.com");
fstream output("myfile", ios::out | ios::binary);
person.SerializeToOstream(&output);
# 反序列化数据
fstream input("myflwscamile", ios::in | ios::binary);
Person 李秉洁person;
person.ParseFromIstream(&input);cout << "Name: " << person.name() << endl;cout << "E-mail: " << person.email() << endl;

为什么不直接运用XML

同XML比较,Protobuf的优势在于高性能,它以高效的二进制存储办法比XML小3到10倍,快20到100倍,原因在于:

  • ProtoBuf序列化后所生成的二进制音讯十分紧凑
  • ProtoBuf封解包进程十分简略

Protobuf序列化

Varint简介

Varint李梦,丰田rav4,寒假日子-雷竞技注册_雷竞技注册官网_雷竞技电竞 是一种紧凑的表明数字的办法。它用一个或多个字节来表明一个数字,值越小的数字运用越少的字节数。这能减少用来表明数字的字节数。

比方关于int32类型的数字,一般需求4个byte来表明,可是选用Varint关于很小的int32类型的数字,则可美好小区七号楼以用1个byte来表明。当然凡事都有好的李梦,丰田rav4,寒假日子-雷竞技注册_雷竞技注册官网_雷竞技电竞也有欠好的一面,朱圣伟选用Varint表明法,大的数字则需求5个byte来表明。从核算的视点来说,一般不会一切的音讯中的数字都是大数,因而大布罗梅尔大都情况下,选用Varint后能够用更少的字节数来表明数字信息。

Varint格局

Varint中的每个byte的最高位bit有特别的意义,假如该位为1,表明后续苞的byte也是该数字的一部分,假如该位为0则完毕,其他的7个bit都用来表明数字。因而小于128的数字都能够用一个byte表明,大于128的数字会用两个字节来表明。

Varint编解码

比方数值300用Varint来表明便是:1010洪志明 1100 0000 0010。下图演示了Google Protocol Buffer解析Varint表明的300的进程,因为Google Protocol Buffer选用小端字节序仟校网,所以实践存储的字节次序是反过来的:

Google Protocol Buffer序列化

音讯经过序列化后会成为一个二进制数据流,该流中的数据为一系列的Key-Value对。如下图所示:

选用这种Key-Pair结构无需运用分隔符来切割不同的 Field。关于可选的Field,假如音讯中不存在该Field,那么在终究的Message Buffer中就没有该Field,这些特性都有助于节省音讯本精慌身的巨细。Key 用来标识详细的Field,在解包的时分ProtoBuf依据Key就能够知道相应的Value应该对应于音讯中的哪一个Field。Key由字段的编号和字段的线性传输类型构成(field_number << 3) | wire_type

wire_typeMeaningUsed For0Varintint32, int64, uint32, uint64, sint32, sint64, bool, enum164-bitfixed64, sfixed64, double2Length-delimistring, bytes, embedded messages, packed repeated fields3Start groupGroups (deprecated)4End groupGroups (deprecated)532-bitfixed32, sfixed32, float

  • Google Protocol Buffer选用zigzag编码来用无符号数来表明有符号数字,zigzag选用正数和负数交织的办法来一起表明无符号数来表明有符号数字,如图所示:

运用zigzag编码,绝对值小的数字,不管正负都能够选用较少的byte来表明,充分利用了Varint这种技能。

  • 其他的数据类型,比方字符串等则选用相似数据库中的varchar的表明办法,即用一个varint表明长度,然后将其余部分紧跟在这个长度部分之后即可。

ProtoBuf编码与XML编码比照

音讯界说如下:

package lm;
message helloworld
{
required int32 id = 1; 李梦,丰田rav4,寒假日子-雷竞技注册_雷竞技注册官网_雷竞技电竞// ID
required string str = 2; // str
optional int32 opt = 3209263; //optional field
}

假设有一条helloworld音讯id=101 str="hello",那么用Protobuf序列化后的字节序列为:

08 65 12 06 48 65 6C 6C 6F 77

而假如用XML,则相似这样:

31 30 31 3C 2F 69 64 3E 3C 6E 61 6D 65 3E 68 65
6C 6C 6F 3C 2F 6E 61 6D 65 3E 3C 2F 68 65 6C 6C
6F 77 6F 72 6C 64 3E
总共 55 个字节,这些古怪的数字需求略微解释一下,其意义用 ASCII 表明如下:

101
hello

ProtoBuf封解包

首要咱们来了解一下XML的封解包进程。XML需求从文件中读取出字符串,再转换为XML文档目标结构模型。之后再从XML文档目标结构模型中读取指定节点的字符串,最终再将这个字符串转换成指定伊周电子版下载类型的变量,这个进程十分杂乱。其间将XML文件转换为文档目标结构模型的进程一般需求完结词法文法分李梦,丰田rav4,寒假日子-雷竞技注册_雷竞技注册官网_雷竞技电竞析等很多消李梦,丰田rav4,寒假日子-雷竞技注册_雷竞技注册官网_雷竞技电竞耗 CPU 的杂乱核算。

反观Protobuf,它只需求简略地将一个二进制序列依照指定的格局读取到C++对应的结构类型中就能够了。从上一节的描绘能够看到,音讯的解码进程也能够经过几个位移操作组成的表达式核算即可完结,速度十分快。

上面比如中,Protob臭逼uf解包helloworld音讯的进程能够用下图表明:

整个解析进程需求P推开窗看天边白色的鸟rotobuf自身的结构代码和由Protobuf编译器生成的代码共同完结。其间Message以及Message_lite作护陵铠为通用的流程结构,CodedInputStreamWireFormatLite供给了对二进制数据的解码功用,并且Protobuf的解码能够经过几个简略的数学运算完结,无需杂乱的词法语法分析,因而图中ReadTag()等办法都十分快。相关于XML的解析,整个调用途径上的其他类和办法都十分简略,这也便是ProtoBuf封解包速度敏捷的原因。