производительность flatbuffer vs protobuf - PullRequest
0 голосов
/ 29 октября 2018

Мне сказали, что производительность flatbuffer лучше, чем proto, я проверил производительность на flatbuffer и protobuf, я могу быть уверен, что вектор std не оказал влияния больше чем прото. Protobuf лучше flatbuf или я ошибся в некоторых деталях?

образец плоского буфера

    #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);

результат плоского буфера

 $ ./sample_person 10000000
insert time 9232 vector time 1
flat prepare time 1493
serialized size 320000024 costtime 0
deserialize time 0

Результат протокола

$ ./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

1 Ответ

0 голосов
/ 30 октября 2018

Возможно, вы захотите извлечь gettimeofday из внутреннего цикла, поскольку это может занять значительное время, влияющее на время. Если вы не хотите, чтобы push_back что-то стоило, просто зарезервируйте его размер перед циклом.

Для остальной части кода сравнение между яблоками и апельсинами. Для ProtoBuf вы измеряете только SerializeToString, тогда как для работы этой функции вы должны выделить (и освободить) вектор объектов Protobuf. Вы не измеряете это время. FlatBuffer выполняет всю эту работу как часть сериализации сразу, не требует промежуточных структур данных (кроме упомянутого выше вектора).

Код также не показывает, как вы создаете FlatBufferBuilder, учитывая, что хороший размер по умолчанию будет иметь большое значение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...