Remove the use of ThreadLocal for performance reasons

This commit is contained in:
Norman Maurer 2013-11-29 15:57:31 +01:00
parent 8b495bb6e1
commit 4a680a3b49

View File

@ -104,13 +104,6 @@ public abstract class HttpObjectDecoder extends ByteToMessageDecoder {
static final int DEFAULT_MAX_HEADER_SIZE = 8192; static final int DEFAULT_MAX_HEADER_SIZE = 8192;
static final int DEFAULT_MAX_CHUNK_SIZE = 8192; static final int DEFAULT_MAX_CHUNK_SIZE = 8192;
private static final ThreadLocal<StringBuilder> BUILDERS = new ThreadLocal<StringBuilder>() {
@Override
protected StringBuilder initialValue() {
return new StringBuilder(512);
}
};
private final int maxInitialLineLength; private final int maxInitialLineLength;
private final int maxHeaderSize; private final int maxHeaderSize;
private final int maxChunkSize; private final int maxChunkSize;
@ -123,7 +116,7 @@ public abstract class HttpObjectDecoder extends ByteToMessageDecoder {
private int contentRead; private int contentRead;
private long contentLength = Long.MIN_VALUE; private long contentLength = Long.MIN_VALUE;
private State state = State.SKIP_CONTROL_CHARS; private State state = State.SKIP_CONTROL_CHARS;
private StringBuilder sb; private final StringBuilder sb = new StringBuilder(128);
/** /**
* The internal state of {@link HttpObjectDecoder}. * The internal state of {@link HttpObjectDecoder}.
@ -202,7 +195,8 @@ public abstract class HttpObjectDecoder extends ByteToMessageDecoder {
// FALL THROUGH // FALL THROUGH
} }
case READ_INITIAL: try { case READ_INITIAL: try {
StringBuilder sb = builder(); StringBuilder sb = this.sb;
sb.setLength(0);
HttpMessage msg = splitInitialLine(sb, buffer, maxInitialLineLength); HttpMessage msg = splitInitialLine(sb, buffer, maxInitialLineLength);
if (msg == null) { if (msg == null) {
@ -218,7 +212,7 @@ public abstract class HttpObjectDecoder extends ByteToMessageDecoder {
return; return;
} }
case READ_HEADER: try { case READ_HEADER: try {
State nextState = readHeaders(buffer, builder()); State nextState = readHeaders(buffer);
if (nextState == state) { if (nextState == state) {
// was not able to consume whole header // was not able to consume whole header
return; return;
@ -439,7 +433,7 @@ public abstract class HttpObjectDecoder extends ByteToMessageDecoder {
return; return;
} }
case READ_CHUNK_FOOTER: try { case READ_CHUNK_FOOTER: try {
LastHttpContent trailer = readTrailingHeaders(buffer, builder()); LastHttpContent trailer = readTrailingHeaders(buffer);
if (trailer == null) { if (trailer == null) {
// not enough data // not enough data
return; return;
@ -595,9 +589,9 @@ public abstract class HttpObjectDecoder extends ByteToMessageDecoder {
reset(); reset();
} }
private State readHeaders(ByteBuf buffer, StringBuilder sb) { private State readHeaders(ByteBuf buffer) {
final HttpMessage message = this.message; final HttpMessage message = this.message;
if (!parseHeaders(message.headers(), buffer, sb)) { if (!parseHeaders(message.headers(), buffer)) {
return state; return state;
} }
// this means we consumed the header completly // this means we consumed the header completly
@ -625,8 +619,10 @@ public abstract class HttpObjectDecoder extends ByteToMessageDecoder {
HEADERS_END HEADERS_END
} }
private boolean parseHeaders(HttpHeaders headers, ByteBuf buffer, StringBuilder sb) { private boolean parseHeaders(HttpHeaders headers, ByteBuf buffer) {
// mark the index before try to start parsing and reset the StringBuilder // mark the index before try to start parsing and reset the StringBuilder
StringBuilder sb = this.sb;
sb.setLength(0);
buffer.markReaderIndex(); buffer.markReaderIndex();
String name = null; String name = null;
@ -764,8 +760,8 @@ public abstract class HttpObjectDecoder extends ByteToMessageDecoder {
return true; return true;
} }
} }
private LastHttpContent readTrailingHeaders(ByteBuf buffer, StringBuilder sb) { private LastHttpContent readTrailingHeaders(ByteBuf buffer) {
StringBuilder line = readHeader(buffer, sb); StringBuilder line = readHeader(buffer);
if (line == null) { if (line == null) {
// not enough data // not enough data
return null; return null;
@ -801,7 +797,7 @@ public abstract class HttpObjectDecoder extends ByteToMessageDecoder {
lastHeader = name; lastHeader = name;
} }
line = readHeader(buffer, sb); line = readHeader(buffer);
if (line == null) { if (line == null) {
// not enough data // not enough data
buffer.resetReaderIndex(); buffer.resetReaderIndex();
@ -815,7 +811,8 @@ public abstract class HttpObjectDecoder extends ByteToMessageDecoder {
return LastHttpContent.EMPTY_LAST_CONTENT; return LastHttpContent.EMPTY_LAST_CONTENT;
} }
private StringBuilder readHeader(ByteBuf buffer, StringBuilder sb) { private StringBuilder readHeader(ByteBuf buffer) {
StringBuilder sb = this.sb;
sb.setLength(0); sb.setLength(0);
int headerSize = this.headerSize; int headerSize = this.headerSize;
buffer.markReaderIndex(); buffer.markReaderIndex();
@ -875,7 +872,8 @@ public abstract class HttpObjectDecoder extends ByteToMessageDecoder {
} }
private StringBuilder readLine(ByteBuf buffer, int maxLineLength) { private StringBuilder readLine(ByteBuf buffer, int maxLineLength) {
StringBuilder sb = builder(); StringBuilder sb = this.sb;
sb.setLength(0);
int lineLength = 0; int lineLength = 0;
buffer.markReaderIndex(); buffer.markReaderIndex();
@ -1068,14 +1066,4 @@ public abstract class HttpObjectDecoder extends ByteToMessageDecoder {
} }
return result; return result;
} }
private StringBuilder builder() {
if (sb == null) {
// Obtain the StringBuilder from the ThreadLocal and store it for later usage.
// This minimize the ThreadLocal.get() operations a lot and so eliminate some overhead
sb = BUILDERS.get();
}
sb.setLength(0);
return sb;
}
} }