Fix performance regression which was caused by calling the fireInboundBufferUpdated() a way to often

* Also use a ThreadLocal for the decoder buffer to safe space as it is cheap
This commit is contained in:
Norman Maurer 2013-04-03 17:07:52 +02:00
parent c3559ddbda
commit 9828267165
2 changed files with 111 additions and 112 deletions

View File

@ -45,18 +45,23 @@ public abstract class ByteToMessageDecoder
private volatile boolean singleDecode; private volatile boolean singleDecode;
private boolean decodeWasNull; private boolean decodeWasNull;
private MessageBuf<Object> decoderOutput;
private static final ThreadLocal<MessageBuf<Object>> decoderOutput =
new ThreadLocal<MessageBuf<Object>>() {
@Override
protected MessageBuf<Object> initialValue() {
return Unpooled.messageBuffer();
}
};
@Override @Override
public ByteBuf newInboundBuffer(ChannelHandlerContext ctx) throws Exception { public ByteBuf newInboundBuffer(ChannelHandlerContext ctx) throws Exception {
decoderOutput = Unpooled.messageBuffer();
return super.newInboundBuffer(ctx); return super.newInboundBuffer(ctx);
} }
@Override @Override
public void freeInboundBuffer(ChannelHandlerContext ctx) throws Exception { public void freeInboundBuffer(ChannelHandlerContext ctx) throws Exception {
super.freeInboundBuffer(ctx); super.freeInboundBuffer(ctx);
decoderOutput.release();
} }
/** /**
@ -130,12 +135,12 @@ public abstract class ByteToMessageDecoder
protected void callDecode(ChannelHandlerContext ctx, ByteBuf in) { protected void callDecode(ChannelHandlerContext ctx, ByteBuf in) {
boolean wasNull = false; boolean wasNull = false;
boolean decoded = false; boolean decoded = false;
MessageBuf<Object> out = decoderOutput(); MessageBuf<Object> out = decoderOutput();
assert out.isEmpty(); assert out.isEmpty();
try {
while (in.isReadable()) { while (in.isReadable()) {
try { try {
int outSize = out.size(); int outSize = out.size();
@ -165,6 +170,8 @@ public abstract class ByteToMessageDecoder
} else { } else {
throw new DecoderException(t); throw new DecoderException(t);
} }
}
}
} finally { } finally {
for (;;) { for (;;) {
Object msg = out.poll(); Object msg = out.poll();
@ -175,13 +182,6 @@ public abstract class ByteToMessageDecoder
ChannelHandlerUtil.addToNextInboundBuffer(ctx, msg); ChannelHandlerUtil.addToNextInboundBuffer(ctx, msg);
} }
if (decoded) {
decoded = false;
ctx.fireInboundBufferUpdated();
}
}
}
if (decoded) { if (decoded) {
decodeWasNull = false; decodeWasNull = false;
ctx.fireInboundBufferUpdated(); ctx.fireInboundBufferUpdated();
@ -191,6 +191,7 @@ public abstract class ByteToMessageDecoder
} }
} }
} }
}
/** /**
* Decode the from one {@link ByteBuf} to an other. This method will be called till either the input * Decode the from one {@link ByteBuf} to an other. This method will be called till either the input
@ -217,7 +218,7 @@ public abstract class ByteToMessageDecoder
} }
final MessageBuf<Object> decoderOutput() { final MessageBuf<Object> decoderOutput() {
return decoderOutput; return decoderOutput.get();
} }
} }

View File

@ -406,10 +406,13 @@ public abstract class ReplayingDecoder<S> extends ByteToMessageDecoder {
@Override @Override
protected void callDecode(ChannelHandlerContext ctx, ByteBuf buf) { protected void callDecode(ChannelHandlerContext ctx, ByteBuf buf) {
boolean wasNull = false; boolean wasNull = false;
ByteBuf in = cumulation; ByteBuf in = cumulation;
MessageBuf<Object> out = decoderOutput(); MessageBuf<Object> out = decoderOutput();
boolean decoded = false; boolean decoded = false;
assert out.isEmpty();
try {
while (in.isReadable()) { while (in.isReadable()) {
try { try {
int oldReaderIndex = checkpoint = in.readerIndex(); int oldReaderIndex = checkpoint = in.readerIndex();
@ -454,8 +457,9 @@ public abstract class ReplayingDecoder<S> extends ByteToMessageDecoder {
} else { } else {
throw new DecoderException(t); throw new DecoderException(t);
} }
}
}
} finally { } finally {
for (;;) { for (;;) {
Object msg = out.poll(); Object msg = out.poll();
if (msg == null) { if (msg == null) {
@ -464,13 +468,6 @@ public abstract class ReplayingDecoder<S> extends ByteToMessageDecoder {
decoded = true; decoded = true;
ChannelHandlerUtil.addToNextInboundBuffer(ctx, msg); ChannelHandlerUtil.addToNextInboundBuffer(ctx, msg);
} }
if (decoded) {
decoded = false;
ctx.fireInboundBufferUpdated();
}
}
}
if (decoded) { if (decoded) {
decodeWasNull = false; decodeWasNull = false;
ctx.fireInboundBufferUpdated(); ctx.fireInboundBufferUpdated();
@ -480,6 +477,7 @@ public abstract class ReplayingDecoder<S> extends ByteToMessageDecoder {
} }
} }
} }
}
@Override @Override
public void channelReadSuspended(ChannelHandlerContext ctx) throws Exception { public void channelReadSuspended(ChannelHandlerContext ctx) throws Exception {