有人告诉我,flatbuffer的性能比proto好,我对flatbuffer和protobuf的性能进行了测试,我可以确定std向量没有影响。通过序列化和脱序列可以很快,但是总花费时间是不止是原始的。 protobuf比flatbuf更好,还是我在某些细节上犯了错误?
flatbuffer样本
#include"person.pb.h"
#include<sys/time.h>
int main(int argc,char *argv[])
{
if(argc<2)
{
printf("<usage> num\n");
return -1;
}
size_t iNum = strtoul(argv[1],NULL,10);
person::School school;
for(size_t i=0;i<iNum;++i)
{
person::Person *p = school.add_student();
p->set_name("rockycai");
p->set_age(i);
}
timeval tbegin,tend;
std::string buffer;
gettimeofday(&tbegin,NULL);
school.SerializeToString(&buffer);
gettimeofday(&tend,NULL);
unsigned long int uUsedMs = (tend.tv_sec - tbegin.tv_sec) * 1000 +
(tend.tv_usec - tbegin.tv_usec) / 1000;
printf("serialize size %u cost time %lu\n",buffer.size(),uUsedMs);
person::School school1;
gettimeofday(&tbegin,NULL);
school1.ParseFromString(buffer);
gettimeofday(&tend,NULL);
uUsedMs = (tend.tv_sec - tbegin.tv_sec) * 1000 +
(tend.tv_usec - tbegin.tv_usec) / 1000;
printf("deserialize time %lu\n",uUsedMs);
return 0;
}
protbuf示例:
timeval tbegin,tend;
gettimeofday(&tbegin,NULL);
timeval tbegin1,tend1;
unsigned long int iTotal = 0;
for(size_t i=0;i<iNum;++i)
{
auto name = builder.CreateString("rockycai");
uint32_t age = i;
auto student = CreateStudent(builder,name,age);
gettimeofday(&tbegin1,NULL);
student_vector.push_back(student);
gettimeofday(&tend1,NULL);
iTotal += ((tend1.tv_sec - tbegin1.tv_sec) * 1000 + (tend1.tv_usec - tbegin1.tv_usec) / 1000);
}
gettimeofday(&tend,NULL);
unsigned long int uUsedMs = (tend.tv_sec - tbegin.tv_sec) * 1000 +
(tend.tv_usec - tbegin.tv_usec) / 1000;
printf("insert time %lu vector time %lu\n",uUsedMs,iTotal);
gettimeofday(&tbegin,NULL);
auto vecStu = builder.CreateVector(student_vector);
auto school = CreateSchool(builder,vecStu);
gettimeofday(&tend,NULL);
uUsedMs = (tend.tv_sec - tbegin.tv_sec) * 1000 + (tend.tv_usec - tbegin.tv_usec) / 1000;
printf("flat prepare time %lu\n",uUsedMs);
gettimeofday(&tbegin,NULL);
builder.Finish(school);
gettimeofday(&tend,NULL);
uUsedMs = (tend.tv_sec - tbegin.tv_sec) * 1000 +
(tend.tv_usec - tbegin.tv_usec) / 1000;
printf("serialized size %u costtime %lu\n",builder.GetSize(),uUsedMs);
gettimeofday(&tbegin,NULL);
auto res = GetSchool(builder.GetBufferPointer());
gettimeofday(&tend,NULL);
uUsedMs = (tend.tv_sec - tbegin.tv_sec) * 1000 + (tend.tv_usec - tbegin.tv_usec) / 1000;
printf("deserialize time %lu\n",uUsedMs);
flatbuffer结果
$ ./sample_person 10000000
insert time 9232 vector time 1
flat prepare time 1493
serialized size 320000024 costtime 0
deserialize time 0
protobuf结果
$ ./test_person 10000000
serialize size 167886336 cost time 2799
deserialize time 4446
平面定义
namespace My.School;
table Student
{
name:string;
age:uint32;
}
table School
{
student:[Student];
}
root_type School;
原型定义
package person;
message Person
{
optional string name = 1;
optional uint32 age = 2;
}
message School
{
repeated Person student = 1;
}
更新...整个代码:
#include "person_generated.h"
#include<sys/time.h>
using namespace My::School;
int main(int argc,char *argv[])
{
timeval ttbegin,ttend;
gettimeofday(&ttbegin,NULL);
if(argc<2)
{
printf("<usage> num\n");
return -1;
}
size_t iNum = strtoul(argv[1],NULL,10);
flatbuffers::FlatBufferBuilder builder(10000000);
std::vector<flatbuffers::Offset<Student>> student_vector;
student_vector.reserve(10000000);
timeval tbegin,tend;
gettimeofday(&tbegin,NULL);
//timeval tbegin1,tend1;
unsigned long int iTotal = 0;
for(size_t i=0;i<iNum;++i)
{
auto name = builder.CreateString("rockycai");
uint32_t age = i;
auto student = CreateStudent(builder,name,age);
//gettimeofday(&tbegin1,NULL);
student_vector.push_back(student);
//gettimeofday(&tend1,NULL);
//iTotal += ((tend1.tv_sec - tbegin1.tv_sec) * 1000 + (tend1.tv_usec - tbegin1.tv_usec) / 1000);
}
gettimeofday(&tend,NULL);
unsigned long int uUsedMs = (tend.tv_sec - tbegin.tv_sec) * 1000 +
(tend.tv_usec - tbegin.tv_usec) / 1000;
printf("insert time %lu\n",uUsedMs);
gettimeofday(&tbegin,NULL);
auto vecStu = builder.CreateVector(student_vector);
auto school = CreateSchool(builder,vecStu);
gettimeofday(&tend,NULL);
uUsedMs = (tend.tv_sec - tbegin.tv_sec) * 1000 + (tend.tv_usec - tbegin.tv_usec) / 1000;
printf("flat prepare time %lu\n",uUsedMs);
gettimeofday(&tbegin,NULL);
builder.Finish(school);
gettimeofday(&tend,NULL);
uUsedMs = (tend.tv_sec - tbegin.tv_sec) * 1000 +
(tend.tv_usec - tbegin.tv_usec) / 1000;
printf("serialized size %u costtime %lu\n",builder.GetSize(),uUsedMs);
gettimeofday(&tbegin,NULL);
auto res = GetSchool(builder.GetBufferPointer());
gettimeofday(&tend,NULL);
uUsedMs = (tend.tv_sec - tbegin.tv_sec) * 1000 + (tend.tv_usec - tbegin.tv_usec) / 1000;
printf("deserialize time %lu\n",uUsedMs);
gettimeofday(&ttend,NULL);
uUsedMs = (ttend.tv_sec - ttbegin.tv_sec) * 1000 + (ttend.tv_usec - ttbegin.tv_usec) / 1000;
printf("total time %lu\n",uUsedMs);
return 0;
}
#include"person.pb.h"
#include<sys/time.h>
int main(int argc,char *argv[])
{
timeval ttbegin,ttend;
gettimeofday(&ttbegin,NULL);
if(argc<2)
{
printf("<usage> num\n");
return -1;
}
size_t iNum = strtoul(argv[1],NULL,10);
person::School school;
timeval tbegin,tend;
gettimeofday(&tbegin,NULL);
for(size_t i=0;i<iNum;++i)
{
person::Person *p = school.add_student();
p->set_name("rockycai");
p->set_age(i);
}
gettimeofday(&tend,NULL);
unsigned long int uUsedMs = (tend.tv_sec - tbegin.tv_sec) * 1000 + (tend.tv_usec - tbegin.tv_usec) / 1000;
printf("vector time %lu\n",uUsedMs);
std::string buffer;
gettimeofday(&tbegin,NULL);
school.SerializeToString(&buffer);
gettimeofday(&tend,NULL);
uUsedMs = (tend.tv_sec - tbegin.tv_sec) * 1000 +
(tend.tv_usec - tbegin.tv_usec) / 1000;
printf("serialize size %u cost time %lu\n",buffer.size(),uUsedMs);
person::School school1;
gettimeofday(&tbegin,NULL);
school1.ParseFromString(buffer);
gettimeofday(&tend,NULL);
uUsedMs = (tend.tv_sec - tbegin.tv_sec) * 1000 +
(tend.tv_usec - tbegin.tv_usec) / 1000;
printf("deserialize time %lu\n",uUsedMs);
gettimeofday(&ttend,NULL);
uUsedMs = (ttend.tv_sec - ttbegin.tv_sec) * 1000 + (ttend.tv_usec - ttbegin.tv_usec) / 1000;
printf("total time %lu\n",uUsedMs);
return 0;
}
res is:
$ ./sample_person 10000000
insert time 7763
flat prepare time 1159
serialized size 320000024 costtime 0
deserialize time 0
total time 8922
$ ./test_person 10000000
vector time 2598
serialize size 167886336 cost time 2706
deserialize time 4676
total time 9981
答案 0 :(得分:1)
您可能希望将gettimeofday
从内部循环中删除,因为这可能会花费大量时间来影响计时。如果您不希望push_back
花费任何费用,请确保在循环之前保留其大小。
对于其余的代码,比较是苹果与橘子。对于ProtoBuf,您仅测量SerializeToString
,而要使此功能正常工作,您必须分配(并取消分配)Protobuf对象的向量。您这次没有测量。 FlatBuffer一次性完成了所有这些工作,成为序列化的一部分,它不需要中间的数据结构(除了上面提到的向量)。
代码也没有显示如何创建FlatBufferBuilder
,因为默认大小合适会带来很大的不同。