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"就足够了。

    测试程序已经上传到百度网盘,点击这个链接即可下载。欢迎各位的批评意见。

 

你可能感兴趣的:(protobuf)