google protobuf序列化原理

  一个message,序列化时首先就算这个message所有filed序列化需要占用的字节长度,计算这个长度是非常简单的,因为protobuf中每种类型的filed所占用的字节数是已知的(bytes、string除外),只需要累加即可。这个长度就是serializedSize,32为integer,在protobuf的某些序列化方式中可能使用varint32(一个压缩的、根据数字区间,使用不同字节长度的int);

此后是filed列表输出,每个filed输出包含int32(tag,type)和value的字节数据,我们知道每个filed都有一个唯一的数字tag表示它的index位置,type为字段的类型;如果filed为string、bytes类型,还会在value之前额外的补充添加一个varint32类型的数字,表示string、bytes的字节长度。

消息经过序列化后会成为一个二进制数据流,该流中的数据为一系列的 Key-Value 对,如下图

二进制格式的message使用数字标签作为key,Key 用来标识具体的 field,在解包的时候,Protocol Buffer 根据 Key 就可以知道相应的 Value 应该对应于消息中的哪一个 field。

  那么在反序列化的时候,首先读取一个32为的int表示serializedSize,然后读取serializedSize个字节保存在一个bytebuffer中,即读取一个完整的package。然后读取一个int32数字,从这个数字中解析出tag和type,如果type为string、bytes,然后补充读取一个varint32就知道了string的字节长度了,此后根据type或者字节长度,读取后续的字节数组并转换成java type。重复上述操作,直到整个package解析完毕。

采用这种 Key-Pair 结构无需使用分隔符来分割不同的 Field。对于可选的 Field,如果消息中不存在该 field,那么在最终的 Message Buffer 中就没有该 field,这些特性都有助于节约消息本身的大小。

上边我们说,“二进制格式的message使用数字标签作为key”,此处的数字标签,并非单纯的数字标签,而是数字标签与传输类型的组合,根据传输类型能够确定出值的长度。

key的定义:

(field_number >> 3) | wire_type

Key 由两部分组成。第一部分是 field_number,第二部分为 wire_type。表示 Value 的传输类型。也就是说,key中的后三位,是值的传输类型

Wire Type 可能的类型如下表所示:

Type Meaning Used For
0 Varint int32, int64, uint32, uint64, sint32, sint64, bool, enum
1 64-bit fixed64, sfixed64, double
2 Length-delimi string, bytes, embedded messages, packed repeated fields
3 Start group Groups (deprecated)
4 End group Groups (deprecated)
5 32-bit fixed32, sfixed32, float
时间: 2024-10-29 19:10:21

google protobuf序列化原理的相关文章

Google protobuf序列化以及反序列化

序列化的目的是将对象持久化到硬盘或者用于网络传输.java也提供了序列化技术,非常简单,只要实现Serializable接口即可.如下: public class commonService implements Serializable { private static final long serialVersionUID = 1L; } 这种方式有以下几个缺点:(1)无法跨语言    (2)序列化的码流太大   (3)序列化的性能差 下面我测试一下序列化一个对象后的大小,代码如下: pub

python protobuf序列化repeated运用

下面是proto描述文件的定义 message Person { required string name = 1; required int32 id = 2; optional string email = 3; enum PhoneType { MOBILE = 0; HOME = 1; WORK = 2; } message PhoneNumber { required string number = 1; optional PhoneType type = 2 [default = H

google protobuf学习笔记一:使用和原理

一.什么是protobuf protobuf全称Google Protocol Buffers,是google开发的的一套用于数据存储,网络通信时用于协议编解码的工具库.它和XML或者JSON差不多,也就是把某种数据结构的信息,以某种格式(XML,JSON)保存起来,protobuf与XML和JSON不同在于,protobuf是基于二进制的.主要用于数据存储.传输协议格式等场合.那既然有了XML等工具,为什么还要开发protobuf呢?主要是因为性能,包括时间开销和空间开销: 1.时间开销:XM

Protocol Buffer 序列化原理解析 - 为什么Protocol Buffer性能这么好?

前言 习惯用 Json.XML 数据存储格式的你们,相信大多都没听过Protocol Buffer Protocol Buffer 其实 是 Google出品的一种轻量 & 高效的结构化数据存储格式,性能比 Json.XML 真的强!太!多! 由于 Google出品,我相信Protocol Buffer已经具备足够的吸引力 今天,我将讲解为什么Protocol Buffer的性能如此的好: a. 序列化速度 & 反序列化速度快 b. 数据压缩效果好,即序列化后的数据量体积小 阅读本文前请先

google protobuf学习笔记一:windows下环境配置

欢迎转载,转载请注明原文地址:http://blog.csdn.net/majianfei1023/article/details/45371743 protobuf的使用和原理,请查看:http://blog.csdn.net/majianfei1023/article/details/45112415 Windows下google protobuf开发环境配置 最近项目需求,Client与Server的网络通信协议传输使用google protobuf rpc.对于Protobuf,以前是只

Google Protobuf 使用 Java 版

一 . Protobuf 的入门 Protobuf 是一个灵活,高效,结构化的数据序列化框架, 相比于 XML 等传统的序列化工具,它更小,更快,更灵活,更简单. Protobuf 支持数据结构化一次可以到处使用.甚至跨语言使用.同通过代码生成工具可以自动生成不同语言版本的源代码,甚至可以在使用不同版本的数据结构中进行数据传递,实现数据结构的向前兼容. Google 的 protobuf 在业界非常流行,很多商业项目选择 protobuf 作为编码解码框架,这里我们一起回顾一下 Protobuf

google protobuf初体验

最近在读别人代码的时候发现一个的东西,名字叫protobuf, 感觉挺好用的,写在这里,留个记录.那么什么是protobuf 呢?假如您在网上搜索,应该会得到类似这样的文字介绍: Google Protocol Buffer( 简称 Protobuf) 是 Google 公司内部的混合语言数据标准,目前已经正在使用的有超过 48,162 种报文格式定义和超过 12,183 个 .proto 文件.他们用于 RPC 系统和持续数据存储系统. Protocol Buffers 是一种轻便高效的结构化

比较跨语言通讯框架:Apache Thrift和Google Protobuf

前两天想在微博上发表一个观点:在现在的技术体系中,能用于描述通讯协议的方式很多,xml,json,protobuf,thrift,如果在有如此众多选择的基础上,在设计系统时,还自造协议,自己设计协议类型和解析方式,那么我只能说,您真的落后了,不是技术上,而是思想上.对于xml,和json我们不做过多描述了,参考相关文档就可以了.特别是json,如今在 web系统,页游系统的前后台通讯中,应用非常广泛.本文将重点介绍两种目前在大型系统中,应用比较普遍的两种通讯框架,thrift和Protobuf,

使用CSharp编写Google Protobuf插件

什么是 Google Protocol Buffer? Google Protocol Buffer( 简称 Protobuf) 是 Google 公司内部的混合语言数据标准,目前已经正在使用的有超过 48,162 种报文格式定义和超过 12,183 个 .proto 文件.他们用于 RPC 系统和持续数据存储系统. Protocol Buffers 是一种轻便高效的结构化数据存储格式,可以用于结构化数据串行化,或者说序列化.它很适合做数据存储或 RPC 数据交换格式.可用于通讯协议.数据存储等