我最近开始在工作中阅读和使用gRPC。 gRPC在内部将协议缓冲区用作其IDL,我一直在各处阅读协议缓冲区的性能要好得多,尤其是与JSON和XML相比,更快。
我不明白的是-他们是怎么做到的?与XML和JSON相比,协议缓冲区中的哪种设计实际上使它们执行得更快?
答案 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或其他具有文本表示形式的协议的性能。
RapidJSON或jsoniter-scala之类的高效JSON解析器以每字节2-8个周期的速度解析大多数JSON样本。它们的序列化效率更高,除非某些极端情况,例如带有浮点数的数字,此时序列化速度可以降低到每个字节16-32个周期。
但是对于大多数没有太多浮点数或两倍数的域,它们的速度与最好的二进制序列化程序相比具有相当的竞争力。请查看基准测试的结果,其中jsoniter-scala与ProtoBuf的Java和Scala库进行同等的解析和序列化:
答案 2 :(得分:0)
我不得不争论二进制协议通常会在性能上胜于基于文本的协议。哈,您不会发现许多(或任何)使用JSON表示帧数据的视频流应用程序。但是,任何设计不良的数据结构在解析时都会遇到困难。我从事过许多通信项目,在这些项目中,基于文本的协议被“二进制协议”所取代。