ProtocolBuffer VS AMF3(fixed)

感謝Atry的指導,筆者修改了一下範例,以求更客觀的比較結果,順便也比較一下修改前及修改後的效能差異

主要修改的有兩部分:

1. 使用optional取代required

2. scalar最佳化

proto文件如下

message BigData {
         
        repeated MediumData mediumDatas = 1;
}
 
message MediumData {
         
        repeated SmallData smallDatas = 1; 
}
 
message SmallData {
        optional sfixed32 intValue = 1;
        optional fixed32 uintValue = 2;
        optional bool booleanValue = 3;
        optional float numberField = 4;
}

proto文件記載了BigData、MediumData及SmallData,SmallData只有基本資料型別,而MediumData及BigData則是用巢狀方式讓資料格式更大,repeated屬性可以讓欄位變成陣列(Array)或清單(List),由於直接使用ProtocolBuffer轉出來的類別轉AMF3的話,AMF3會把繼承的Message類一起寫入,為了避免這點,範例再寫一組同樣格式但沒有繼承的資料物件給AMF3使用,以求更客觀的比較結果

範例為測試AMF3及ProtocolBuffer的序列化及反序列化速度,結果如下

protoBuff_benchmark1.png

以大小來看,Protocol Buffer比較小,即使是巢狀資料也比AMF小一點,但速度方面是AMF3較好,原因可能是AMF3的序列化及反序列化為底層API,效能可能有被優化,不過以實用上來看Protocl Buffer的速度是可接受的,畢竟平常的封包也不會太大。

再來比較一下proto文件的required及optional差異,required是指示欄位一定要有值,而optional是可有可無,以官網的說法 ,required欄位如果之後要改成optional會有讀取問題,建議是使用optional,為了試驗,筆者把上述的smallData所有欄位改成required,比較一下效能,結果如下

protoBuff_benchmark1_2.png

如果是使用required,Protocol buffer的變化不大,筆者之前有試過optional加default的話,會比required欄位小很多,但如果都使用賦值,差異就看不出來了

另一個要測的是scalar,也就是欄位宣告的類型,Protocol Buffer跟AMF不同,即使類型同樣為正負號整數,必須依使用情況宣告成不同的scalar才能發揮Protocol Buffer最大功效,可參考 http://code.google.com/apis/protocolbuffers/docs/proto.html#scalar

也就是當使用整數時,如果是小值,可宣告成int,如果值常超過228,要用fixed32,或是整數常出現負號,應使用sint32,針對不同需求應宣告成對應類型,這部分就要看實例時,欄位要怎麼設計,筆者把範例修改成只宣告uint及int,比較一下兩者的差異

protoBuff_benchmark1_3.png

出乎意料的是差異不大,只有大小有明顯的變化,或許是筆者範例的欄位太少,只有一點的差異讓我有點意外。

最後做個總結,Protocol Buffer的測試似乎依實例來測會比較準,筆者目前寫的測試方法還是無法比較出差異,主要應該是值都是重覆使用,無法發揮封包特性,或許還要再想一個比較好的實例來測會比較準

原始檔下載

如果有網友測出不同結果,或覺得範例測試方法有誤,歡迎留言討論。

測試環境為: ProtocolBuffer 2.4.0a、Flex 4.0 SDK、Protoc-gen-as3 0.9.0、FlashPlayer 10.3 Release

相關文章: [教學]在Flash中使用Google Protocol Buffers

轉載請註明出處

