设为首页 加入收藏

TOP

Protobuf的简单介绍、使用和分析(二)
2019-09-17 18:55:39 】 浏览:75
Tags:Protobuf 简单 介绍 使用 分析
,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()方法开始将序列化后的字节写入输出流中

 

GenerateMessage 继承AbstractMessage类,序列化最终在AbstractMesssage中完成,序列化的实现过程:

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

调用AbstractMessage类中的writeTo()方法

 

b、 序列化Message中每一个字段

调用CodeOutputStream类中的writeMessageSetExtension()方法

 

c、 对于Varints  Tag 的序列化流程:

调用CodeOutputStream类中的writeUInt32()方法

调用CodeOutputStream类中的WriteRawVarint32()方法

 

d、 对于非Varints Tag的序列化

调用CodeOutputStream类中的WriteTag()方法

 

 

具体的序列化实现都在CodedOutputStream中完成

 

2、java使用protobuf 的反序列化流程分析

java程序通过调用parserFrom(byte[] data)开始反序列化

 

具体在com.google.protobuf. AbstractParser类中实现

 

 

 

 

 

最后在com.google.protobuf.CodedInputStream类中完成反序列化

3、动态编译

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

编译的流程:

检查proto的语法规则

将proto的文件中的message结构转换为GenerateMessage类的子类,并实现Builder接口。

首页 上一页 1 2 3 下一页 尾页 2/3/3
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇C# 函数式编程及Monads.net库 下一篇Rabbitmq~对Vhost的配置

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目