protobuf的一些特性研究

1.protobuf编码相比于json更小的原理

通过之前的文章可以了解到,对于以下一个json对象

{

  "name":"john",

  “age":5

}

编码成protobuf时(这里我为了可读性更好,所以做了一个小转换),就会变成以下形式

1john25

意思是,第一个字段是john,第二个字段是数字5

而如果采用json形式

{"name":"john",“age":5}

我们会发现,json为了实现自解释性,从而需要将字段名包含在编码中,且为了格式需要,还需要包含很多标点符号

而protobuf牺牲了自解释性和可读性,从而使得编码的结果比json小了很多,因此采用这种方式就可以随意命名字段的名称了,反正编码后都是固定的形式

那么字段名等信息又如何获得呢?

这些信息是通过protobuf生成的具体语言的解析代码实现的,也就是说,如果A系统将某些信息编码成了protobuf的形式,并且希望传输给B系统,那么B系统也必须使用相应的解析代码进行解析,而2个系统的生成解析代码的依据必须是同一份proto文件。

所以归纳来说,protobuf是通过将数据的一部分信息,直接落地在系统上,从而减少了传输过程所需要的数据量,即以系统存储空间换数据传输空间

2.一个小戏法

从前文可以知道,protobuf的数据在传输过程中其实是缺失数据的字段名的,那么利用这一点,我们可以使得A系统发送的某个对象,在B系统中被解析成另外一个对象,即不同模型间的相互转换

我们定义如下2个模型

message Person {

  string name = 1;

  int32 id = 2;

  string email = 3;

  repeated string contacts = 4;

}

message Computer {

  string type = 1;

  int32 cpu = 2;

  string merchant = 3;

  repeated string disks = 4;

}

demo的ProtobufTest.ModelTransformationTest()中,我们可以看到2个不同的模型之间是能互相转换的

当然这种转换的限制非常大,2个模型的字段名可以完全不同,但是相应的字段类型和序号则必须一致,否则将会抛出异常

因此该trick的实用性并非很高,但在服务端的数据交互中可以起到一定作用

例如,你需要从A系统请求数据,然后将其转换成自己系统中定义的模型,在使用json格式的时候,我们要么完全严格地按照A系统定义的字段名创建模型,或者是写一些非常冗余且低效的代码,将数据中的字段一一赋值给自己定义的模型中相应的字段,那么此时这个trick就可以起到一定的作用,它能让你任性地定义自己喜欢的字段名!是不是感觉有点棒!


3.关于序号字节对于编码大小的影响

我们现在回顾一下protobuf的编码原理,其中有提到,序号字节的编码最低3位表示字段类型,最高位是用来判断是否到达最后一个字节,中间4位才用来表示序号,因此单个字节表示序号的时候,一个模型最多定义15个字段

当我们定义超过15个字段时,且这些字段都被赋值时,编码后的序号字段将需要至少2个字节表示

例如之前我们给Person对象的序号为23的large字段同样赋值150,得到的结果是

-72 1   -106   1

10111000 00000001 10010110 00000001

序号是

10111000 00000001

那么就需要思考一个问题,如果我们某个对象有超过15个字段,那么超过的部分在编码时就会多出一个字段,当模型字段特别多的时候,这些多出的字节也将是不小的一部分

为了尽量避免这个问题,可以考虑采用子对象的形式

某个对象有30个字段,在编码时会多出15个字节的额外量,那么我们可以定义2个子对象,并将30个字段分别定义在2个子对象中,每个子对象15个字段,那么在编码时就可以节省部分字节

具体实例:

我们定义一个模型,其中包含30个字段,另一个模型包含2个15个字段的子对象

比较结果为

115

126

为何只少了11个字节呢?从前文子对象的编码过程中会发现,每一个子对象也需要有一个字节去标记其类型,还有一个字节标识其长度,因此2个子对象共需要额外4个字节,那么原先节省了15个字节,所以总计15-4=11个字节

当然这种形式会使得字段的读取略微麻烦一些,并且整体的节省比例会随着实际每个字段数据量的增加而缩小,因此比较适合于对传输过程有极限要求的场景

demo的ProtobufTest.compareNestedAndNotNestedModel()和ProtobufTest.compareFieldNest()中我展示了这种对比

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。