协议缓冲区如何比XML和JSON更快?

时间:2018-09-03 09:19:42

标签: json protocol-buffers grpc

我最近开始在工作中阅读和使用gRPC。 gRPC在内部将协议缓冲区用作其IDL,我一直在各处阅读协议缓冲区的性能要好得多,尤其是与JSON和XML相比,更快。

我不明白的是-他们是怎么做到的?与XML和JSON相比,协议缓冲区中的哪种设计实际上使它们执行得更快?

3 个答案:

答案 0 :(得分:12)

数据的字符串表示形式

  • 需要文本编码/解码(虽然很便宜,但这仍然是一个额外的步骤)
  • 需要复杂的解析代码,尤其是在存在诸如“必须允许空白”之类的人性化规则时。
  • 由于涉及名称之类的东西,并且通常必须处理人类友好的表示形式(例如,如何对语法进行标记),因此通常会涉及更多的带宽-从而导致更多的实际有效载荷流失-
  • 通常需要很多中间字符串实例,这些实例用于成员查找等

基于文本的序列化程序和基于二进制的序列化程序都可以快速,高效(或缓慢而又可怕)...只是:二进制序列化程序具有其优势。这意味着“好的”二进制序列化程序通常比“好的”基于文本的序列化程序要快。

让我们比较一个整数的基本示例:

json:

{"id":42}

如果我们假设是ASCII或UTF-8编码且没有空格,则为9个字节。

xml:

<id>42</id>

如果我们假设是ASCII或UTF-8编码且没有空格,则没有11个字节-也没有像名称空间一样的名称空间噪声。

protobuf:

0x08 0x2a

2个字节

现在想象一下编写一个通用的xml或json解析器,以及处理仅在文本层上所需的所有歧义和场景,然后您需要映射文本标记"id"成员,则需要对"42"进行整数解析。在protobuf中,有效载荷较小,加上数学运算也很简单,并且成员查找是整数(因此:适合于非常快的switch / jump)。

答案 1 :(得分:1)

虽然二进制协议在理论上具有优势,但在实践中,取决于实现,它们可能会失去JSON或其他具有文本表示形式的协议的性能。

RapidJSONjsoniter-scala之类的高效JSON解析器以每字节2-8个周期的速度解析大多数JSON样本。它们的序列化效率更高,除非某些极端情况,例如带有浮点数的数字,此时序列化速度可以降低到每个字节16-32个周期。

但是对于大多数没有太多浮点数或两倍数的域,它们的速度与最好的二进制序列化程序相比具有相当的竞争力。请查看基准测试的结果,其中jsoniter-scala与ProtoBuf的Java和Scala库进行同等的解析和序列化:

https://github.com/dkomanov/scala-serialization/pull/8

答案 2 :(得分:0)

我不得不争论二进制协议通常会在性能上胜于基于文本的协议。哈,您不会发现许多(或任何)使用JSON表示帧数据的视频流应用程序。但是,任何设计不良的数据结构在解析时都会遇到困难。我从事过许多通信项目,在这些项目中,基于文本的协议被“二进制协议”所取代。