The Java 6 VM must be magic
I am currently experimenting / prototyping some code that makes an intensive use of Java NIO features. The code that I am writing is tested on large sets of data (around 200 MB for an average test).
Although I cannot share the code, I thought that I would share with you some suprising results, hoping that some Java VM expert can pop up and tell me why on earth I am getting those results
I did a first naive implementation: whenever I need a byte array or (heap) ByteBuffer, a new instance is created. That makes the code easy to make work. The flip side of the coin is that those buffers are instanciated... well... very very often.
I branched my code and decided to reuse buffers, so that a very limited and constrained set of them would be allocated. The code got free of buffer allocations, and I was hoping for a dramatic performance boost...
...and I was wrong.
It turns out that on a specific data set, both implementations run in approximately 28s (Apple Java 6 64bits). I ran the tests several times: the naive approach first then the "improved" one second and vice-versa.
I even used a profiler to see what was going on, and the result is that the naive approach is not only as fast as the other one, but it consumes just about 100kb of extra non-heap memory. Just to make it straight once again: buffers are allocated almost all the time.
In a way this is a pleasing result: I can stick with a naive, simple code that will also be easier to make multithreading-compliant than the one that takes care of reusing buffers.
Now I need to understand why I get this result. After all, the C programmer in me tells me that allocation has a significant cost.
I wonder if the JVM is able to reuse unreferenced instances of the same type and same size. There is maybe some caching happening on the ByteBuffer objects allocations as well.
Does anyone have a clue? I'm really puzzled.
Related posts:
- Random bullet points that are related to Java stuff
- IzPack and Java Web Start
- Initialization blocks in Java
- Java: flashback in time
- Playing with Berkeley DB Java Edition and Guice

March 9th, 2009 - 23:51
Sure, this behaviour looks… well, magic.
I’d like to know this answer too.
Moreover, you make me lol when you write: “the C programmer in me”!
March 10th, 2009 - 08:10
“premature optimization is the root of all evil.” — D. Knuth
There actually seems to be a caching behaviour under the hood, just like
integers if I’m right. Well, more like reusing unused instances instead of gc
them and re instantiate, as you suggested. But as you know, I’m not a Java
expert