Protobuf的简约介绍、使用和剖析

 

一、protobuf是什么?

        protobuf(谷歌 Protocol
Buffers)是Google提供一个所有高速的商事数据交流格式工具库(类似Json),但相比较于Json,Protobuf有更高的中转功效,时间效用和空中功能都是JSON的3-5倍。前面将会有简短的demo对于这二种格式的多寡转发效用的自查自纠。但以此库如今接纳还不是太流行,据说Google里面很多产品都有使用。

 

二、protobuf有什么?

        Protobuf
提供了C++、java、python语言的支撑,提供了windows(proto.exe)和linux平台动态编译生成proto文件对应的源文件。proto文件定义了协商数据中的实体结构(message
,field)

关键字message: 代表了实体结构,由五个音讯字段(field)组成。

信息字段(field): 包括数据类型、字段名、字段规则、字段唯一标识、默认值

数据类型:常见的原子类型都襄助(在菲尔德(Field)Descriptor::kTypeToName中有定义)

字段规则:(在FieldDescriptor::kLabelToName中定义)

        required:必须初阶化字段,如若没有赋值,在数码连串化时会抛出特别

        optional:可选字段,可以不必开端化。

        repeated:数据能够另行(相当于java 中的Array或List)

        字段唯一标识:连串化和反系列化将会采纳到。

默认值:在概念音讯字段时方可给出默认值。

 

三、protobuf有什么用?

       
Xml、Json是眼下常用的数据交流格式,它们向来运用字段名称保养系列化后类实例中字段与数码里面的照耀关系,一般用字符串的样式保留在连串化后的字节流中。信息和音讯的定义相对独立,可读性较好。但系列化后的数目字节很大,系列化和反体系化的时日较长,数据传输功效不高。

       
Protobuf和Xml、Json系列化的措施不同,采纳了二进制字节的体系化形式,用字段索引和字段类型通过算法总计拿到字段在此之前的涉及映射,从而达到更高的时间功用和空间功能,特别吻合对数码大小和传输速率相比灵敏的场子使用。

四、Protobuf在Android上的应用

1、创制proto文件,定义音信的实业结构

2、编译proto文件生成对应的java文件

3、添加protobuf-java-2.5.0.jar到android工程

4、在android中落实对信息结构的体系化/反体系化  

 

五、Protobuf与json的对比

1、创建product.proto文件

        定义了多少个Message(ProductInfo、PhoneInfo、沃特(Wat)ch)信息结构

图片 1

2、信息结构对应的java类(ProductInfo、PhoneInfo、沃特ch)

图片 2

 

3、音讯结构和java对象赋值

PhoneName:” idol3”

Price:2000

Top:1

 

WatchName:” tcl watch”

Price:1000

Top:1

 

4、JSON字符串

 

{“phone”:{“phoneName”:”idol3″,”price”:2000,”top”:1},”watch”:{“watchName”:”tcl
wtch”,”top”:1,”price”:1000}}

 

5、Protobuf转化后的二进制文件

图片 3

 

空中效用

Json:107个字节

Protobuf:32个字节

 

时刻效能

Json序列化: 1ms ,  反连串化:0ms

Protobuf 序列化: 0ms 反类别化:0ms

 

将public List<Phone> list和repeated PhoneInfo phoneInfoList
=3;都赋值为1000个PhoneInfo

 

空间功能

Json:4206个字节

Protobuf:1332个字节

 

日子效率

Json序列化: 4ms ,  反系列化:1ms

Protobuf 序列化: 1ms 反系列化:0ms

六、protobuf的概括解析

1、优缺点

亮点:通过以上的时间功用和空间效用,可以看到protobuf的空间功效是JSON的2-5倍,时间效能要高,对于数据大小敏感,传输效率高的模块可以利用protobuf库

 

症结:消息结构可读性不高,系列化后的字节连串为二进制连串不可能简单的剖析有效性;近期选用不常见,只帮助java,C++和Python;

 

2、数据类别化/反系列化

a、规则:

protobuf把音信结果message也是经过
key-value对来表示。只是其中的key是运用一定的算法总结出来的即因此各类message中各类字段(field
index)和字段的数据类型举办演算得来的key = (index<<3)|type;

type类型的附和关系如下:

 

Type

Meaning

Used For

0

Varint

int32, int64, uint32, uint64, sint32, sint64, bool, enum

1

64-bit

fixed64, sfixed64, double

2

Length-delimited

string, bytes, embedded messages, packed repeated fields

3

Start group

groups (deprecated)

4

End group

groups (deprecated)

5

32-bit

fixed32, sfixed32, float

 

Value会遵照数据类型的不等会有二种表现格局:

对此各个int,bool,enum类型,value就是Varint

对此string,bytes,message等等类型,value就是length+原始内容编码

 

