Change the type of HTTP string properties to AsciiString

Related: #3132

Motivation:

Changing the type of the string properties of HttpVersion and
HttpResponseStatus to AsciiString will give us the performance advantage
when encoding it into the wire.

Modifications:

- Change the type of the following properties to AsciiString:
  - HttpVersion.protocolName()
  - HttpVersion.text()
  - HttpResponseStatus.reasonPhrase()
- Inline their respective encode() methods because they are used only in
  the encoders.
- Fix the test failures incurred by the changes above

Result:

Getting close to the machine
This commit is contained in:
Trustin Lee 2014-12-06 18:42:58 +09:00
parent 377ef31bb1
commit 97bf8a6d61
7 changed files with 55 additions and 79 deletions

View File

@ -39,7 +39,6 @@ public class HttpRequestEncoder extends HttpObjectEncoder<HttpRequest> {
protected void encodeInitialLine(ByteBuf buf, HttpRequest request) throws Exception {
AsciiString method = request.method().name();
buf.writeBytes(method.array(), method.arrayOffset(), method.length());
buf.writeByte(SP);
// Add / as absolute path if no is present.
@ -73,9 +72,10 @@ public class HttpRequestEncoder extends HttpObjectEncoder<HttpRequest> {
}
buf.writeBytes(uri.getBytes(CharsetUtil.UTF_8));
buf.writeByte(SP);
request.protocolVersion().encode(buf);
AsciiString version = request.protocolVersion().text();
buf.writeBytes(version.array(), version.arrayOffset(), version.length());
buf.writeBytes(CRLF);
}
}

View File

@ -16,6 +16,7 @@
package io.netty.handler.codec.http;
import io.netty.buffer.ByteBuf;
import io.netty.handler.codec.AsciiString;
import static io.netty.handler.codec.http.HttpConstants.*;
@ -33,9 +34,16 @@ public class HttpResponseEncoder extends HttpObjectEncoder<HttpResponse> {
@Override
protected void encodeInitialLine(ByteBuf buf, HttpResponse response) throws Exception {
response.protocolVersion().encode(buf);
AsciiString version = response.protocolVersion().text();
buf.writeBytes(version.array(), version.arrayOffset(), version.length());
buf.writeByte(SP);
response.status().encode(buf);
AsciiString code = response.status().codeAsText();
buf.writeBytes(code.array(), code.arrayOffset(), code.length());
buf.writeByte(SP);
AsciiString reasonPhrase = response.status().reasonPhrase();
buf.writeBytes(reasonPhrase.array(), reasonPhrase.arrayOffset(), reasonPhrase.length());
buf.writeBytes(CRLF);
}
}

View File

