Google プロトコル バッファーと ASN.1 の比較
-
09-09-2019 - |
質問
Google プロトコル バッファと ASN.1 (PER エンコーディング) の最も顕著な違いは何ですか?私のプロジェクトにとって最も重要な問題は、シリアル化されたデータのサイズです。誰かがこの 2 つのデータサイズを比較したことがありますか?
解決
これは、私がどんなASN.1の仕事をやったので、長い時間だが、サイズはあなたのタイプと実際のデータの詳細に依存する可能性が非常に高いです。
私はの強くの両方のプロトタイプを作成することをお勧めしますと比較することで、いくつかの実際のデータを入れます。
う あなたのプロトコルバッファが繰り返さプリミティブ型が含まれます場合は、は、プロトコルバッファのためのSubversionの最新のソースを見てみなければならない - 彼らははるかに空間効率である今、「パック」の形式で表現することができます。 (私のC#のポートがあり、のちょうどこの機能を、いくつかの時間先週に追いついの。)
他のヒント
(例えば、リストの長さなどのために、整数の下限/上限、上限を指定する)、あなたのエンコーディングは非常になりますコンパクト。そこフィールド間の位置合わせ又はパディングのようなもののために無駄に何ビットでなくなり、各フィールドの値のその許容範囲を保持するのに必要な最小のビット数で符号化されます。例えば、タイプINTEGER(1..8)のフィールドは、3ビットで符号化され(1 = '000'、2 = '001'、...、8 = '111')。四の代替とCHOICEが2ビット(選択された代替を示す)プラス選ば代替によって占められるビットを占有します。 ASN.1は成功し、多くの公開されている標準で使用されている他の多くの興味深い機能を備えています。例えば、シーケンス、CHOICE列挙、および他のタイプに適用される拡張マーカー(「...」)であり、仕様の異なるバージョンを実装するエンドポイント間backward-および前方互換性を可能にします。
パック/エンコードされたメッセージのサイズが重要な場合は、protobuf がパックできないという事実にも注意する必要があります。 repeated
ではないフィールド primitive numeric type
, これを読む 詳細については。
これは問題です。そのタイプのメッセージがある場合:(コメントは実際の値の範囲を定義します)
message P{
required sint32 x = 1; // -0x1ffff to 0x20000
required sint32 y = 2; // -0x1ffff to 0x20000
required sint32 z = 3; // -0x319c to 0x3200
}
message Array{
repeated P ps = 1;
optional uint32 somemoredata = 2;
}
たとえば、配列の長さが 32 の場合、配列に実際に含まれる値に応じて、protobuf を使用したパックされたメッセージのサイズは約 250 ~ 450 バイトになります。32 ビット範囲全体を使用する場合、これは 1000 バイトを超えることもあります または 使用する場合に備えて int32
の代わりに sint32
そして負の値を持ちます。
生データ BLOB (z が次のように定義できると仮定) int16
value) は 320 バイトしか消費しないため、 ASN.1 メッセージは いつも 最大値は実際には 32 ビットではなく、19 ビット (x,y) と 15 ビット (z) であるため、320 バイトより小さくなります。
protobuf メッセージ サイズは、次のメッセージ定義を使用して最適化できます。
message Ps{
repeated sint32 xs = 1 [packed=true];
repeated sint32 ys = 2 [packed=true];
repeated sint32 zs = 3 [packed=true];
}
message Array{
required Ps ps = 1;
optional uint32 somemoredata = 2;
}
その結果、メッセージ サイズは約 100 バイト (すべての値がゼロ)、300 バイト (最大範囲の値)、および 500 バイト (すべての値が上位 32 ビット値) になります。