Protocol Buffers 介绍(二)

转载请注明出处 http://blog.csdn.net/manchew/article/details/39523197


上节讲了什么是Protocol Buffers,以及如何使用。 我们知道Protocol Buffers有着高性能,低空间占用,那么,它到底是如何做到的呢?本节就深入了解一下它的实现机制。

其实任何序列化,反序列化的东东,不过就是它们的编解码过程,那么我们看看Protocol Buffers如何在Google大牛的思想下妙笔开花。


在介绍之前,先来普及几个概念:

protocol buffers里面的字段最终编码后序列化为以key-value的形式被读取或保存。

Wire Type 用来标识我们以什么方式去解析字段的方法,主要的Wire Type有以下六种,到底Wire Type的中文名叫什么,确实也不太好翻译,哪位大婶知道好的名字,不妨说来听听。


可以看到Wire type会包含很多种字段类型,换句话讲就是,int32, int 64这些都用Varint的方式去解析,而fixed64这些都会用64-bit的这种方式去解析,说这些比较抽象,之后我会用例子来说明一下。

Key用来标识后面的数据是哪个字段的值,Key被定义为( tag << 3 ) | wire type, 这样的话key的最后面3bit就是wire type, key的值右移3bit后就得到tag的值


64-bit编解码

如果定义一个message test,代码如下:

message Test
{
    required fixed64 id = 1;
}
接下来调用

...
int main(){
    Test msg,
     msg.set_id(5);
}
...
内存模型应该是这个样子的



tag为00001,对应id这个字段,wire type为001,后面的数据解析方式为64-bit的形式,64-bit的意思是,64-bit为value的值,所以id的值为5,注意Google Protocol Buffers是按小端存取数据的。虽然后面56bit都为0,但这里还是要占用7个字节。这样显得有点儿浪费空间,前面也有讲过,protocol buffers最显著的特点就是解析快,省空间。这时,wire type为 varint的方式就派上用场了。

Varint,从名字来看,就是可变的int, 我们知道,一个int在32位机器上占4个字节,如果用varint的话就不定占4个字节了,尤其你存储的是小数据时,根本不需要4个字节来存储。

Varint把第一个字节的第一个bit赋予新的意义,如果为1表示当前的值还没有表示完,后面还有字节应该属于当前值,直到遇到首位为0的字节,才表示后面没有更多的字节了。


第一步,先转化为二进制格式,然后从后面取7bit放在低地址位,因为后面还有字节来表示当前值,所以首位给1

第二步,再从二进制格式中,取7bit放在高地址位,因为这个字节已经是最后一个字节,再没有其它的字节了,所以首位给0

这样就完成了varint类型的编码了。


了解Varint的编码过程,解码就比较容易了。

例如有message

message Test{
    required int32 a = 1;
}


另外,Protocol buffers还提供了Length-Delimited方式的wire type来编解码,这种类型主要用于value为可变长度类型时使用,比如string就是一个典型的例子。

这种方式在解码的过程中,同样先解码key,可以得知wire type,然后去取得value的值。

比如 Message

message Test {
    required string b = 2;
}
编码后的内存模型为


我们对字段b进行赋值,下图显示了解码的全过程


对Key值进行解码,得到tag=2, wire type=2; 因为当前的wire type为 length-delimited类型,所以后面紧跟着length,指明value占有用多少个字节。这里注意的时,length也是varint类型,所以length本身所占字节并不是一个字节,而可以是更多个字节,如果这时字符串很长时。


关于Google Protocol Buffers的介绍就先到这里。



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值