web-dev-qa-db-ja.com

プロトコルバッファはXMLやJSONよりも高速ですか?

私は最近、仕事でgRPCを読み、採用し始めました。 gRPCはそのIDLとして内部的にプロトコルバッファーを使用します。JSONやXMLと比較して、プロトコルバッファーのパフォーマンスがはるかに優れている(特に高速である)場合はどこでも読み続けます。

私が理解できないのは-彼らはそれをどのように行うのですか?プロトコルバッファのどの設計が、XMLやJSONと比較して実際に高速に動作するのですか?

14
gravetii

データの文字列表現:

  • テキストのエンコード/デコードが必要です(これは安価ですが、追加の手順です)
  • 特に「ホワイトスペースを許可する」などの人にやさしいルールがある場合は、複雑な解析コードが必要です。
  • 通常、より多くの帯域幅を必要とします-チャーンする実際のペイロードがより多くなります-名前のようなものの埋め込みと、(再び)人にやさしい表現を処理する必要があるため(構文をトークン化する方法など)
  • 多くの場合、メンバーの検索などに使用される多くの中間文字列インスタンスが必要です

テキストベースのシリアライザとバイナリベースのシリアライザは、どちらも高速で効率的(または遅くて恐ろしい)になる可能性があります。これは、「良い」バイナリシリアライザーは通常「良い」テキストベースのシリアライザーよりも高速であることを意味します。

整数の基本的な例を比較してみましょう:

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に適しています)。

18
Marc Gravell

理論上、バイナリプロトコルには利点がありますが、実際には、実装によっては、テキスト表現を使用するJSONまたはその他のプロトコルに比べてパフォーマンスが低下する可能性があります。

RapidJSON または jsoniter-scala のような効率的なJSONパーサーは、バイトあたり2-8サイクルの速度でほとんどのJSONサンプルを解析します。シリアル化速度がバイトあたり16〜32サイクルに低下する可能性がある浮動小数点数のような一部のEdgeケースを除いて、これらはさらに効率的にシリアル化します。

しかし、浮動小数点数や倍数が多くないほとんどのドメインでは、速度は最高のバイナリシリアライザーと非常に競合します。 jsoniter-scalaがJavaおよびScala Library for ProtoBuf)を使用して解析およびシリアル化するベンチマークの結果を参照してください。

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

1

バイナリプロトコルは通常は常にテキストベースのプロトコルと比較してパフォーマンスが優れていると主張する必要があります。ほら、JSONを使用してフレームデータを表現するビデオストリーミングアプリケーションは多くありません。ただし、適切に設計されていないデータ構造は、解析時に苦労します。テキストベースのプロトコルが「バイナリプロトコル」に置き換えられた多くの通信プロジェクトに取り組んできました。

0
user2879582