Native C/C++ Like Performance For Java Object Serialisation
mechanical-sympathy.blogspot.com
mechanical-sympathy.blogspot.com
The main reason that Java serialization is so slow is that it is designed to persist self-describing, arbitrary object graphs.
Self-describing = Full package+class names and versions. Any object graph containing Serializable classes available via the classloaders of both the sender and receiver.
Arbitrary object graphs = The identity of objects is preserved. Let's say that 17 SalesOrder objects point to the same Customer object. salesOrderA.getCustomer() == salesOrderB.getCustomer() (identity in Java for those who haven't had the pleasure) is maintained.
Oh, and JDK dynamic proxies are handled as a special case. And some other stuff, too. I had the pleasure a few months ago of copying the JDK's serialization code into my own package structure and adding logging so we could debug deser issues in an OSGi environment. From what I can tell, the impedence mismatch between OSGi classloading hierarchies and Java Serialization makes this combination a non-starter.
The very-performant sample case provided in the blog posting works only for a list of flat objects. As soon as you try to preserve identity, you must implement a two-pass system where you deser placeholders and then resolve them later. I'm not suggesting that it isn't useful, but it probably constrains your serializable objects to such a degree that you'll be unhappy in other areas of your system.
Kyro (as another commenter noted) seems like the best combination of small size/speed/general-ness that I've encountered thus far. There seem to be a reasonable number of pre-built Kyro serializers for common libraries such as Joda time.
For a project I worked on recently where size was more important than speed, I took advantage of the similarity of the objects I was serializing and wrote a custom serializer which created dictionary look-ups on the fly. Repeated strings were turned into small integers, etc. I wish I didn't have to write it.
In a nutshell, if you constrain the scope of the problem you are attempting to solve, the maximum possible performance of the system across covered use-cases goes up. Java Serialization's performance is relatively poor compared to less generalized schemes -- as expected.
Hadoop's IPC protocol does something similar to what this article describes. They roll their own serialization format[0] and write to a wrapped ByteArrayOutputStream[1].
[0]: Example of a serialized object: https://github.com/apache/hadoop-common/blob/fdf697eebc95cbb...
[1]: https://github.com/apache/hadoop-common/blob/fdf697eebc95cbb...
If you check the code you will see the buffer is only allocated once so the cost is not an issue.
kryo - Fast, efficient Java serialization and cloning
http://code.google.com/p/kryo/
It'd be fun to see how kryo stacks against native C++.
It doesn't just happen in Java, it happens in C++ stuff too, and it can even be the throughput bottleneck for data going from the right kind of disk to the network -- that's why zero-copy I/O exists.