From 08c87c6256dbe007180bec4195222638cc47933a Mon Sep 17 00:00:00 2001 From: Trustin Lee Date: Tue, 22 Jul 2014 13:28:02 -0700 Subject: [PATCH] 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. --- .../java/io/netty/channel/ChannelOutboundBuffer.java | 12 ++++++++---- .../io/netty/channel/ChannelOutboundBufferTest.java | 6 +++--- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/transport/src/main/java/io/netty/channel/ChannelOutboundBuffer.java b/transport/src/main/java/io/netty/channel/ChannelOutboundBuffer.java index bdb6f10a73..367ebd008e 100644 --- a/transport/src/main/java/io/netty/channel/ChannelOutboundBuffer.java +++ b/transport/src/main/java/io/netty/channel/ChannelOutboundBuffer.java @@ -48,13 +48,17 @@ public final class ChannelOutboundBuffer { private static final InternalLogger logger = InternalLoggerFactory.getInstance(ChannelOutboundBuffer.class); - private static final int INITIAL_CAPACITY = 32; + private static final int INITIAL_CAPACITY = + SystemPropertyUtil.getInt("io.netty.outboundBufferInitialCapacity", 4); - private static final int threadLocalDirectBufferSize; + private static final int threadLocalDirectBufferSize = + SystemPropertyUtil.getInt("io.netty.threadLocalDirectBufferSize", 64 * 1024); static { - threadLocalDirectBufferSize = SystemPropertyUtil.getInt("io.netty.threadLocalDirectBufferSize", 64 * 1024); - logger.debug("-Dio.netty.threadLocalDirectBufferSize: {}", threadLocalDirectBufferSize); + if (logger.isDebugEnabled()) { + logger.debug("-Dio.netty.outboundBufferInitialCapacity: {}", INITIAL_CAPACITY); + logger.debug("-Dio.netty.threadLocalDirectBufferSize: {}", threadLocalDirectBufferSize); + } } private static final Recycler RECYCLER = new Recycler() { diff --git a/transport/src/test/java/io/netty/channel/ChannelOutboundBufferTest.java b/transport/src/test/java/io/netty/channel/ChannelOutboundBufferTest.java index f1cfdb3820..53ca073d1b 100644 --- a/transport/src/test/java/io/netty/channel/ChannelOutboundBufferTest.java +++ b/transport/src/test/java/io/netty/channel/ChannelOutboundBufferTest.java @@ -34,7 +34,7 @@ public class ChannelOutboundBufferTest { ChannelOutboundBuffer buffer = ChannelOutboundBuffer.newInstance(channel); assertEquals(0, buffer.nioBufferCount()); ByteBuffer[] buffers = buffer.nioBuffers(); - assertEquals(32, buffers.length); + assertNotNull(buffers); for (ByteBuffer b: buffers) { assertNull(b); } @@ -49,7 +49,7 @@ public class ChannelOutboundBufferTest { ChannelOutboundBuffer buffer = ChannelOutboundBuffer.newInstance(channel); assertEquals(0, buffer.nioBufferCount()); ByteBuffer[] buffers = buffer.nioBuffers(); - assertEquals(32, buffers.length); + assertNotNull(buffers); for (ByteBuffer b: buffers) { assertNull(b); } @@ -65,7 +65,7 @@ public class ChannelOutboundBufferTest { } 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) {