protobuf为什么快
protobuf为什么快
protobuf为什么快_protostaff-CSDN博客
为什么protobuf这么快_protocolbuffer为什么效率高-CSDN博客
说明
Protobuf(Protocol Buffers)是由 Google 开发的一种轻量级、高效的数据交换格式,它被用于结构化数据的序列化、反序列化和传输。相比于 XML 和 JSON 等文本格式,Protobuf 具有更小的数据体积、更快的解析速度和更强的可扩展性。
核心思想:使用协议(Protocol)来定义数据的结构和编码方式。使用 Protobuf,可以先定义数据的结构和各字段的类型、字段等信息,然后使用Protobuf提供的编译器生成对应的代码,用于序列化和反序列化数据。由于 Protobuf 是基于二进制编码的,因此可以在数据传输和存储中实现更高效的数据交换,同时也可以跨语言使用,如下所示

总结
类型:
- 基本都是正数(varint):int32、int64
- 既有正数又有负数(使用zigzag + varint优化):sint32、sint64
- 数据很大(tag使用varint,数据使用固定长度4字节或者8字节):fixed32、fixed64
- 字符串类型(Tag+Length+Value):string

格式:

tag :高位(字段序号) + 低三位(字段类型)
体积小、传输快:编号代替字段名,传输的纯是数据本身,体积通常比 JSON 小 30% 以上,网络传输自然就快。
格式:tag+数据+tag+数据+tag+length+数据
- 数字就是:tag+数据
- Varint + ZigZag
- 字符串:tag+length+数据
- Tag-Length-Value
- tag = makeTag返回值 = 高位(字段序号) + 低三位(字段类型)
- 小端序存储
- 存储的时候怎么知道这个字段是tag还是数据:
- 最高位1表示这个是上一个字节的部分,最高位是0表示是tag
- 每个字节只有7位数字表示内容,最高位表示是不是tag
- 二进制按这种存储,解析按这样解析,就会快!!!

