From 35c7f66c4805427fa7c779d789a0cd225c55eebf Mon Sep 17 00:00:00 2001 From: Norman Maurer Date: Mon, 23 Jun 2014 07:01:05 +0200 Subject: [PATCH] MessageToByteEncoder always starts with ByteBuf that use initalCapacity == 0 Motivation: MessageToByteEncoder always starts with ByteBuf that use initalCapacity == 0 when preferDirect is used. This is really wasteful in terms of performance as every first write into the buffer will cause an expand of the buffer itself. Modifications: - Change ByteBufAllocator.ioBuffer() use the same default initialCapacity as heapBuffer() and directBuffer() - Add new allocateBuffer method to MessageToByteEncoder that allow the user to do some smarter allocation based on the message that will be encoded. Result: Less expanding of buffer and more flexibilty when allocate the buffer for encoding. --- .../buffer/AbstractByteBufAllocator.java | 4 ++-- .../io/netty/buffer/ByteBufAllocator.java | 2 +- .../handler/codec/MessageToByteEncoder.java | 19 ++++++++++++++----- 3 files changed, 17 insertions(+), 8 deletions(-) diff --git a/buffer/src/main/java/io/netty/buffer/AbstractByteBufAllocator.java b/buffer/src/main/java/io/netty/buffer/AbstractByteBufAllocator.java index e94d2e51d0..7eda9d97bb 100644 --- a/buffer/src/main/java/io/netty/buffer/AbstractByteBufAllocator.java +++ b/buffer/src/main/java/io/netty/buffer/AbstractByteBufAllocator.java @@ -96,9 +96,9 @@ public abstract class AbstractByteBufAllocator implements ByteBufAllocator { @Override public ByteBuf ioBuffer() { if (PlatformDependent.hasUnsafe()) { - return directBuffer(0); + return directBuffer(DEFAULT_INITIAL_CAPACITY); } - return heapBuffer(0); + return heapBuffer(DEFAULT_INITIAL_CAPACITY); } @Override diff --git a/buffer/src/main/java/io/netty/buffer/ByteBufAllocator.java b/buffer/src/main/java/io/netty/buffer/ByteBufAllocator.java index 9c33af88d8..c30d962046 100644 --- a/buffer/src/main/java/io/netty/buffer/ByteBufAllocator.java +++ b/buffer/src/main/java/io/netty/buffer/ByteBufAllocator.java @@ -43,7 +43,7 @@ public interface ByteBufAllocator { ByteBuf buffer(int initialCapacity, int maxCapacity); /** - * Allocate a {@link ByteBuf} whose initial capacity is 0, preferably a direct buffer which is suitable for I/O. + * Allocate a {@link ByteBuf}, preferably a direct buffer which is suitable for I/O. */ ByteBuf ioBuffer(); diff --git a/codec/src/main/java/io/netty/handler/codec/MessageToByteEncoder.java b/codec/src/main/java/io/netty/handler/codec/MessageToByteEncoder.java index 3cf0719215..1dbbb94998 100644 --- a/codec/src/main/java/io/netty/handler/codec/MessageToByteEncoder.java +++ b/codec/src/main/java/io/netty/handler/codec/MessageToByteEncoder.java @@ -102,11 +102,7 @@ public abstract class MessageToByteEncoder extends ChannelHandlerAdapter { if (acceptOutboundMessage(msg)) { @SuppressWarnings("unchecked") I cast = (I) msg; - if (preferDirect) { - buf = ctx.alloc().ioBuffer(); - } else { - buf = ctx.alloc().heapBuffer(); - } + buf = allocateBuffer(ctx, cast, preferDirect); try { encode(ctx, cast, buf); } finally { @@ -134,6 +130,19 @@ public abstract class MessageToByteEncoder extends ChannelHandlerAdapter { } } + /** + * Allocate a {@link ByteBuf} which will be used as argument of {@link #encode(ChannelHandlerContext, I, ByteBuf)}. + * Sub-classes may override this method to returna {@link ByteBuf} with a perfect matching {@code initialCapacity}. + */ + protected ByteBuf allocateBuffer(ChannelHandlerContext ctx, @SuppressWarnings("unused") I msg, + boolean preferDirect) throws Exception { + if (preferDirect) { + return ctx.alloc().ioBuffer(); + } else { + return ctx.alloc().heapBuffer(); + } + } + /** * Encode a message into a {@link ByteBuf}. This method will be called for each written message that can be handled * by this encoder.