Reduce the default initial capacity of ChannelOutboundBuffer

Motivation:

ChannelOutboundBuffer is basically a circular array queue of its entry
objects.  Once an entry is created in the array, it is never nulled out
to reduce the allocation cost.

However, because it is a circular queue, the array almost always ends up
with as many entry instances as the size of the array, regardless of the
number of pending writes.

At worst case, a channel might have only 1 pending writes at maximum
while creating 32 entry objects, where 32 is the initial capacity of the
array.

Modifications:

- Reduce the initial capacity of the circular array queue to 4.
- Make the initial capacity of the circular array queue configurable

Result:

We spend 4 times less memory for entry objects under certain
circumstances.
This commit is contained in:
Trustin Lee 2014-07-22 13:28:02 -07:00
parent 0062a871f4
commit 7e362277b9
2 changed files with 12 additions and 4 deletions

View File

@ -27,6 +27,7 @@ import io.netty.util.Recycler;
import io.netty.util.Recycler.Handle;
import io.netty.util.ReferenceCountUtil;
import io.netty.util.internal.PlatformDependent;
import io.netty.util.internal.SystemPropertyUtil;
import io.netty.util.internal.logging.InternalLogger;
import io.netty.util.internal.logging.InternalLoggerFactory;
@ -42,7 +43,14 @@ public class ChannelOutboundBuffer {
private static final InternalLogger logger = InternalLoggerFactory.getInstance(ChannelOutboundBuffer.class);
protected static final int INITIAL_CAPACITY = 32;
protected static final int INITIAL_CAPACITY =
SystemPropertyUtil.getInt("io.netty.outboundBufferInitialCapacity", 4);
static {
if (logger.isDebugEnabled()) {
logger.debug("-Dio.netty.outboundBufferInitialCapacity: {}", INITIAL_CAPACITY);
}
}
private static final Recycler<ChannelOutboundBuffer> RECYCLER = new Recycler<ChannelOutboundBuffer>() {
@Override

View File

@ -36,7 +36,7 @@ public class NioSocketChannelOutboundBufferTest {
NioSocketChannelOutboundBuffer buffer = NioSocketChannelOutboundBuffer.newInstance(channel);
assertEquals(0, buffer.nioBufferCount());
ByteBuffer[] buffers = buffer.nioBuffers();
assertEquals(32, buffers.length);
assertNotNull(buffers);
for (ByteBuffer b: buffers) {
assertNull(b);
}
@ -50,7 +50,7 @@ public class NioSocketChannelOutboundBufferTest {
NioSocketChannelOutboundBuffer buffer = NioSocketChannelOutboundBuffer.newInstance(channel);
assertEquals(0, buffer.nioBufferCount());
ByteBuffer[] buffers = buffer.nioBuffers();
assertEquals(32, buffers.length);
assertNotNull(buffers);
for (ByteBuffer b: buffers) {
assertNull(b);
}
@ -66,7 +66,7 @@ public class NioSocketChannelOutboundBufferTest {
}
buffer.addFlush();
buffers = buffer.nioBuffers();
assertEquals(32, buffers.length);
assertNotNull(buffers);
assertEquals("Should still be 0 as not flushed yet", 1, buffer.nioBufferCount());
for (int i = 0; i < buffers.length; i++) {
if (i == 0) {