I've been implementing Netty 4 on my app and I've ran into a limitation which I would like to optimize.
I'm using NioSocketChannel where when I receive data, the final object it needs to end up into is a Direct ByteBuffer Native,created as such:
ByteBuffer.allocateDirect(var0).order(ByteOrder.nativeOrder());
This is hard requirement, I can't go around it.
To minimize object allocation, I'm using a ByteBufferPool and my ChannelRead looks something like this:
try{
receivingBuf.writeBytes((ByteBuf) msg);
if(receivingBuf.readableBytes() >= nextPacketLength){
var bb = ByteBufferPoolManager.getByteBuffer();
receivingBuf.readBytes(bb.array(), 0, nextPacketLength-12);
bb.position(0);
bb.limit(nextPacketLength - 12);
MyCustomMethodToProcessData(bb);
}
}
finally
{
((ByteBuf) msg).release();
}
Please ignore the -12 bytes, that is due to the format of my packets. Also, ByteBufferPoolManager.getByteBuffer()
returns a normal heap ByteBuffer.
GOAL: Transfer a specific number of bytes from receivingBuf
into a Direct Native Order allocated ByteBuffer.
I tried to do this:
var bb = ByteBufferPoolManager.getNativeByteBuffer();
receivingBuf.readBytes(bb.array(), 0, nextPacketLength-12);
bb.position(0);
bb.limit(nextPacketLength - 12);
MyCustomMethodToProcessData(bb);
But this doesn't work, as you can't access .array()
on a Direct ByteBuffer. You get exception:
java.lang.UnsupportedOperationException
at java.base/java.nio.ByteBuffer.array(ByteBuffer.java:1471)
If I do:
var bb = ByteBufferPoolManager.getNativeByteBuffer();
receivingBuf.readBytes(bb, 0, nextPacketLength-12);
...
This doesn't exist as an available method on ByteBuf.
Additionally, if I do:
var bb = ByteBufferPoolManager.getNativeByteBuffer();
receivingBuf.readBytes(bb);
...
Will cause an exception, as the Native ByteBuffer is massive (1000000 size), and ByteBuf will attempt to copy over 1 million bytes, while the available bytes on the ByteBuf is way less than that.
One option I've considered, is having a byte[] per channel context, which is used exclusively do to this data transfer, but still, I don't think I will have much improvements vs what I'm doing now.
Any ideas on how I can remove this middle hop in ByteBuf -> Heap ByteBuffer -> Native ByteBuffer
?