当前位置: 首页 > news >正文

高效的ProtoBuf

一、背景

Google ProtoBuf介绍 这篇文章我们讲了怎么使用ProtoBuf进行序列化,但ProtoBuf怎么做到最高效的,它的数据又是如何压缩的,下面先看一个例子,然后再讲ProtoBuf压缩机制。

二、案例

网上有各种序列化方式性能对比,我们这里仅对比一下JSON序列化和ProtoBuf序列化。

原始数据如下

{
"id":1,
"name":"qingcai18036",
"email":"qingcai18036@yeah.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

  • Type=1 :如果是 int32采用Varints编码编码,如果是sint32采用ZigZag编码(因为要对负数进行有效压缩)。

  • Type=1:分配64位大小空间,采用小端模式

  • Type=5:分配32位大小空间,采用小端模式

  • Type=2:string是一个指定长度的编码,key+length+content,key编码采用统一的方式,length(内容长度)采用varints编码,content就是由length指定长度的byte。所以其对字符串本身的内容并不压缩?

五、总结

ProtoBuf采用了Varint、ZigZa压缩算法,二制制的数据就非常紧凑,并且比JSON少了{}符号、字段名、所以用ProtoBuf序列化后整体体积会更小,这样网络传输更快,更高效。

http://www.lryc.cn/news/183015.html

相关文章:

  • 删除SQL记录
  • 数据结构--》探索数据结构中的字符串结构与算法
  • 云安全之等级保护详解
  • VUE状态持久化,储存动态路由
  • 微信小程序代驾系统源码(含未编译前端,二开无忧) v2.5
  • 1797_GNU pdf阅读器evince
  • 网络-跨域解决
  • git提交代码的流程
  • 【SpringBoot】配置文件详解
  • 一文讲懂-五险一金
  • 判断三条边是否构成三角形(Python实现)
  • The directory ‘*‘ or its parent directory is not owned by the current user
  • leetcode做题笔记162. 寻找峰值
  • nginx负载转发源请求http/https:X-Forwarded-Proto及nginx中的转发报头
  • Docker compose插件安装
  • 【数据结构与算法】树、二叉树的概念及结构(详解)
  • 函数指针数组指针(指向函数指针数组的指针)
  • 经典算法-----汉诺塔问题
  • 博客之站项目测试报告
  • k8s晋级之管理容器的计算资源
  • 计算机竞赛 深度学习火车票识别系统
  • 盒子阴影和网页布局
  • Ph.D,一个Permanent head Damage的群体
  • visual studio禁用qt-vsaddin插件更新
  • Docker通过Dockerfile创建Redis、Nginx--详细过程
  • 关于使用 uniapp Vue3 开发分享页面 语法糖 setup 开发获取ref踩坑
  • Springboot+vue的时间管理系统(有报告)。Javaee项目,springboot vue前后端分离项目。
  • 企业如何实时监管员工聊天转账行为
  • 2.2.3.1vim + ctags + cscope + taglist
  • JAVA面经整理(4)