Share same ThreadLocal for all decoder/encoders to minimize memory usage

This commit is contained in:
Norman Maurer 2013-04-03 18:19:35 +02:00
parent 94ef7dc1b9
commit 1675e61f5b
5 changed files with 26 additions and 43 deletions

View File

@ -45,14 +45,6 @@ public abstract class ByteToMessageDecoder
private volatile boolean singleDecode;
private boolean decodeWasNull;
private static final ThreadLocal<OutputMessageBuf> decoderOutput =
new ThreadLocal<OutputMessageBuf>() {
@Override
protected OutputMessageBuf initialValue() {
return new OutputMessageBuf();
}
};
/**
* If set then only one message is decoded on each {@link #inboundBufferUpdated(ChannelHandlerContext)} call.
* This may be useful if you need to do some protocol upgrade and want to make sure nothing is mixed up.
@ -91,7 +83,7 @@ public abstract class ByteToMessageDecoder
@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
OutputMessageBuf out = decoderOutput();
OutputMessageBuf out = OutputMessageBuf.get();
try {
ByteBuf in = ctx.inboundByteBuffer();
if (in.isReadable()) {
@ -131,7 +123,7 @@ public abstract class ByteToMessageDecoder
protected void callDecode(ChannelHandlerContext ctx, ByteBuf in) {
boolean wasNull = false;
boolean decoded = false;
OutputMessageBuf out = decoderOutput();
OutputMessageBuf out = OutputMessageBuf.get();
assert out.isEmpty();
@ -217,9 +209,4 @@ public abstract class ByteToMessageDecoder
protected void decodeLast(ChannelHandlerContext ctx, ByteBuf in, MessageBuf<Object> out) throws Exception {
decode(ctx, in, out);
}
final OutputMessageBuf decoderOutput() {
return decoderOutput.get();
}
}

View File

@ -42,14 +42,6 @@ import io.netty.channel.ChannelInboundMessageHandlerAdapter;
*/
public abstract class MessageToMessageDecoder<I> extends ChannelInboundMessageHandlerAdapter<I> {
private static final ThreadLocal<OutputMessageBuf> decoderOutput =
new ThreadLocal<OutputMessageBuf>() {
@Override
protected OutputMessageBuf initialValue() {
return new OutputMessageBuf();
}
};
protected MessageToMessageDecoder() { }
protected MessageToMessageDecoder(Class<? extends I> inboundMessageType) {
@ -58,7 +50,7 @@ public abstract class MessageToMessageDecoder<I> extends ChannelInboundMessageHa
@Override
public final void messageReceived(ChannelHandlerContext ctx, I msg) throws Exception {
OutputMessageBuf out = decoderOutput.get();
OutputMessageBuf out = OutputMessageBuf.get();
try {
decode(ctx, msg, out);
} finally {

View File

@ -39,13 +39,6 @@ import io.netty.channel.ChannelOutboundMessageHandlerAdapter;
*
*/
public abstract class MessageToMessageEncoder<I> extends ChannelOutboundMessageHandlerAdapter<I> {
private static final ThreadLocal<OutputMessageBuf> encoderOutput =
new ThreadLocal<OutputMessageBuf>() {
@Override
protected OutputMessageBuf initialValue() {
return new OutputMessageBuf();
}
};
protected MessageToMessageEncoder() { }
@ -55,9 +48,7 @@ public abstract class MessageToMessageEncoder<I> extends ChannelOutboundMessageH
@Override
public final void flush(ChannelHandlerContext ctx, I msg) throws Exception {
OutputMessageBuf out = encoderOutput.get();
assert out.isEmpty();
OutputMessageBuf out = OutputMessageBuf.get();
try {
encode(ctx, msg, out);

View File

@ -20,15 +20,28 @@ import io.netty.buffer.DefaultMessageBuf;
final class OutputMessageBuf extends DefaultMessageBuf<Object> {
private int byteBufs;
public OutputMessageBuf() {
private static final ThreadLocal<OutputMessageBuf> output =
new ThreadLocal<OutputMessageBuf>() {
@Override
protected OutputMessageBuf initialValue() {
return new OutputMessageBuf();
}
@Override
public OutputMessageBuf get() {
OutputMessageBuf buf = super.get();
// Just to be sure
buf.clear();
return buf;
}
};
static OutputMessageBuf get() {
return output.get();
}
public OutputMessageBuf(int initialCapacity) {
super(initialCapacity);
}
public OutputMessageBuf(int initialCapacity, int maxCapacity) {
super(initialCapacity, maxCapacity);
private OutputMessageBuf() {
}
@Override

View File

@ -364,7 +364,7 @@ public abstract class ReplayingDecoder<S> extends ByteToMessageDecoder {
@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
OutputMessageBuf out = decoderOutput();
OutputMessageBuf out = OutputMessageBuf.get();
try {
replayable.terminate();
@ -412,7 +412,7 @@ public abstract class ReplayingDecoder<S> extends ByteToMessageDecoder {
protected void callDecode(ChannelHandlerContext ctx, ByteBuf buf) {
boolean wasNull = false;
ByteBuf in = cumulation;
OutputMessageBuf out = decoderOutput();
OutputMessageBuf out = OutputMessageBuf.get();
boolean decoded = false;
assert out.isEmpty();