diff --git a/transport/src/main/java/io/netty/channel/ChannelOutboundBuffer.java b/transport/src/main/java/io/netty/channel/ChannelOutboundBuffer.java index 155d73f35e..d3a934a829 100644 --- a/transport/src/main/java/io/netty/channel/ChannelOutboundBuffer.java +++ b/transport/src/main/java/io/netty/channel/ChannelOutboundBuffer.java @@ -434,21 +434,9 @@ public final class ChannelOutboundBuffer { } nioBuffers[nioBufferCount++] = nioBuf; } else { - ByteBuffer[] nioBufs = entry.bufs; - if (nioBufs == null) { - // cached ByteBuffers as they may be expensive to create in terms - // of Object allocation - entry.bufs = nioBufs = buf.nioBuffers(); - } - for (int i = 0; i < nioBufs.length && nioBufferCount < maxCount; ++i) { - ByteBuffer nioBuf = nioBufs[i]; - if (nioBuf == null) { - break; - } else if (!nioBuf.hasRemaining()) { - continue; - } - nioBuffers[nioBufferCount++] = nioBuf; - } + // The code exists in an extra method to ensure the method is not too big to inline as this + // branch is not very likely to get hit very frequently. + nioBufferCount = nioBuffers(entry, buf, nioBuffers, nioBufferCount, maxCount); } if (nioBufferCount == maxCount) { break; @@ -463,6 +451,25 @@ public final class ChannelOutboundBuffer { return nioBuffers; } + private static int nioBuffers(Entry entry, ByteBuf buf, ByteBuffer[] nioBuffers, int nioBufferCount, int maxCount) { + ByteBuffer[] nioBufs = entry.bufs; + if (nioBufs == null) { + // cached ByteBuffers as they may be expensive to create in terms + // of Object allocation + entry.bufs = nioBufs = buf.nioBuffers(); + } + for (int i = 0; i < nioBufs.length && nioBufferCount < maxCount; ++i) { + ByteBuffer nioBuf = nioBufs[i]; + if (nioBuf == null) { + break; + } else if (!nioBuf.hasRemaining()) { + continue; + } + nioBuffers[nioBufferCount++] = nioBuf; + } + return nioBufferCount; + } + private static ByteBuffer[] expandNioBufferArray(ByteBuffer[] array, int neededSpace, int size) { int newCapacity = array.length; do { diff --git a/transport/src/main/java/io/netty/channel/nio/NioEventLoop.java b/transport/src/main/java/io/netty/channel/nio/NioEventLoop.java index f1aed11bc4..539ac81d37 100644 --- a/transport/src/main/java/io/netty/channel/nio/NioEventLoop.java +++ b/transport/src/main/java/io/netty/channel/nio/NioEventLoop.java @@ -793,17 +793,9 @@ public final class NioEventLoop extends SingleThreadEventLoop { selectCnt = 1; } else if (SELECTOR_AUTO_REBUILD_THRESHOLD > 0 && selectCnt >= SELECTOR_AUTO_REBUILD_THRESHOLD) { - // The selector returned prematurely many times in a row. - // Rebuild the selector to work around the problem. - logger.warn( - "Selector.select() returned prematurely {} times in a row; rebuilding Selector {}.", - selectCnt, selector); - - rebuildSelector(); - selector = this.selector; - - // Select again to populate selectedKeys. - selector.selectNow(); + // The code exists in an extra method to ensure the method is not too big to inline as this + // branch is not very likely to get hit very frequently. + selector = selectRebuildSelector(selectCnt); selectCnt = 1; break; } @@ -826,6 +818,21 @@ public final class NioEventLoop extends SingleThreadEventLoop { } } + private Selector selectRebuildSelector(int selectCnt) throws IOException { + // The selector returned prematurely many times in a row. + // Rebuild the selector to work around the problem. + logger.warn( + "Selector.select() returned prematurely {} times in a row; rebuilding Selector {}.", + selectCnt, selector); + + rebuildSelector(); + Selector selector = this.selector; + + // Select again to populate selectedKeys. + selector.selectNow(); + return selector; + } + private void selectAgain() { needsToSelectAgain = false; try {