Cache underlying ByteBuffers and count in ChannelOutboundBuffer.Entry to reduce object creation and so GC pressure
Beside this it also helps to reduce CPU usage as nioBufferCount() is quite expensive when used on CompositeByteBuf which are nested and contains a lot of components
This commit is contained in:
parent
fc805a0787
commit
c2101d3c56
@ -790,6 +790,5 @@ public abstract class AbstractCompositeByteBufTest extends AbstractByteBufTest {
|
|||||||
|
|
||||||
buf.addComponent(buffer().writeByte(1));
|
buf.addComponent(buffer().writeByte(1));
|
||||||
assertFalse(buf.isDirect());
|
assertFalse(buf.isDirect());
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -373,24 +373,40 @@ public final class ChannelOutboundBuffer {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Entry entry = buffer[i];
|
||||||
ByteBuf buf = (ByteBuf) m;
|
ByteBuf buf = (ByteBuf) m;
|
||||||
final int readerIndex = buf.readerIndex();
|
final int readerIndex = buf.readerIndex();
|
||||||
final int readableBytes = buf.writerIndex() - readerIndex;
|
final int readableBytes = buf.writerIndex() - readerIndex;
|
||||||
|
|
||||||
if (readableBytes > 0) {
|
if (readableBytes > 0) {
|
||||||
nioBufferSize += readableBytes;
|
nioBufferSize += readableBytes;
|
||||||
int count = buf.nioBufferCount();
|
int count = entry.count;
|
||||||
|
if (count == -1) {
|
||||||
|
entry.count = count = buf.nioBufferCount();
|
||||||
|
}
|
||||||
if (nioBufferCount + count > nioBuffers.length) {
|
if (nioBufferCount + count > nioBuffers.length) {
|
||||||
this.nioBuffers = nioBuffers = doubleNioBufferArray(nioBuffers, nioBufferCount);
|
this.nioBuffers = nioBuffers = doubleNioBufferArray(nioBuffers, nioBufferCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (buf.isDirect() || threadLocalDirectBufferSize <= 0) {
|
if (buf.isDirect() || threadLocalDirectBufferSize <= 0) {
|
||||||
if (buf.nioBufferCount() == 1) {
|
if (count == 1) {
|
||||||
nioBuffers[nioBufferCount ++] = buf.internalNioBuffer(readerIndex, readableBytes);
|
ByteBuffer nioBuf = entry.buf;
|
||||||
|
if (nioBuf == null) {
|
||||||
|
// cache ByteBuffer as it may need to create a new ByteBuffer instance if its a
|
||||||
|
// derived buffer
|
||||||
|
entry.buf = nioBuf = buf.internalNioBuffer(readerIndex, readableBytes);
|
||||||
|
}
|
||||||
|
nioBuffers[nioBufferCount ++] = nioBuf;
|
||||||
} else {
|
} else {
|
||||||
nioBufferCount = fillBufferArray(buf, nioBuffers, nioBufferCount);
|
ByteBuffer[] nioBufs = entry.buffers;
|
||||||
|
if (nioBufs == null) {
|
||||||
|
// cached ByteBuffers as they may be expensive to create in terms of Object allocation
|
||||||
|
entry.buffers = nioBufs = buf.nioBuffers();
|
||||||
|
}
|
||||||
|
nioBufferCount = fillBufferArray(nioBufs, nioBuffers, nioBufferCount);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
nioBufferCount = fillBufferArrayNonDirect(buffer[i], buf, readerIndex,
|
nioBufferCount = fillBufferArrayNonDirect(entry, buf, readerIndex,
|
||||||
readableBytes, alloc, nioBuffers, nioBufferCount);
|
readableBytes, alloc, nioBuffers, nioBufferCount);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -402,8 +418,7 @@ public final class ChannelOutboundBuffer {
|
|||||||
return nioBuffers;
|
return nioBuffers;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int fillBufferArray(ByteBuf buf, ByteBuffer[] nioBuffers, int nioBufferCount) {
|
private static int fillBufferArray(ByteBuffer[] nioBufs, ByteBuffer[] nioBuffers, int nioBufferCount) {
|
||||||
ByteBuffer[] nioBufs = buf.nioBuffers();
|
|
||||||
for (ByteBuffer nioBuf: nioBufs) {
|
for (ByteBuffer nioBuf: nioBufs) {
|
||||||
if (nioBuf == null) {
|
if (nioBuf == null) {
|
||||||
break;
|
break;
|
||||||
@ -424,10 +439,10 @@ public final class ChannelOutboundBuffer {
|
|||||||
directBuf.writeBytes(buf, readerIndex, readableBytes);
|
directBuf.writeBytes(buf, readerIndex, readableBytes);
|
||||||
buf.release();
|
buf.release();
|
||||||
entry.msg = directBuf;
|
entry.msg = directBuf;
|
||||||
if (nioBufferCount == nioBuffers.length) {
|
// cache ByteBuffer
|
||||||
nioBuffers = doubleNioBufferArray(nioBuffers, nioBufferCount);
|
ByteBuffer nioBuf = entry.buf = directBuf.internalNioBuffer(0, readableBytes);
|
||||||
}
|
entry.count = 1;
|
||||||
nioBuffers[nioBufferCount ++] = directBuf.internalNioBuffer(0, readableBytes);
|
nioBuffers[nioBufferCount ++] = nioBuf;
|
||||||
return nioBufferCount;
|
return nioBufferCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -578,17 +593,23 @@ public final class ChannelOutboundBuffer {
|
|||||||
|
|
||||||
private static final class Entry {
|
private static final class Entry {
|
||||||
Object msg;
|
Object msg;
|
||||||
|
ByteBuffer[] buffers;
|
||||||
|
ByteBuffer buf;
|
||||||
ChannelPromise promise;
|
ChannelPromise promise;
|
||||||
long progress;
|
long progress;
|
||||||
long total;
|
long total;
|
||||||
int pendingSize;
|
int pendingSize;
|
||||||
|
int count = -1;
|
||||||
|
|
||||||
public void clear() {
|
public void clear() {
|
||||||
|
buffers = null;
|
||||||
|
buf = null;
|
||||||
msg = null;
|
msg = null;
|
||||||
promise = null;
|
promise = null;
|
||||||
progress = 0;
|
progress = 0;
|
||||||
total = 0;
|
total = 0;
|
||||||
pendingSize = 0;
|
pendingSize = 0;
|
||||||
|
count = -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user