AI回答
-
格式是 tag+数据+tag+数据,直接二进制的,没有额外的字段名存储
-
这样体积小,体积小对应的传输就快
-
解析快,也是因为是二进制,且有预定义的 Schema,可以流式顺序读取,直接往对应的结构体里填充数据,甚至支持零拷贝。
-
AI解答这个回答:
-
你的核心观点(完全正确,直接说)
- 传输快:无字段名,只有Tag+Value,体积通常是JSON的1/3,网络IO时间短。
- 解析快:无需文本分词,基于预定义Schema(
.proto文件)直接内存填充,支持零拷贝。
-
补上“为什么比压缩过的JSON还快”的杀招:Varint
- JSON即使压缩成gzip,服务端解压和解析文本是两步,CPU开销大。
- Protobuf用了Varint(变长整数)编码。整数不固定占4字节,数字小(如
1)只占1个字节。更关键的是,它用位运算(位移和异或)取代了JSON解析时的乘除法和字符转换,这是CPU指令级别的降维打击。
-
补上“为什么填充内存快”的杀招:无需反序列化两次
- JSON解析通常是:
读文本 -> 生成DOM树/Map -> 再转成对象,产生大量临时对象,GC(垃圾回收)压力大。 - Protobuf生成的代码直接操作内存偏移量(offset)。读到Tag,就知道把这个Value直接写到结构体的哪个内存地址上。一次遍历,边读边填,且内存连续,对CPU缓存极友好。
- JSON解析通常是:
终极回答模板(融合版)
“Protobuf快是空间和时间双赢的结果。
空间上,它用Tag代替字段名,结合Varint变长编码,让数据包极小,传输快。
时间上,它是二进制协议,解析时省去了JSON繁琐的字符转数字和键值查找。加上有预定义的Schema,解析器能顺序读取,通过内存偏移量直接赋值给结构体,省去了中间对象创建,GC压力小,所以极快。”
-
-
-
第一,它是二进制协议,没有“废话”。
JSON 和 XML 是文本格式,会传输大量的键名、引号、花括号这些元数据。而 Protobuf 用字段编号代替字段名,传输的纯是数据本身,体积通常比 JSON 小 30% 以上,网络传输自然就快。第二,编解码过程中省去了字符处理。
JSON 解析需要做文本分词、处理 Unicode、把字符串数字转成整数,这些都是 CPU 密集操作。而 Protobuf 直接操作二进制字节流,用的是位运算和位移,没有字符编码转换的开销。第三,采用了高效的变长编码(Varint)。
对于整数,它不用固定 4 个或 8 个字节,数值越小占的字节越少。比如数字 1 只占 1 个字节,这就进一步压缩了数据量。第四,解析时不需要构建树形结构。
JSON 需要先完整加载数据、构建 DOM 树再查找字段,内存分配多、GC 压力大。而 Protobuf 因为有预定义的 Schema,可以流式顺序读取,直接往对应的结构体里填充数据,甚至支持零拷贝。总结一句话: Protobuf 用牺牲可读性和依赖预定义 Schema 为代价,换来了极致的压缩率和直接的内存填充,所以编解码和传输都快。
JSON\XML是怎么传输的,为什么慢?
JSON 传输的是"字符的二进制编码"(比如 ASCII 码),而 Protobuf 传输的是"数值的二进制表示"。前者是"文本流",后者是"数据流"。
-
JSON 和 XML 本质上是文本协议,传输和解析慢的核心原因有三点:
-
第一,传输时携带了大量冗余信息。 字段名、引号、花括号、标签这些全是"传输开销",有效数据占比低,网络 IO 时间长。
-
第二,解析时需要做文本分词和类型转换。 数字在文本里是字符
'1''2''3',要转成真正的数字需要乘法和累加;真假值(true/false)需要字符串比较;这些操作远不如直接读二进制快。 -
第三,解析时需要构建树形结构。 JSON 要先生成 DOM 树或哈希表,XML 要构建 DOM 树,然后再从中查找字段,中间产生大量临时对象,GC 压力大。
-
核心一句话: JSON/XML 慢在"人类可读"这四个字上——为了让人能看懂,付出了巨大的编解码代价。
-
-
JSON 示例
{"user_id": 12345, "user_name": "张三", "age": 25}-
实际传输的字节(UTF-8):每一个字符都会变成一个ASCII 码表示
{ " u s e r _ i d " : 1 2 3 4 5 , " u s e r _ n a m e " : " 张 三 " , " a g e " : 2 5 } -
有效数据:
12345(5字节)+张三(6字节)+25(2字节)= 13 字节 -
冗余数据:花括号、引号、冒号、逗号、键名 = 约 35+ 字节
-
每一个字符都会变成一个ASCII 码表示:
-
例如:
字符 '1' → ASCII 码 0x31 字符 '2' → ASCII 码 0x32 字符 '3' → ASCII 码 0x33 字符 '4' → ASCII 码 0x34 字符 '5' → ASCII 码 0x35 # JSON网络传输的字节流:31 32 33 34 35 (5 个字节) 数字 12345 → 二进制是 0x3039 → Varint 编码后 → 0xB9 0x60 # Protobuf网络传输的字节流:B9 60 (2 个字节) 看出区别了吗?同样是 0 和 1,JSON 传的是"数字的字符表示",Protobuf 传的是"数字本身"。
-
序列化方式、或者说传输信息时使用的方式除了xml、json、protobuf还有哪些?
-
第一类,文本型:XML、JSON,以及更紧凑的 YAML、TOML,主要用于配置文件和人机交互。
-
第二类,通用二进制型:Protobuf、Thrift、Avro,主要用于微服务 RPC 通信,兼顾性能和跨语言。
-
第三类,高性能极致型:FlatBuffers、Cap'n Proto,支持零拷贝,解析时不需要反序列化,直接访问内存。
-
第四类,语言专属型:Java 的 Serializable 和 Kryo、Go 的 gob、Python 的 pickle,主要用于同语言进程间通信或本地持久化。
-
第五类,存储引擎型:Parquet、ORC,主要用于大数据列式存储。
-
选什么取决于业务需求:对内 RPC 用 Protobuf/Thrift,对外 API 用 JSON,嵌入式极致性能用 FlatBuffers,大数据分析用 Parquet。
-
一张图总结:选型决策树
你的数据要给谁看? ├── 人看 → 文本型 │ ├── API 接口 → JSON │ ├── 配置文件 → YAML / TOML │ └── 企业级 → XML │ └── 机器看 → 二进制 ├── 需要极致解析速度(零拷贝)→ FlatBuffers / Cap'n Proto ├── 需要 RPC 通信(跨语言) │ ├── 标准统一 → Protobuf(gRPC) │ ├── 传输灵活 → Thrift │ └── Schema 动态演进 → Avro(Kafka) ├── 同语言进程内 → Kryo / gob / pickle └── 大数据分析 → Parquet / ORC -
序列化从"慢到快"的本质演进:
- "序列化技术的发展,本质是在人类可读性和机器效率之间不断向后者倾斜。JSON/XML 为人而生,Protobuf/Thrift 为机器而生,FlatBuffers/Cap'n Proto 为极致吞吐而生。没有最好,只有最合适。 选型要看场景:对外要灵活用 JSON,对内要性能用 Protobuf,极致要吞吐用 FlatBuffers。"
浙公网安备 33010602011771号