[#2656] Minimize ByteBuf.writeBytes(...) calls by pack the separator into the HttpHeaderEntity.
Motivation: Currently we do 4 ByteBuf.writeBytes(...) calls per header line. This is can be improved. Modification: Introduce two new HttpHeaders methods to allow create HttpHeaderEntity which contains the separator. With this we can minimize it to 2 ByteBuf.writeBytes(...) calls per header line Result: Performance improvement.
This commit is contained in:
parent
c4d0a87e19
commit
8fe3d97d8d
@ -23,11 +23,25 @@ final class HttpHeaderEntity implements CharSequence {
|
|||||||
private final String name;
|
private final String name;
|
||||||
private final int hash;
|
private final int hash;
|
||||||
private final byte[] bytes;
|
private final byte[] bytes;
|
||||||
|
private final int separatorLen;
|
||||||
|
|
||||||
public HttpHeaderEntity(String name) {
|
public HttpHeaderEntity(String name) {
|
||||||
|
this(name, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public HttpHeaderEntity(String name, byte[] separator) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
hash = HttpHeaders.hash(name);
|
hash = HttpHeaders.hash(name);
|
||||||
bytes = name.getBytes(CharsetUtil.US_ASCII);
|
byte[] nameBytes = name.getBytes(CharsetUtil.US_ASCII);
|
||||||
|
if (separator == null) {
|
||||||
|
bytes = nameBytes;
|
||||||
|
separatorLen = 0;
|
||||||
|
} else {
|
||||||
|
separatorLen = separator.length;
|
||||||
|
bytes = new byte[nameBytes.length + separator.length];
|
||||||
|
System.arraycopy(nameBytes, 0, bytes, 0, nameBytes.length);
|
||||||
|
System.arraycopy(separator, 0, bytes, nameBytes.length, separator.length);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int hash() {
|
int hash() {
|
||||||
@ -36,11 +50,14 @@ final class HttpHeaderEntity implements CharSequence {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int length() {
|
public int length() {
|
||||||
return bytes.length;
|
return bytes.length - separatorLen;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public char charAt(int index) {
|
public char charAt(int index) {
|
||||||
|
if ((bytes.length - separatorLen) <= index) {
|
||||||
|
throw new IndexOutOfBoundsException();
|
||||||
|
}
|
||||||
return (char) bytes[index];
|
return (char) bytes[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -54,7 +71,8 @@ final class HttpHeaderEntity implements CharSequence {
|
|||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
void encode(ByteBuf buf) {
|
boolean encode(ByteBuf buf) {
|
||||||
buf.writeBytes(bytes);
|
buf.writeBytes(bytes);
|
||||||
|
return separatorLen > 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1363,17 +1363,20 @@ public abstract class HttpHeaders implements Iterable<Map.Entry<String, String>>
|
|||||||
|
|
||||||
@SuppressWarnings("deprecation")
|
@SuppressWarnings("deprecation")
|
||||||
static void encode(CharSequence key, CharSequence value, ByteBuf buf) {
|
static void encode(CharSequence key, CharSequence value, ByteBuf buf) {
|
||||||
encodeAscii(key, buf);
|
if (!encodeAscii(key, buf)) {
|
||||||
buf.writeBytes(HEADER_SEPERATOR);
|
buf.writeBytes(HEADER_SEPERATOR);
|
||||||
encodeAscii(value, buf);
|
}
|
||||||
buf.writeBytes(CRLF);
|
if (!encodeAscii(value, buf)) {
|
||||||
|
buf.writeBytes(CRLF);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void encodeAscii(CharSequence seq, ByteBuf buf) {
|
public static boolean encodeAscii(CharSequence seq, ByteBuf buf) {
|
||||||
if (seq instanceof HttpHeaderEntity) {
|
if (seq instanceof HttpHeaderEntity) {
|
||||||
((HttpHeaderEntity) seq).encode(buf);
|
return ((HttpHeaderEntity) seq).encode(buf);
|
||||||
} else {
|
} else {
|
||||||
encodeAscii0(seq, buf);
|
encodeAscii0(seq, buf);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1395,6 +1398,28 @@ public abstract class HttpHeaders implements Iterable<Map.Entry<String, String>>
|
|||||||
return new HttpHeaderEntity(name);
|
return new HttpHeaderEntity(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new {@link CharSequence} which is optimized for reuse as {@link HttpHeaders} name.
|
||||||
|
* So if you have a Header name that you want to reuse you should make use of this.
|
||||||
|
*/
|
||||||
|
public static CharSequence newNameEntity(String name) {
|
||||||
|
if (name == null) {
|
||||||
|
throw new NullPointerException("name");
|
||||||
|
}
|
||||||
|
return new HttpHeaderEntity(name, HEADER_SEPERATOR);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new {@link CharSequence} which is optimized for reuse as {@link HttpHeaders} value.
|
||||||
|
* So if you have a Header value that you want to reuse you should make use of this.
|
||||||
|
*/
|
||||||
|
public static CharSequence newValueEntity(String name) {
|
||||||
|
if (name == null) {
|
||||||
|
throw new NullPointerException("name");
|
||||||
|
}
|
||||||
|
return new HttpHeaderEntity(name, CRLF);
|
||||||
|
}
|
||||||
|
|
||||||
protected HttpHeaders() { }
|
protected HttpHeaders() { }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Loading…
Reference in New Issue
Block a user