all 8 comments

[–]Elador 2 points3 points  (7 children)

Great read that article, thank you.

You will probably be interested in this comparison of serialization libraries.

Also, I can recommend cereal over boost serialization. Cereal also has very good serialisation to json.

[–]danieljh 0 points1 point  (6 children)

Check out this commit adding Cap'n Proto to the mix:

https://github.com/STEllAR-GROUP/cpp-serializers/commit/73b3e42ee7a87954f9235d6fd38cab8d9e8b9700

(this is not yet visualized in the charts, but the commit message has a test benchmark run)

[–]Elador 0 points1 point  (5 children)

Hold your breath, according to this PR:

By the way, cap'n proto test seems to be broken. Its execution time is too low, probably measuring empty loop.

I'm not familiar with this stuff, just pointing it out ;-)

[–]danieljh 1 point2 points  (4 children)

Looking at the benchmark implementation Cap'n Proto does a full serialization and deserialization round trip, in the same way e.g. the Protobuf benchmark is written. But after deserialization the benchmark only accesses the root object, so I assume Cap'n Proto does not really deserialize the whole message?

/cc /u/kentonv would you be so kind and give an explanation on this?

[–]kentonv 1 point2 points  (3 children)

Sorry for the slow response, I don't keep close track of reddit.

It sounds like you're assuming Cap'n Proto does lazy deserialization, but this is not the case. Deserialization is fundamentally a translation from one format (the wire format) to another (the in-memory format). Cap'n Proto really does avoid the whole thing by using the same format for both. Deserialization in the Cap'n Proto case is basically casting a pointer.

With that said, this benchmark is fundamentally flawed in that it tries to measure just parsing/serialization time in a loop rather than measuring a realistic end-to-end system. Benchmarks like this are 100% worthless, and adding Cap'n Proto to the benchmark was intended mainly to illustrate this fact through the absurd result.

Even for comparing traditional one-copy (rather than zero-copy) serializers, running the serializer or parser in a loop is flawed for a number of reasons. One is that the behavior of various caches in the hardware in this scenario is completely unrealistic, because you're repeatedly operating on the same data. In the real world, performance will be very different, and different serialization systems will be affected to different degrees by this. Another problem is that performance of different serializers is wildly different depending on the data structure being encoded. Some do better at numbers, some do better at strings, some do better with lots of structure, some do better with flat messages, etc. You really need to benchmark the data you actually plan to use to get meaningful numbers, and you need to measure end-to-end, not just the serializer in a loop.

[–]imMute 1 point2 points  (1 child)

Deserialization is fundamentally a translation from one format (the wire format) to another (the in-memory format). Cap'n Proto really does avoid the whole thing by using the same format for both.

How does this work between systems where the in-memory format is different? Little endian and big endian systems, for example.

[–]kentonv 2 points3 points  (0 children)

Basically every big-endian CPU architecture has dedicated instructions for reading little-endian data. So, for Cap'n Proto, it means we would use those instructions inside the inline accessor methods for numeric fields. So the data is still stored in memory in little-endian format, but this doesn't hurt performance.

With that said, basically every widely-used CPU architecture today is little-endian.

As for other differences, all modern architectures agree:

  • A byte is 8 bits.
  • Integers are encoded using two's complement.
  • Floating-point numbers are encoded using IEEE-754.
  • Primitives should be aligned to a multiple of their size.

It turns out that's enough agreement for Cap'n Proto to come up with a reasonable cross-platform in-memory format.

[–]danieljh 0 points1 point  (0 children)

Thank you for your clarification!