title: Protobuf vs Flatbuffers vs Cap'n proto which is faster?
body: <p>I decided to figure out which of Protobuf, Flatbuffers and Cap'n proto would be the best/fastest serialization for my application. In my case sending some kind of byte/char array over a network (the reason I serialized to that format). So I made simple implementations for all three where i seialize and dezerialize a string, a float and an int. This gave unexpected resutls: Protobuf being the fastest. I would call them unexpected since both cap'n proto and flatbuffes "claims" to be faster options. Before I accept this I would like to see if I unitentionally cheated in my code somehow. If i did not cheat I would like to know why protobuf is faster (exactly why is probably impossible). Could the messages be to simeple for cap'n proto and faltbuffers to really make them shine? </p>
  
  <p><strong>My timings</strong>: </p>
  
  <p>Time taken flatbuffers: 14162 microseconds<br>
  Time taken capnp: 60259 microseconds<br>
  Time taken protobuf: 12131 microseconds<br>
  (obviously these are dependent on my machine but it is the relative time that matters)</p>
  
  <p><strong>flatbuffer code</strong>:  </p>
  
  <pre><code>int main (int argc, char *argv[]){
      std::string s = "string";
      float f = 3.14;
      int i = 1337;
  
      std::string s_r;
      float f_r;
      int i_r;
      flatbuffers::FlatBufferBuilder message_sender;
  
      int steps = 10000;
      auto start = high_resolution_clock::now(); 
      for (int j = 0; j &lt; steps; j++){
          auto autostring =  message_sender.CreateString(s);
          auto encoded_message = CreateTestmessage(message_sender, autostring, f, i);
          message_sender.Finish(encoded_message);
          uint8_t *buf = message_sender.GetBufferPointer();
          int size = message_sender.GetSize();
          message_sender.Clear();
          //Send stuffs
          //Receive stuffs
          auto recieved_message = GetTestmessage(buf);
  
          s_r = recieved_message-&gt;string_()-&gt;str();
          f_r = recieved_message-&gt;float_();
          i_r = recieved_message-&gt;int_(); 
      }
      auto stop = high_resolution_clock::now(); 
      auto duration = duration_cast&lt;microseconds&gt;(stop - start); 
      cout &lt;&lt; "Time taken flatbuffer: " &lt;&lt; duration.count() &lt;&lt; " microseconds" &lt;&lt; endl;
      return 0;
  }
  
  </code></pre>
  
  <p><strong>cap'n proto code</strong>:  </p>
  
  <pre><code>int main (int argc, char *argv[]){
      char s[] = "string";
      float f = 3.14;
      int i = 1337;
  
      const char * s_r;
      float f_r;
      int i_r;
      ::capnp::MallocMessageBuilder message_builder;
      Testmessage::Builder message = message_builder.initRoot&lt;Testmessage&gt;();
  
      int steps = 10000;
      auto start = high_resolution_clock::now(); 
      for (int j = 0; j &lt; steps; j++){  
          //Encodeing
          message.setString(s);
          message.setFloat(f);
          message.setInt(i);
  
          kj::Array&lt;capnp::word&gt; encoded_array = capnp::messageToFlatArray(message_builder);
          kj::ArrayPtr&lt;char&gt; encoded_array_ptr = encoded_array.asChars();
          char * encoded_char_array = encoded_array_ptr.begin();
          size_t size = encoded_array_ptr.size();
          //Send stuffs
          //Receive stuffs
  
          //Decodeing
          kj::ArrayPtr&lt;capnp::word&gt; received_array = kj::ArrayPtr&lt;capnp::word&gt;(reinterpret_cast&lt;capnp::word*&gt;(encoded_char_array), size/sizeof(capnp::word));
          ::capnp::FlatArrayMessageReader message_receiver_builder(received_array);
          Testmessage::Reader message_receiver = message_receiver_builder.getRoot&lt;Testmessage&gt;();
          s_r = message_receiver.getString().cStr();
          f_r = message_receiver.getFloat();
          i_r = message_receiver.getInt();
      }
      auto stop = high_resolution_clock::now(); 
      auto duration = duration_cast&lt;microseconds&gt;(stop - start); 
      cout &lt;&lt; "Time taken capnp: " &lt;&lt; duration.count() &lt;&lt; " microseconds" &lt;&lt; endl;
      return 0;
  
  }
  </code></pre>
  
  <p><strong>protobuf code</strong>:  </p>
  
  <pre><code>int main (int argc, char *argv[]){
      std::string s = "string";
      float f = 3.14;
      int i = 1337;
  
      std::string s_r;
      float f_r;
      int i_r;
      Testmessage message_sender;
      Testmessage message_receiver;
      int steps = 10000;
      auto start = high_resolution_clock::now(); 
      for (int j = 0; j &lt; steps; j++){
          message_sender.set_string(s);
          message_sender.set_float_m(f);
          message_sender.set_int_m(i);
          int len = message_sender.ByteSize();
          char encoded_message[len];
          message_sender.SerializeToArray(encoded_message, len);
          message_sender.Clear();
  
          //Send stuffs
          //Receive stuffs
          message_receiver.ParseFromArray(encoded_message, len);
          s_r = message_receiver.string();
          f_r = message_receiver.float_m();
          i_r = message_receiver.int_m();
          message_receiver.Clear();
  
      }
      auto stop = high_resolution_clock::now(); 
      auto duration = duration_cast&lt;microseconds&gt;(stop - start); 
      cout &lt;&lt; "Time taken protobuf: " &lt;&lt; duration.count() &lt;&lt; " microseconds" &lt;&lt; endl;
      return 0;
  }
  
  </code></pre>
  
  <p>not including the message definition files scince they are simple and most likely has nothing to do with it. </p>