私は最近、仕事でgRPCを読み、採用し始めました。 gRPCはそのIDLとして内部的にプロトコルバッファーを使用します。JSONやXMLと比較して、プロトコルバッファーのパフォーマンスがはるかに優れている(特に高速である)場合はどこでも読み続けます。
私が理解できないのは-彼らはそれをどのように行うのですか?プロトコルバッファのどの設計が、XMLやJSONと比較して実際に高速に動作するのですか?
データの文字列表現:
テキストベースのシリアライザとバイナリベースのシリアライザは、どちらも高速で効率的(または遅くて恐ろしい)になる可能性があります。これは、「良い」バイナリシリアライザーは通常「良い」テキストベースのシリアライザーよりも高速であることを意味します。
整数の基本的な例を比較してみましょう:
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に適しています)。
理論上、バイナリプロトコルには利点がありますが、実際には、実装によっては、テキスト表現を使用するJSONまたはその他のプロトコルに比べてパフォーマンスが低下する可能性があります。
RapidJSON または jsoniter-scala のような効率的なJSONパーサーは、バイトあたり2-8サイクルの速度でほとんどのJSONサンプルを解析します。シリアル化速度がバイトあたり16〜32サイクルに低下する可能性がある浮動小数点数のような一部のEdgeケースを除いて、これらはさらに効率的にシリアル化します。
しかし、浮動小数点数や倍数が多くないほとんどのドメインでは、速度は最高のバイナリシリアライザーと非常に競合します。 jsoniter-scalaがJavaおよびScala Library for ProtoBuf)を使用して解析およびシリアル化するベンチマークの結果を参照してください。
バイナリプロトコルは通常は常にテキストベースのプロトコルと比較してパフォーマンスが優れていると主張する必要があります。ほら、JSONを使用してフレームデータを表現するビデオストリーミングアプリケーションは多くありません。ただし、適切に設計されていないデータ構造は、解析時に苦労します。テキストベースのプロトコルが「バイナリプロトコル」に置き換えられた多くの通信プロジェクトに取り組んできました。