2009-02-27 94 views
24

Google協議緩衝區和ASN.1(使用PER編碼)最顯着的區別是什麼?對於我的項目來說,最重要的問題是序列化數據的大小。有沒有人在兩者之間做過任何數據大小的比較?Google協議緩衝區與ASN.1相比如何?

+0

也許是一個相關的問題:當我們已經有一個成熟的ASN.1時,爲什麼我們需要協議緩衝區? Google沒有在這裏發明綜合徵? – 2018-03-05 09:58:50

回答

8

自從我完成了任何ASN.1工作以來,這已經很長時間了,但其大小很可能取決於您的類型和實際數據的細節。

我會強烈建議您原型,並把一些真實的數據進行比較。

如果您的協議緩衝區包含重複的原始類型,您應該查看Subversion協議緩衝區中的最新源代碼 - 它們可以用現在更加節省空間的「打包」格式表示。 (我的C#端口有只是趕上了這個功能,上週一些時間。)

18

如果使用ASN.1與非對齊PER,並確定使用相應的約束(數據類型例如,指定下/上整數的範圍,列表長度的上限等),您的編碼將非常緊湊。對於字段之間的對齊或填充等內容,將不會浪費比特,並且每個字段都將被編碼爲保持其允許的值範圍所需的最小比特數。例如,INTEGER(1..8)類型的字段將被編碼爲3位(1 ='000',2 ='001',...,8 ='111');而一個有四種選擇的CHOICE將佔用2位(表示所選擇的選擇)加上所選備選項佔用的位。 ASN.1還有許多其他有趣的功能,已經在許多已發佈的標準中成功使用。一個例子是擴展標記(「...」),當它應用於SEQUENCE,CHOICE,ENUMERATED和其他類型時,實現了實現不同版本規範的端點之間的向前和向後兼容性。

3

當打包/編碼消息的大小是很重要的,你也應該注意一個事實,即protobuf的無法收拾repeated字段是一個primitive numeric type的不是,read this以獲取更多信息。

這是一個問題,例如如果有該類型的消息:(評論定義值的實際範圍)

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比你會導致大約250到450個字節的填充消息大小與protobuf,取決於數組實際包含的值。如果您使用int32而不是sint32並且具有負值,那麼在使用完整32位範圍的情況下,這甚至可以增加到超過1000字節。

原始數據blob(假定Z可以定義爲int16值)將只消耗320個字節,因此ASN.1消息是總是小於320字節,因爲最大值實際上不是32位,但19位(x,y)和15位(z)。

的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位值)。