views:

101

answers:

3

Hi everyone, I'm wonder how I'd code up a ByteBuffer recycling class that can get me a ByteBuffer which is at least as big as the specified length, and which can lock up ByteBuffer objects in use to prevent their use while they are being used by my code. This would prevent re-construction of DirectByteBuffers and such over and over, instead using existing ones. Is there an existing Java library which can do this very effectively? I know Javolution can work with object recycling, but does that extend to the ByteBuffer class in this context with the requirements set out?

Cheers,
Chris

+1  A: 

This is just advice, not an answer. If you do implement some caching for DirectByteBuffer, then be sure to read about the GC implications, because the memory consumed by DirectByteBuffer is not tracked by the garbage collector.

Some references:

A thread - featuring Stack Overflow's tackline

A blog post on the same subject

And the followup

daveb
Cheers for that. Thinking about it, I need to be more rigorous in my garbage collection, ugh :)
Chris Dennett
As the post suggests, it may be wise to allocate a huge direct bytebuffer and allocate portions of this for use, and so the problem shifts to reducing fragmentation in the user-created heap, for which an API is even more important to handle this :) I want to avoid the pain of writing a heap allocator if possible, lol
Chris Dennett
Sounds fun, well at least for the first couple of hours...
daveb
+2  A: 

It would be more to the point to be more conservative in your usage patterns in the first place. For example there is lots of code out there that shows allocation of a new ByteBuffer on every OP_READ. This is insane. You only need two ByteBuffers at most per connection, one for input and one for output, and depending on what you're doing you can get away with exactly one. In extremely simple cases like an echo server you can get away with one BB for the entire application.

I would look into that rather than paper over the cracks with yet another layer of software.

EJP
+1  A: 

Typically, you would use combination of ThreadLocal and SoftReference wrapper. Former to simplify synchronization (eliminate need for it, essentially); and latter to make buffer recycleable if there's not enough memory (keeping in mind other comments wrt. GC issues with direct buffers). It's actually quite simple: check if SoftReference has buffer with big enough size; if not, allocate; if yes, clear reference. Once you are done with it, re-set reference to point to buffer.

Another question is whether ByteBuffer is needed, compared to regular byte[]. Many developers assume ByteBuffers are better performance-wise, but that assumption is not usually backed by actual data (i.e. testing to see if there is performance difference, and to what direction). Reason why byte[] may often be faster is that code accessing it can be simpler, easier for HotSpot to efficiently JIT.

StaxMan
In the end, I think I used Grizzly's slab allocator :) And for Apache MINA apps, I rewrote the IoBuffer class to use that slab allocator as a backend instead.
Chris Dennett
Cool, reusing existing well-implemented functionality is usually the best way :)
StaxMan