《关于加快网站群建设的通知》,h5游戏大全在线玩,长沙网站关键词seo,微信里的小程序不见了一、背景
Google ProtoBuf介绍 这篇文章我们讲了怎么使用ProtoBuf进行序列化#xff0c;但ProtoBuf怎么做到最高效的#xff0c;它的数据又是如何压缩的#xff0c;下面先看一个例子#xff0c;然后再讲ProtoBuf压缩机制。
二、案例
网上有各种序列化方式性能对比#…一、背景
Google ProtoBuf介绍 这篇文章我们讲了怎么使用ProtoBuf进行序列化但ProtoBuf怎么做到最高效的它的数据又是如何压缩的下面先看一个例子然后再讲ProtoBuf压缩机制。
二、案例
网上有各种序列化方式性能对比我们这里仅对比一下JSON序列化和ProtoBuf序列化。
原始数据如下
{
id:1,
name:qingcai18036,
email:qingcai18036yeah.net
}
序列化后十六进值如下 可以看出使用ProtoBuf序列化后的十六进值长度要小很多。
三、基础概念
1、大小端模式
大端模式数据的高字节保存在内存低地址中数据的低字节保存在内存高地址中。
小端模式数据的高字节保存在内存高地址中数据的低字节保存在内存的低地址中。
这里记住小端模式的存储是 高高低低小端模式也是ProtoBuf协议中使用的模式。
十六进制数据 0x12345678,大小端模式在内存的存放如下 2、ZigZag编码
ZigZag是一种对负数友好的压缩算法可以压缩掉多余为0的比特位。
正数byte a 11; 存储用原码表示二进制值0000 1011
ZigZag对正数进行编码 整体数据左移1位 0001 0110 符号位移到最低位 0001 0110
负数byte a -11; 存储用补码表示二进值 11110101 原码10001011- 反码11110100- 补码11110101
ZigZag对负数进行编码 1、左移1位11101010 2、符号位移到最低位11101011 3、除最后一位外全部取反00010101
ZigZag 对负数-11增加了前导三个0可以压缩掉
3、 Varint编码
Varint是一种使用一个或多个字节序列化整数的办法对于32位的整数用Varint编码后为1~5个字节小的数字使用1个byte大的数字使用5个byte。但实际场景中小数字使用率大于大数字这样就达到压缩效果而Java序列化Int需要用4个byte。
Varint每个字节中每一比特位定义 第8位最高位1表示后续的字节也是该数字的一部分 0表示该数字结束。
第1~7位表示具体数字值
Varint编码例子
小于128的数字用一个字节就可以表示大于128的数比如1234需要用到2个字节表示。
1234 二进制值 10011010010
在Java中Int类型占用4个字节如果直接使用Java序列化存储如下
00000000 00000000 00000100 11010010
前面有21个0造成空间的浪费可以对空位0进行压缩节省空间。
Varint编码从右往左每隔7位取一片段并补上标识位再将若干片段从左往右排序。
1、从右往左取7位 1010010并补上标记位1表示后续还有数据 11010010
2、再续继取7位 000100 1并补上标记位0表示后续没有数据00001001
3、再往左已经全部是0了就不管了。
4、然后将上面形成的两个片段从左往右排列小端模式 11010010 00001001
最终整数1234做Varint编码后二进制为 11010010 00001001
四、ProtoBuf协议 1、ProtoBuf序列结构 2、Key定义 (field_number 3) | wire_type field_number 是 定义在proto文件中字段的序号
3、wire_type Type1 如果是 int32采用Varints编码编码如果是sint32采用ZigZag编码因为要对负数进行有效压缩。 Type1分配64位大小空间采用小端模式 Type5分配32位大小空间采用小端模式 Type2string是一个指定长度的编码keylengthcontentkey编码采用统一的方式length内容长度采用varints编码content就是由length指定长度的byte。所以其对字符串本身的内容并不压缩
五、总结
ProtoBuf采用了Varint、ZigZa压缩算法二制制的数据就非常紧凑并且比JSON少了{}符号、字段名、所以用ProtoBuf序列化后整体体积会更小这样网络传输更快更高效。