Varints是一种紧凑表示数字的法子。它用一个或者多少个字节表示一个数字,值越小的数字字节数越少。绝对于传统的用4字节意味着int32类型数字,Varints对于小于128的数值都得以用一个字节表示,大于128的数值会用更多的字节来代表,对于很大的数量则需要用5个字节来表示。

 

Varints算法描述:
每一个字节的参天位都是有独特含义的,假设是1,则表示继续的字节也是该数字的一有的;假使是0,则截止

b、demo生成的的二进制文件反系列化。

第1个字节 (0A)

字段索引(index):         0A = 0001010  0A>>3 = 001 = 1

数据类型(type):           0A = 0001010&111  = 2 (String);

 

第2个字节 (0C)

字符串长度(length):      0E = 12;

字符串:                         0A 05 69 64 6F 6C 33 10 01 18 BD 0F

 

第3个字节 (0A)

因为字符串是源于phoneInfo属于嵌套类型

字段索引(index):         0A = 0001010  0A>>3 = 001 = 1

数据类型(type):           0A = 0001010&111  = 2 (String);

第4-9个字节(69 64 6F 6C 33)

字符串长度(length):    05 = 5

字符串:                       69 64 6F 6C 33 = idol3

 

第10个字节 (10)

字段索引(index):         10 = 00010000    10A>>3 = 0010 = 2

数据类型(type):           10 = 00010000&111  = 0 (Varints);

 

第11个字节  (01)

Varints:                          01 = 00001字节的参天位为0 整数截止

Value:                            1;

 

第12个字节(18)

字段索引(index):           18 = 00011000    18>> 00011 = 3

数据类型(type):           18 = 00011000&111  = 0 (Varints);

 

第13个字节(D0)

高高的位为1,整数总结到下一个字节

 

第14个字节(0F)

参天位为0,整数总结停止

Value:为11111010000 =2000

 

C、反系列化结果

phoneinfo为

phoneName = “idol3”

top = 1

price = 2000;

 

同一的点子watchInfo为:

watchName = “tcl name”

top = 1

price=2000 

3、时间效能

经过protobuf体系化/反连串化的过程能够汲取:protobuf是透过算法生成二进制流,序列化与反系列化不需要分析相应的节点属性和剩余的叙述音讯,所以体系化和反连串化时间效用较高。

4、空间功用

xml、json是用字段名称来规定类实例中字段之间的独立性,所以连串化后的数码多了成千上万描述音讯,扩展了系列化后的字节系列的容量。

 

Protobuf的系列化/反连串化过程可以汲取:

protobuf是由字段索引(fieldIndex)与数据类型(type)总括(fieldIndex<<3|type)得出的key维护字段之间的映射且只占一个字节,所以比较json与xml文件,protobuf的连串化字节没有过多的key与叙述符信息,所以占用空间要小很多。

七、Protobuf的源码分析

1、protobuf在java使用的连串化流程

 

java程序调用parserFrom(byte[]
data)开首字节系列的反系列,Java程序通过调用编译生类GenerateMessage中的wirteTo()方法起初将系列化后的字节写入输出流中

 图片 4

图片 5

GenerateMessage
继承AbstractMessage类,体系化最后在AbstractMesssage中做到,连串化的实现过程:

a、遍历对象中Message结构()

调用AbstractMessage类中的writeTo()方法

 图片 6

b、 体系化Message中每一个字段

调用CodeOutputStream类中的writeMessageSetExtension()方法

图片 7

 

c、 对于Varints  Tag 的连串化流程:

调用CodeOutputStream类中的writeUInt32()方法

图片 8

调用CodeOutputStream类中的WriteRawVarint32()方法

图片 9

 

d、 对于非Varints Tag的连串化

调用CodeOutputStream类中的WriteTag()方法

图片 10 

图片 11

 

具体的连串化实现都在CodedOutputStream中成就

 

2、java使用protobuf 的反连串化流程分析

java程序通过调用parserFrom(byte[] data)起头反连串化

 图片 12

图片 13

实际在com.google.protobuf. AbstractParser类中实现

 

图片 14

 

图片 15

图片 16

 

图片 17

 

 

最终在com.google.protobuf.CodedInputStream类中形成反系列化

3、动态编译

以windows下用protoc.exe工具实现proto文件编译为例,protoc.exe是用C++实现。在控制台执行命令:

图片 18

编译的流水线:

检查proto的语法规则

将proto的文本中的message结构转换为GenerateMessage类的子类,并促成Builder接口。

编译流程

Main.cc中的main()方法

图片 19

 

Command_line_interface.cc中的Run()方法

图片 20

 

Import类中Import()

图片 21

 

在Descriptor中完成message音信的采集和转化。

相关文章

网站地图xml地图