Search code examples
javanettyniobytebufferzero-copy

Netty using ByteBuffer from pooled direct ByteBuf


I try to understand few things about netty's ByteBuf and its relation to nio.ByteBuffer.

the problem I try to solve is that my server has to return random portion of a file located on the server - this was implemented using nio.FileChannel and FChannel is depending on nio.ByteBuffer.

As I understand allocating direct ByteBuffer should be pooled - but there is no native pool implementation in nio - and my application should add such layer so I dont pay penalty of creating direct buffer for each request.

My application uses netty as server so I thought that I can use netty's pooled direct ByteBuff and access ByteBuffer it wraps using

var byteBuf = ctx.alloc().directBuffer(1024); // (1)
var chunkHolder = byteBuf.nioBuffer(0, byteBuf.capacity()); // (2)

so everything works as expected but .nioBuffer or .nioBuffers create a copy of the buffer - not just a view on ByteBuff so after writing to chunkHolder positions/limits/etc of byteBuf remains unchanged!

I have to use

var flip = chunkHolder.flip(); // (2)
var content = Unpooled.wrappedBuffer(flip);
ctx.writeAndFlush(content)
   .addListener(f -> byteBuf.release()); (1)

so object are created again, the only good thing is that that memory is not copied - if I am not mistaken.

the question: can I do something smarter so there is no data copying between tcp transport and file read with minimal garbage? is nio somehow helps in maintaining direct ByteBuffers?

The best idea that is coming to my mind is to wrap BytBuf with ByteBuffer-like implementation and proxy all write operation back to underlying byteBuf.

PS: I ve looked also at io/netty/channel/DefaultFileRegion.java as it works with nio.FileChannel but behind the scene netty uses nio directly

raf = new RandomAccessFile(filePath, "r");
ctx.write(new DefaultFileRegion(raf.getChannel(), 0, length));

Solution

  • FileRegion will do zero-copy transfer for you as it uses JDK's FileChannel#transferTo() internally. This will be the route for minimal garbage creation in this case.