FlatBuffers與protobuf性能比較

  FlatBuffers發佈時,順便也公佈了它的性能數據,具體數據請見Benchmark

    它的測試用例由以下數據構成"a set of about 10 objects containing an array, 4 strings, and a large variety of int/float scalar values of all sizes, meant to be representative of game data, e.g. a scene format."

   我感覺這樣測試如同兒戲,便自己設計了一個測試用例,主要關注CPU計算時間和內存空間佔用兩個指標,參考對象是protobuf。

   測試用例爲:序列化一個通訊錄personal_info_list(table),通訊錄可以認爲是有每個人的信息(personal_info)的集合。每個人信息personal_info(table)有:個人id(uint)、名字(string)、年齡(byte)、性別(enum, byte)和電話號碼(ulong)。本來我想用struct表示personal_info(table),但是struct不允許有數組或string成員,無奈我用table描述它了。相應的idl文件如下:

[cpp] view plain copy
  1. //////////////////////////////////////////////////////  
  2. //// FILE     : tellist.fbs  
  3. //// DESC     : basic message for msg-center  
  4. //// AUTHOR   : v 0.1 written by Alex Stocks on June 22, 2014  
  5. //// LICENCE  :  
  6. //// MOD      :  
  7. ////////////////////////////////////////////////////////  
  8.   
  9. namespace as.tellist;  
  10.   
  11. enum GENDER_TYPE : byte  
  12. {  
  13.     MALE    = 0,  
  14.     FEMALE  = 1,  
  15.     OTHER   = 2  
  16. }  
  17.   
  18. table personal_info  
  19. {  
  20.     id : uint;  
  21.     name : string;  
  22.     age : byte;  
  23.     gender : GENDER_TYPE;  
  24.     phone_num : ulong;  
  25. }  
  26.   
  27. table personal_info_list  
  28. {  
  29.     info : [personal_info];  
  30. }  
  31.   
  32. root_type personal_info_list;  

   因爲要以protobuf做性能參考,列出protobuf的idl文件如下:    

[cpp] view plain copy
  1. //////////////////////////////////////////////////////  
  2. //// FILE     : tellist.proto  
  3. //// DESC     : basic message for msg-center  
  4. //// AUTHOR   : v 0.1 written by Alex Stocks on June 22, 2014  
  5. //// LICENCE  :  
  6. //// MOD      :  
  7. ////////////////////////////////////////////////////////  
  8.   
  9. package as.tellist;  
  10.   
  11. enum gender_type  
  12. {  
  13.     MALE    = 0;  
  14.     FEMALE  = 1;  
  15.     OTHER   = 2;  
  16. }  
  17.   
  18. message personal_info  
  19. {  
  20.     optional uint32         id = 1;  
  21.     optional string         name = 2;  
  22.     optional uint32         age = 3;  
  23.     optional gender_type    gender = 4;  
  24.     optional uint64         phone_num = 5;  
  25. }  
  26.   
  27. message personal_info_list  
  28. {  
  29.     repeated personal_info  info = 1;  
  30. }  

    若用C的struct描述對應的頭文件(其對應的程序稱之爲“二進制”),如下:

