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文件例如以下:
////////////////////////////////////////////////////// //// FILE : tellist.fbs //// DESC : basic message for msg-center //// AUTHOR : v 0.1 written by Alex Stocks on June 22, 2014 //// LICENCE : //// MOD : //////////////////////////////////////////////////////// namespace as.tellist; enum GENDER_TYPE : byte { MALE = 0, FEMALE = 1, OTHER = 2 } table personal_info { id : uint; name : string; age : byte; gender : GENDER_TYPE; phone_num : ulong; } table personal_info_list { info : [personal_info]; } root_type personal_info_list;
由于要以protobuf做性能參考。列出protobuf的idl文件例如以下:
////////////////////////////////////////////////////// //// FILE : tellist.proto //// DESC : basic message for msg-center //// AUTHOR : v 0.1 written by Alex Stocks on June 22, 2014 //// LICENCE : //// MOD : //////////////////////////////////////////////////////// package as.tellist; enum gender_type { MALE = 0; FEMALE = 1; OTHER = 2; } message personal_info { optional uint32 id = 1; optional string name = 2; optional uint32 age = 3; optional gender_type gender = 4; optional uint64 phone_num = 5; } message personal_info_list { repeated personal_info info = 1; }
若用C的struct描写叙述相应的头文件(其相应的程序称之为“二进制”)。例如以下:
/** * FILE : tellist.h * DESC : to test tellist * AUTHOR : v1.0 written by Alex Stocks * DATE : on June 28, 2014 * LICENCE : GPL 2.0 * MOD : **/ #ifndef __TELLIST_H__ #define __TELLIST_H__ enum { GENDER_TYPE_MALE = 0, GENDER_TYPE_FEMALE = 1, GENDER_TYPE_OTHER = 2, }; inline const char **EnumNamesGENDER_TYPE() { static const char *names[] = { "MALE", "FEMALE", "OTHER"}; return names; } inline const char *EnumNameGENDER_TYPE(int e) { return EnumNamesGENDER_TYPE()[e]; } typedef struct personal_info_tag { unsigned id; unsigned char age; char gender; unsigned long long phone_num; char name[32]; } personal_info; typedef struct personal_info_list_tag { int size; personal_info info[0]; } personal_info_list; #endif // the end of the header file tellist.h
測试时,在内存中构造37个personal_info对象。并序列化之,反复这个过程100万次。然后再进行反序列化,再反复100万次。
測试结果例如以下(补充:tellist_pb是protobuf測试程序,tellist_fb是FlatBuffers測试程序,tellist_fb是二进制測试程序。):
測试环境:12Core Intel(R) Xeon(R) CPU E5-2620 0 @ 2.00GHz free total used free shared buffers cached Mem: 66081944 62222028 3859916 0 196448 43690828 -/+ buffers/cache: 18334752 47747192 Swap: 975864 855380 120484 protobuf三次測试结果: bin/tellist_pb encode: loop = 1000000, time diff = 14210ms decode: loop = 1000000, time diff = 11185ms buf size:841 bin/tellist_pb encode: loop = 1000000, time diff = 14100ms decode: loop = 1000000, time diff = 11234ms buf size:841 bin/tellist_pb encode: loop = 1000000, time diff = 14145ms decode: loop = 1000000, time diff = 11237ms buf size:841 序列化后占用内存空间841Byte,encode平均运算时间42455ms / 3 = 14151.7ms,decode平均计算时间33656ms / 3 = 11218.7ms flatbuffers三次測试结果: bin/tellist_fb encode: loop = 1000000, time diff = 11666ms decode: loop = 1000000, time diff = 1141ms buf size:1712 bin/tellist_fb encode: loop = 1000000, time diff = 11539ms decode: loop = 1000000, time diff = 1200ms buf size:1712 bin/tellist_fb encode: loop = 1000000, time diff = 11737ms decode: loop = 1000000, time diff = 1141ms buf size:1712 序列化后占用内存空间1712Byte,encode平均运算时间34942ms / 3 = 11647.3ms,decode平均计算时间3482ms / 3 = 1160.7ms 二进制三次測试结果: bin/tellist encode: loop = 1000000, time diff = 4967ms decode: loop = 1000000, time diff = 688ms buf size:304 bin/tellist encode: loop = 1000000, time diff = 4971ms decode: loop = 1000000, time diff = 687ms buf size:304 bin/tellist encode: loop = 1000000, time diff = 4966ms decode: loop = 1000000, time diff = 686ms buf size:304 序列化后占用内存空间304Byte。encode平均运算时间14904ms / 3 = 4968ms,decode平均计算时间2061ms / 3 = 687ms 測试环境:1 Core Intel(R) Core(TM) i5-3210M CPU @ 2.50GHz free total used free shared buffers cached Mem: 753932 356036 397896 0 50484 224848 -/+ buffers/cache: 80704 673228 Swap: 1324028 344 1323684 protobuf三次測试结果: ./bin/tellist_pb encode: loop = 1000000, time diff = 12451ms decode: loop = 1000000, time diff = 9662ms buf size:841 ./bin/tellist_pb encode: loop = 1000000, time diff = 12545ms decode: loop = 1000000, time diff = 9840ms buf size:841 ./bin/tellist_pb encode: loop = 1000000, time diff = 12554ms decode: loop = 1000000, time diff = 10460ms buf size:841 序列化后占用内存空间841Byte,encode平均运算时间37550ms / 3 = 12516.7ms,decode平均计算时间29962ms / 3 = 9987.3ms flatbuffers三次測试结果: bin/tellist_fb encode: loop = 1000000, time diff = 9640ms decode: loop = 1000000, time diff = 1164ms buf size:1712 bin/tellist_fb encode: loop = 1000000, time diff = 9595ms decode: loop = 1000000, time diff = 1170ms buf size:1712 bin/tellist_fb encode: loop = 1000000, time diff = 9570ms decode: loop = 1000000, time diff = 1172ms buf size:1712 序列化后占用内存空间1712Byte,encode平均运算时间28805ms / 3 = 9345ms,decode平均计算时间3506ms / 3 = 1168.7ms 二进制三次測试结果: bin/tellist encode: loop = 1000000, time diff = 4194ms decode: loop = 1000000, time diff = 538ms buf size:304 bin/tellist encode: loop = 1000000, time diff = 4387ms decode: loop = 1000000, time diff = 544ms buf size:304 bin/tellist encode: loop = 1000000, time diff = 4181ms decode: loop = 1000000, time diff = 533ms buf size:304 序列化后占用内存空间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"就足够了。
測试程序已经上传到百度网盘,点击这个链接就可以下载。
欢迎各位的批评意见。
posted on 2017-04-18 21:26 gavanwanggw 阅读(532) 评论(0) 编辑 收藏 举报