2009-02-27 5 views
24

Worin bestehen die größten Unterschiede zwischen Google Protocol Buffers und ASN.1 (mit PER-Codierung)? Für mein Projekt ist das größte Problem die Größe der serialisierten Daten. Hat jemand irgendwelche Datengrößenvergleiche zwischen den beiden gemacht?Wie vergleicht Google Protocol Buffers mit ASN.1?

+0

Vielleicht eine verwandte Frage: Warum brauchen wir Protokollpuffer, wenn wir bereits einen ausgereiften ASN.1 haben? Nicht erfunden hier bei Google? –

Antwort

8

Es ist lange her, seit ich irgendeine Arbeit ASN.1 gemacht habe, aber die Größe hängt sehr wahrscheinlich von den Details Ihrer Typen und tatsächlichen Daten ab.

Ich würde stark empfehlen, dass Sie beide Prototypen und legen Sie einige echte Daten zu vergleichen.

Wenn Ihr Protokollpuffer wiederholte primitive Typen enthält, sollten Sie sich die neueste Quelle in Subversion für Protokollpuffer ansehen - sie können jetzt in einem "gepackten" Format dargestellt werden, das viel platzsparender ist. (Mein C# Port hat nur mit dieser Funktion einige Zeit letzte Woche aufgeholt.)

18

Wenn Sie ASN.1 mit Unaligned PER verwenden, und definieren Sie Ihre Datentypen mit den entsprechenden Einschränkungen (z. B. unter/oberen angeben Grenzen für ganze Zahlen, obere Grenzen für die Länge von Listen usw.), Ihre Kodierungen werden sehr kompakt sein. Es gibt keine Bits, die für Dinge wie Ausrichtung oder Auffüllen zwischen den Feldern verschwendet werden, und jedes Feld wird in der minimalen Anzahl von Bits codiert, die notwendig sind, um seinen zulässigen Wertebereich zu halten. Zum Beispiel wird ein Feld vom Typ INTEGER (1..8) in 3 Bits codiert (1 = '000', 2 = '001', ..., 8 = '111'); und eine WAHL mit vier Alternativen belegt 2 Bits (was die gewählte Alternative anzeigt) plus die Bits, die von der gewählten Alternative belegt sind. ASN.1 hat viele andere interessante Funktionen, die in vielen veröffentlichten Standards erfolgreich verwendet wurden. Ein Beispiel ist der Erweiterungsmarker ("..."), der, wenn er auf SEQUENCE, CHOICE, ENUMERATED und andere Typen angewendet wird, die Rückwärts- und Vorwärtskompatibilität zwischen Endpunkten ermöglicht, die verschiedene Versionen der Spezifikation implementieren.

3

Wenn die Größe der gepackten/codierte Nachricht ist wichtig, dass Sie auch die Tatsache, sollten beachten, dass protobuf repeated Felder packen nicht in der Lage ist, die nicht von einem primitive numeric type sind, read this für weitere Informationen.

Dies ist ein Problem, z.B. Wenn Nachrichten dieses Typs haben: (Kommentar definiert tatsächlichen Wertebereich)

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; 
} 

Falls man ein Array Länge haben, zum Beispiel 32, als in einem gepackten Nachrichtengröße von etwa 250 bis 450 Bytes führen würde, mit Protobuf, abhängig davon, welche Werte das Array tatsächlich enthält. Dies kann sogar auf über 1000 Bytes steigen, wenn Sie den vollen 32bit-Bereich oder verwenden, wenn Sie int32 anstelle von sint32 verwenden und negative Werte haben.

Die Rohdaten BLOB (die z Annahme kann als Wert definiert werden int16) nur 320 Bytes verbrauchen und somit die ASN.1 Nachricht ist immer kleiner als 320 Bytes, da die Maximalwerte tatsächlich nicht 32bit sind, aber 19 Bit (x, y) und 15 Bit (z).

Die protobuf Nachrichtengröße kann mit dieser Nachrichtendefinition optimiert werden:

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; 
} 

die ca. 100-Byte in Meldung führt Größen zwischen (alle Werte sind Nullen), 300 Byte (Werte bei Bereich max) und 500 Byte (alle Werte sind hoch 32 Bit Werte).