[cpp] view plain copy
  1. /** 
  2.  * FILE        : tellist.h 
  3.  * DESC        : to test tellist 
  4.  * AUTHOR  : v1.0 written by Alex Stocks 
  5.  * DATE        : on June 28, 2014 
  6.  * LICENCE : GPL 2.0 
  7.  * MOD     : 
  8.  **/  
  9.   
  10. #ifndef __TELLIST_H__  
  11. #define __TELLIST_H__  
  12.   
  13. enum  
  14. {  
  15.  GENDER_TYPE_MALE = 0,  
  16.  GENDER_TYPE_FEMALE = 1,  
  17.  GENDER_TYPE_OTHER = 2,  
  18. };  
  19.   
  20.   
  21. inline const char **EnumNamesGENDER_TYPE()  
  22. {  
  23.  static const char *names[] = { "MALE""FEMALE""OTHER"};  
  24.  return names;  
  25. }  
  26.   
  27.   
  28. inline const char *EnumNameGENDER_TYPE(int e)  
  29. {  
  30.  return EnumNamesGENDER_TYPE()[e];  
  31. }  
  32.   
  33. typedef struct personal_info_tag  
  34. {  
  35.  unsigned           id;  
  36.  unsigned char      age;  
  37.  char               gender;  
  38.  unsigned long long phone_num;  
  39.  char               name[32];  
  40. } personal_info;  
  41.   
  42. typedef struct personal_info_list_tag  
  43. {  
  44.  int                size;  
  45.  personal_info  info[0];  
  46. } personal_info_list;  
  47.   
  48. #endif  
  49.   
  50. // the end of the header file tellist.h  

    測試時,在內存中構造37個personal_info對象,並序列化之,重複這個過程100萬次,然後再進行反序列化,再重複100萬次。

    測試結果如下(補充:tellist_pb是protobuf測試程序,tellist_fb是FlatBuffers測試程序,tellist_fb是二進制測試程序,):