11 意見 :: ProtocolBuffer VS AMF3(fixed)

  1. 测试用例全错!!!!!

    1. required应慎用。参见 http://code.google.com/apis/protocolbuffers/docs/proto.html 中的“Required Is Forever”一段。试试把proto文件中的required改成optional再测测性能,有惊喜。

    2. default选项应该同optional一起用而不是和required一起用。参见 http://code.google.com/apis/protocolbuffers/docs/proto.html#optional 。

    3. 重复出现相同的长字符串是一种实践中根本不可能出现的情况,偏偏AMF对这种情况有优化,这不公平。考虑AMF3一个small包就有157B,包含了500个small的medium包竟然才14.8KB,还不到small的一百倍。

    4. uint32类型适合出现小数字几率高的情形。0xFFFFFF用uint32类型存取很低效,应该用fixed32。参见 http://code.google.com/apis/protocolbuffers/docs/proto.html#scalar

    5. int32类型适合出现小正数几率高的情形。2147483647用int32类型存取很低效,应该用sfixed32。

    总之,这样的测试应该尽量用接近实践中的数据。实践中应该有一定比例采用默认值而不设置值的。随机生成的数据也要考虑实践中的分布情况。实践中除了某些UUID外,别的数据很少是均匀分布在0到0xFFFFFFFF之间的而是集中在小数字的情形上。

    实践中最常见的数据包往往内容不大,最多上百字节,但格式异常复杂,嵌套层次很多,此外还存在大量小整数。这类数据正好是Protobuf专门优化的类型。

  2. 此外,字符串和字节数组的字段可以去掉。大的字符串和字节数组不论用何种格式都是简单的字节拷贝,不会有太大的性能差异。

  3. 还有,全部测试数据都是些重复数据,对这些重复数据测试压缩率,当然会超级高了,说明不了任何问题。

  4. Atry感謝您的回應,很高興能有機會跟您討論,這次的範例在測試上確實沒考慮到實際的使用情形,數值及欄位的設計的確有誤,我會參考您的意見再改寫一版測試,也希望您能繼續給予批評與指教,謝謝

  5. 你的测试数据用的是Debugger版本的Flash Player,对解释执行的protobuf很不公平。因为Protobuf的序列化/反序列化代码是在解释器中执行的,性能受Flash Player版本影响很大;而AMF则是调用了C++库,性能与Flash Player版本关系不大。

    我自己用最新的Flash Player 10.3非Debugger版测试,Protobuf并不比AMF慢很多,二者性能在同一数量级。

  6. 此外,您的测试仍然没有体现optional字段留空不填的情形,也没有测试小整数(RIA应用中最常见的数据)的性能。

  7. 抛开optional字段留空以及小整数不论,目前您的测试代码如果在非debugger的Flash Player上跑,性能也不会有这么大差距。这是我跑出来的结果:


    [PROTOCOL BUFFERS]
    serialization
    small:
    size = 18b, cost = 0ms
    medium:
    size = 9.77kb, cost = 1ms
    big:
    size = 97.7kb, cost = 12ms

    deserialization
    small:
    cost = 0ms
    medium:
    cost = 1ms
    big:
    cost = 11ms

    [AMF3]
    serialization
    small:
    size = 90b, cost = 0ms
    medium:
    size = 12.8kb, cost = 0ms
    big:
    size = 127kb, cost = 10ms

    deserialization
    small:
    cost = 0ms
    medium:
    cost = 1ms
    big:
    cost = 7ms

    Total Memory = 4.41mb

  8. 有个老外也做过AMF和protobuf的性能比较,他用的是较早的protoc-gen-as3,性能比 0.9.x 稍差一点。

    http://backgroundthinking.wordpress.com/2010/05/24/performance-of-google%E2%80%99s-protocol-buffers-in-flex-redux/

    这个老外没贴代码,不知道他用的什么数据,但估计他填的数据中有许多小整数。在小整数很多的情况下,protobuf格式比AMF会小得多。他的测试结果可以体现这一点。

  9. 測試的部分還要再設計,這次測試主要是測大數據,且沒有測平均數,改良的做法或許可以參考你貼的網站

  10. 但不管怎样,debugger版的Flash Player会大大降低ActionScript执行效率。用debugger版测出来的数据没有参考价值。

  11. 嗯,您說的沒錯,會造成差異的因素應該盡量避免,我已更新release版的結果上去