@ -15,11 +15,7 @@
*/
package io.netty.handler.codec.http;
import io.netty.buffer.ByteBuf;
import io.netty.handler.codec.AsciiString;
import io.netty.util.CharsetUtil;
import static io.netty.handler.codec.http.HttpConstants.*;
/**
* The response code and its description of HTTP or its derived protocols, such as
@ -472,8 +468,7 @@ public class HttpResponseStatus implements Comparable<HttpResponseStatus> {
private final AsciiString codeAsText;
private HttpStatusClass codeClass;
private final String reasonPhrase;
private final byte[] bytes;
private final AsciiString reasonPhrase;
/**
* Creates a new instance with the specified {@code code} and the auto-generated default reason phrase.
@ -512,12 +507,7 @@ public class HttpResponseStatus implements Comparable<HttpResponseStatus> {
this.code = code;
codeAsText = new AsciiString(Integer.toString(code));
this.reasonPhrase = reasonPhrase;
if (bytes) {
this.bytes = (code + " " + reasonPhrase).getBytes(CharsetUtil.US_ASCII);
} else {
this.bytes = null;
}
this.reasonPhrase = new AsciiString(reasonPhrase);
}
/**
@ -537,7 +527,7 @@ public class HttpResponseStatus implements Comparable<HttpResponseStatus> {
/**
* Returns the reason phrase of this {@link HttpResponseStatus}.
*/
public String reasonPhrase() {
public AsciiString reasonPhrase() {
return reasonPhrase;
}
@ -545,11 +535,11 @@ public class HttpResponseStatus implements Comparable<HttpResponseStatus> {
* Returns the class of this {@link HttpResponseStatus}
*/
public HttpStatusClass codeClass() {
HttpStatusClass type = this.codeClass;
if (type == null) {
this.codeClass = type = HttpStatusClass.valueOf(code);
HttpStatusClass codeClass = this.codeClass;
if (codeClass == null) {
this.codeClass = codeClass = HttpStatusClass.valueOf(code);
}
return type;
return codeClass;
}
@Override
@ -587,14 +577,4 @@ public class HttpResponseStatus implements Comparable<HttpResponseStatus> {
.append(reasonPhrase)
.toString();
}
void encode(ByteBuf buf) {
if (bytes == null) {
HttpHeaderUtil.encodeAscii0(String.valueOf(code()), buf);
buf.writeByte(SP);
HttpHeaderUtil.encodeAscii0(String.valueOf(reasonPhrase()), buf);
} else {
buf.writeBytes(bytes);
}
}
}

View File

@ -15,8 +15,7 @@
*/
package io.netty.handler.codec.http;
import io.netty.buffer.ByteBuf;
import io.netty.util.CharsetUtil;
import io.netty.handler.codec.AsciiString;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@ -37,12 +36,12 @@ public class HttpVersion implements Comparable<HttpVersion> {
/**
* HTTP/1.0
*/
public static final HttpVersion HTTP_1_0 = new HttpVersion("HTTP", 1, 0, false, true);
public static final HttpVersion HTTP_1_0 = new HttpVersion("HTTP", 1, 0, false);
/**
* HTTP/1.1
*/
public static final HttpVersion HTTP_1_1 = new HttpVersion("HTTP", 1, 1, true, true);
public static final HttpVersion HTTP_1_1 = new HttpVersion("HTTP", 1, 1, true);
/**
* Returns an existing or new {@link HttpVersion} instance which matches to
@ -88,12 +87,12 @@ public class HttpVersion implements Comparable<HttpVersion> {
return null;
}
private final String protocolName;
private final AsciiString protocolName;
private final int majorVersion;
private final int minorVersion;
private final String text;
private final AsciiString text;
private final String textAsString;
private final boolean keepAliveDefault;
private final byte[] bytes;
/**
* Creates a new HTTP version with the specified version string. You will
@ -121,12 +120,12 @@ public class HttpVersion implements Comparable<HttpVersion> {
throw new IllegalArgumentException("invalid version format: " + text);
}
protocolName = m.group(1);
protocolName = new AsciiString(m.group(1));
majorVersion = Integer.parseInt(m.group(2));
minorVersion = Integer.parseInt(m.group(3));
this.text = protocolName + '/' + majorVersion + '.' + minorVersion;
textAsString = protocolName + "/" + majorVersion + '.' + minorVersion;
this.text = new AsciiString(textAsString);
this.keepAliveDefault = keepAliveDefault;
bytes = null;
}
/**
@ -140,15 +139,7 @@ public class HttpVersion implements Comparable<HttpVersion> {
* {@code true} if and only if the connection is kept alive unless
* the {@code "Connection"} header is set to {@code "close"} explicitly.
*/
public HttpVersion(
String protocolName, int majorVersion, int minorVersion,
boolean keepAliveDefault) {
this(protocolName, majorVersion, minorVersion, keepAliveDefault, false);
}
private HttpVersion(
String protocolName, int majorVersion, int minorVersion,
boolean keepAliveDefault, boolean bytes) {
public HttpVersion(String protocolName, int majorVersion, int minorVersion, boolean keepAliveDefault) {
if (protocolName == null) {
throw new NullPointerException("protocolName");
}
@ -172,23 +163,18 @@ public class HttpVersion implements Comparable<HttpVersion> {
throw new IllegalArgumentException("negative minorVersion");
}
this.protocolName = protocolName;
this.protocolName = new AsciiString(protocolName);
this.majorVersion = majorVersion;
this.minorVersion = minorVersion;
text = protocolName + '/' + majorVersion + '.' + minorVersion;
textAsString = protocolName + '/' + majorVersion + '.' + minorVersion;
text = new AsciiString(textAsString);
this.keepAliveDefault = keepAliveDefault;
if (bytes) {
this.bytes = text.getBytes(CharsetUtil.US_ASCII);
} else {
this.bytes = null;
}
}
/**
* Returns the name of the protocol such as {@code "HTTP"} in {@code "HTTP/1.0"}.
*/
public String protocolName() {
public AsciiString protocolName() {
return protocolName;
}
@ -209,7 +195,7 @@ public class HttpVersion implements Comparable<HttpVersion> {
/**
* Returns the full protocol version text such as {@code "HTTP/1.0"}.
*/
public String text() {
public AsciiString text() {
return text;
}
@ -226,7 +212,7 @@ public class HttpVersion implements Comparable<HttpVersion> {
*/
@Override
public String toString() {
return text();
return textAsString;
}
@Override
@ -261,12 +247,4 @@ public class HttpVersion implements Comparable<HttpVersion> {
return minorVersion() - o.minorVersion();
}
void encode(ByteBuf buf) {
if (bytes == null) {
HttpHeaderUtil.encodeAscii0(text, buf);
} else {
buf.writeBytes(bytes);
}
}
}

View File

@ -16,6 +16,7 @@
package io.netty.handler.codec.rtsp;
import io.netty.buffer.ByteBuf;
import io.netty.handler.codec.AsciiString;
import io.netty.handler.codec.http.FullHttpRequest;
import io.netty.handler.codec.http.HttpRequest;
import io.netty.util.CharsetUtil;
@ -37,11 +38,15 @@ public class RtspRequestEncoder extends RtspObjectEncoder<HttpRequest> {
@Override
protected void encodeInitialLine(ByteBuf buf, HttpRequest request) throws Exception {
buf.writeBytes(request.method().toString().getBytes(CharsetUtil.US_ASCII));
AsciiString method = request.method().name();
buf.writeBytes(method.array(), method.arrayOffset(), method.length());
buf.writeByte(SP);
buf.writeBytes(request.uri().getBytes(CharsetUtil.UTF_8));
buf.writeByte(SP);
buf.writeBytes(request.protocolVersion().toString().getBytes(CharsetUtil.US_ASCII));
AsciiString version = request.protocolVersion().text();
buf.writeBytes(version.array(), version.arrayOffset(), version.length());
buf.writeBytes(CRLF);
}
}

View File

@ -16,9 +16,9 @@
package io.netty.handler.codec.rtsp;
import io.netty.buffer.ByteBuf;
import io.netty.handler.codec.AsciiString;
import io.netty.handler.codec.http.FullHttpResponse;
import io.netty.handler.codec.http.HttpResponse;
import io.netty.util.CharsetUtil;
import static io.netty.handler.codec.http.HttpConstants.*;
@ -36,11 +36,16 @@ public class RtspResponseEncoder extends RtspObjectEncoder<HttpResponse> {
@Override
protected void encodeInitialLine(ByteBuf buf, HttpResponse response) throws Exception {
buf.writeBytes(response.protocolVersion().toString().getBytes(CharsetUtil.US_ASCII));
AsciiString version = response.protocolVersion().text();
buf.writeBytes(version.array(), version.arrayOffset(), version.length());
buf.writeByte(SP);
buf.writeBytes(String.valueOf(response.status().code()).getBytes(CharsetUtil.US_ASCII));
AsciiString code = response.status().codeAsText();
buf.writeBytes(code.array(), code.arrayOffset(), code.length());
buf.writeByte(SP);
buf.writeBytes(response.status().reasonPhrase().getBytes(CharsetUtil.US_ASCII));
AsciiString reasonPhrase = response.status().reasonPhrase();
buf.writeBytes(reasonPhrase.array(), reasonPhrase.arrayOffset(), reasonPhrase.length());
buf.writeBytes(CRLF);
}
}

View File

@ -52,7 +52,7 @@ public class HttpInvalidMessageTest {
DecoderResult dr = req.decoderResult();
assertFalse(dr.isSuccess());
assertTrue(dr.isFailure());
assertEquals("Good Value", req.headers().get("Good_Name"));
assertTrue("Good Value".contentEquals(req.headers().get("Good_Name")));
assertEquals("/maybe-something", req.uri());
ensureInboundTrafficDiscarded(ch);
}
@ -79,8 +79,8 @@ public class HttpInvalidMessageTest {
DecoderResult dr = res.decoderResult();
assertFalse(dr.isSuccess());
assertTrue(dr.isFailure());
assertEquals("Maybe OK", res.status().reasonPhrase());
assertEquals("Good Value", res.headers().get("Good_Name"));
assertTrue("Maybe OK".contentEquals(res.status().reasonPhrase()));
assertTrue("Good Value".contentEquals(res.headers().get("Good_Name")));
ensureInboundTrafficDiscarded(ch);
}