[html] view plain copy
  1. 測試環境:12Core Intel(R) Xeon(R) CPU E5-2620 0 @ 2.00GHz  
  2. free  
  3.              total       used       free     shared    buffers     cached  
  4. Mem:      66081944   62222028    3859916          0     196448   43690828  
  5. -/+ buffers/cache:   18334752   47747192  
  6. Swap:       975864     855380     120484  
  7.   
  8. protobuf三次測試結果:  
  9. bin/tellist_pb   
  10. encode: loop = 1000000, time diff = 14210ms  
  11. decode: loop = 1000000, time diff = 11185ms  
  12. buf size:841  
  13.   
  14. bin/tellist_pb   
  15. encode: loop = 1000000, time diff = 14100ms  
  16. decode: loop = 1000000, time diff = 11234ms  
  17. buf size:841  
  18.   
  19. bin/tellist_pb   
  20. encode: loop = 1000000, time diff = 14145ms  
  21. decode: loop = 1000000, time diff = 11237ms  
  22. buf size:841  
  23. 序列化後佔用內存空間841Byte,encode平均運算時間42455ms / 3 = 14151.7ms,decode平均計算時間33656ms / 3 = 11218.7ms  
  24.   
  25. flatbuffers三次測試結果:  
  26.  bin/tellist_fb   
  27. encode: loop = 1000000, time diff = 11666ms  
  28. decode: loop = 1000000, time diff = 1141ms  
  29. buf size:1712  
  30.   
  31. bin/tellist_fb   
  32. encode: loop = 1000000, time diff = 11539ms  
  33. decode: loop = 1000000, time diff = 1200ms  
  34. buf size:1712  
  35.   
  36. bin/tellist_fb   
  37. encode: loop = 1000000, time diff = 11737ms  
  38. decode: loop = 1000000, time diff = 1141ms  
  39. buf size:1712  
  40. 序列化後佔用內存空間1712Byte,encode平均運算時間34942ms / 3 = 11647.3ms,decode平均計算時間3482ms / 3 = 1160.7ms  
  41.   
  42. 二進制三次測試結果:  
  43. bin/tellist   
  44. encode: loop = 1000000, time diff = 4967ms  
  45. decode: loop = 1000000, time diff = 688ms  
  46. buf size:304  
  47.   
  48.  bin/tellist   
  49. encode: loop = 1000000, time diff = 4971ms  
  50. decode: loop = 1000000, time diff = 687ms  
  51. buf size:304  
  52.   
  53. bin/tellist   
  54. encode: loop = 1000000, time diff = 4966ms  
  55. decode: loop = 1000000, time diff = 686ms  
  56. buf size:304  
  57. 序列化後佔用內存空間304Byte,encode平均運算時間14904ms / 3 = 4968ms,decode平均計算時間2061ms / 3 = 687ms  
  58.   
  59. 測試環境:1 Core Intel(R) Core(TM) i5-3210M CPU @ 2.50GHz  
  60. free  
  61.              total       used       free     shared    buffers     cached  
  62. Mem:        753932     356036     397896          0      50484     224848  
  63. -/+ buffers/cache:      80704     673228  
  64. Swap:      1324028        344    1323684  
  65. protobuf三次測試結果:  
  66. ./bin/tellist_pb   
  67. encode: loop = 1000000, time diff = 12451ms  
  68. decode: loop = 1000000, time diff = 9662ms  
  69. buf size:841  
  70.   
  71. ./bin/tellist_pb   
  72. encode: loop = 1000000, time diff = 12545ms  
  73. decode: loop = 1000000, time diff = 9840ms  
  74. buf size:841  
  75.   
  76. ./bin/tellist_pb   
  77. encode: loop = 1000000, time diff = 12554ms  
  78. decode: loop = 1000000, time diff = 10460ms  
  79. buf size:841  
  80. 序列化後佔用內存空間841Byte,encode平均運算時間37550ms / 3 = 12516.7ms,decode平均計算時間29962ms / 3 = 9987.3ms  
  81.   
  82. flatbuffers三次測試結果:  
  83. bin/tellist_fb   
  84. encode: loop = 1000000, time diff = 9640ms  
  85. decode: loop = 1000000, time diff = 1164ms  
  86. buf size:1712  
  87.   
  88. bin/tellist_fb   
  89. encode: loop = 1000000, time diff = 9595ms  
  90. decode: loop = 1000000, time diff = 1170ms  
  91. buf size:1712  
  92.   
  93. bin/tellist_fb   
  94. encode: loop = 1000000, time diff = 9570ms  
  95. decode: loop = 1000000, time diff = 1172ms  
  96. buf size:1712  
  97. 序列化後佔用內存空間1712Byte,encode平均運算時間28805ms / 3 = 9345ms,decode平均計算時間3506ms / 3 = 1168.7ms  
  98.   
  99. 二進制三次測試結果:  
  100. bin/tellist   
  101. encode: loop = 1000000, time diff = 4194ms  
  102. decode: loop = 1000000, time diff = 538ms  
  103. buf size:304  
  104.   
  105. bin/tellist   
  106. encode: loop = 1000000, time diff = 4387ms  
  107. decode: loop = 1000000, time diff = 544ms  
  108. buf size:304  
  109.   
  110. bin/tellist   
  111. encode: loop = 1000000, time diff = 4181ms  
  112. decode: loop = 1000000, time diff = 533ms  
  113. buf size:304  
  114. 序列化後佔用內存空間304Byte,encode平均運算時間12762ms / 3 = 4254ms,decode平均計算時間1615ms / 3 = 538.3ms  

    上面的二進制程序的結果無論在內存空間佔用還是cpu計算時間這兩個指標上都是最快的。但本文只討論FlatBuffers和protobuf,所以不讓它的結果參與比較。

    從以上數據看出,在內存空間佔用這個指標上,FlatBuffers佔用的內存空間比protobuf多了兩倍。序列化時二者的cpu計算時間FB比PB快了3000ms左右,反序列化時二者的cpu計算時間FB比PB快了9000ms左右。FB在計算時間上佔優勢,而PB則在內存空間上佔優(相比FB,這也正是它計算時間比較慢的原因)。

    上面的測試環境是在公司的linux server端和我自己的mac pro分別進行的。請手機端開發者自己也在手機端進行下測試, 應該能得到類似的結果。Google宣稱FB適合遊戲開發是有道理的,如果在乎計算時間我想它也適用於後臺開發。

    另外,FB大量使用了C++11的語法,其從idl生成的代碼接口不如protubuf友好。不過相比使用protobuf時的一堆頭文件和佔18M之多的lib庫,FlatBuffers僅僅一個"flatbuffers/flatbuffers.h"就足夠了。

    測試程序已經上傳到百度網盤,點擊這個鏈接即可下載。歡迎各位的批評意見。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章