Improve the performance of copying header sets when hashing and name validation are equivalent.
Motivation: Headers and groups of headers are frequently copied and the current mechanism is slower than it needs to be. Modifications: Skip name validation and hash computation when they are not necessary. Fix emergent bug in CombinedHttpHeaders identified with better testing Fix memory leak in DefaultHttp2Headers when clearing Added benchmarks Result: Faster header copying and some collateral bug fixes
This commit is contained in:
parent
187efca9aa
commit
6e108cb96a
@ -18,10 +18,12 @@ package io.netty.handler.codec.http;
|
|||||||
import io.netty.handler.codec.DefaultHeaders;
|
import io.netty.handler.codec.DefaultHeaders;
|
||||||
import io.netty.handler.codec.ValueConverter;
|
import io.netty.handler.codec.ValueConverter;
|
||||||
import io.netty.util.HashingStrategy;
|
import io.netty.util.HashingStrategy;
|
||||||
|
import io.netty.handler.codec.Headers;
|
||||||
import io.netty.util.internal.StringUtil;
|
import io.netty.util.internal.StringUtil;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
import static io.netty.util.AsciiString.CASE_INSENSITIVE_HASHER;
|
import static io.netty.util.AsciiString.CASE_INSENSITIVE_HASHER;
|
||||||
import static io.netty.util.internal.StringUtil.COMMA;
|
import static io.netty.util.internal.StringUtil.COMMA;
|
||||||
@ -75,6 +77,50 @@ public class CombinedHttpHeaders extends DefaultHttpHeaders {
|
|||||||
super(nameHashingStrategy, valueConverter, nameValidator);
|
super(nameHashingStrategy, valueConverter, nameValidator);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CombinedHttpHeadersImpl add(Headers<? extends CharSequence, ? extends CharSequence, ?> headers) {
|
||||||
|
// Override the fast-copy mechanism used by DefaultHeaders
|
||||||
|
if (headers == this) {
|
||||||
|
throw new IllegalArgumentException("can't add to itself.");
|
||||||
|
}
|
||||||
|
if (headers instanceof CombinedHttpHeadersImpl) {
|
||||||
|
if (isEmpty()) {
|
||||||
|
// Can use the fast underlying copy
|
||||||
|
addImpl(headers);
|
||||||
|
} else {
|
||||||
|
// Values are already escaped so don't escape again
|
||||||
|
for (Map.Entry<? extends CharSequence, ? extends CharSequence> header : headers) {
|
||||||
|
addEscapedValue(header.getKey(), header.getValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (Map.Entry<? extends CharSequence, ? extends CharSequence> header : headers) {
|
||||||
|
add(header.getKey(), header.getValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CombinedHttpHeadersImpl set(Headers<? extends CharSequence, ? extends CharSequence, ?> headers) {
|
||||||
|
if (headers == this) {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
clear();
|
||||||
|
return add(headers);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CombinedHttpHeadersImpl setAll(Headers<? extends CharSequence, ? extends CharSequence, ?> headers) {
|
||||||
|
if (headers == this) {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
for (CharSequence key : headers.names()) {
|
||||||
|
remove(key);
|
||||||
|
}
|
||||||
|
return add(headers);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CombinedHttpHeadersImpl add(CharSequence name, CharSequence value) {
|
public CombinedHttpHeadersImpl add(CharSequence name, CharSequence value) {
|
||||||
return addEscapedValue(name, StringUtil.escapeCsv(value));
|
return addEscapedValue(name, StringUtil.escapeCsv(value));
|
||||||
|
@ -15,12 +15,14 @@
|
|||||||
*/
|
*/
|
||||||
package io.netty.handler.codec.http;
|
package io.netty.handler.codec.http;
|
||||||
|
|
||||||
|
import io.netty.handler.codec.DefaultHeaders;
|
||||||
import io.netty.handler.codec.http.HttpHeadersTestUtils.HeaderValue;
|
import io.netty.handler.codec.http.HttpHeadersTestUtils.HeaderValue;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
|
||||||
import static io.netty.util.AsciiString.contentEquals;
|
import static io.netty.util.AsciiString.contentEquals;
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
public class CombinedHttpHeadersTest {
|
public class CombinedHttpHeadersTest {
|
||||||
@ -41,6 +43,60 @@ public class CombinedHttpHeadersTest {
|
|||||||
assertCsvValues(headers, HeaderValue.FIVE);
|
assertCsvValues(headers, HeaderValue.FIVE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void addCombinedHeadersWhenEmpty() {
|
||||||
|
final CombinedHttpHeaders headers = newCombinedHttpHeaders();
|
||||||
|
final CombinedHttpHeaders otherHeaders = newCombinedHttpHeaders();
|
||||||
|
otherHeaders.add(HEADER_NAME, "a");
|
||||||
|
otherHeaders.add(HEADER_NAME, "b");
|
||||||
|
headers.add(otherHeaders);
|
||||||
|
assertEquals("a,b", headers.get(HEADER_NAME).toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void addCombinedHeadersWhenNotEmpty() {
|
||||||
|
final CombinedHttpHeaders headers = newCombinedHttpHeaders();
|
||||||
|
headers.add(HEADER_NAME, "a");
|
||||||
|
final CombinedHttpHeaders otherHeaders = newCombinedHttpHeaders();
|
||||||
|
otherHeaders.add(HEADER_NAME, "b");
|
||||||
|
otherHeaders.add(HEADER_NAME, "c");
|
||||||
|
headers.add(otherHeaders);
|
||||||
|
assertEquals("a,b,c", headers.get(HEADER_NAME).toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void setCombinedHeadersWhenNotEmpty() {
|
||||||
|
final CombinedHttpHeaders headers = newCombinedHttpHeaders();
|
||||||
|
headers.add(HEADER_NAME, "a");
|
||||||
|
final CombinedHttpHeaders otherHeaders = newCombinedHttpHeaders();
|
||||||
|
otherHeaders.add(HEADER_NAME, "b");
|
||||||
|
otherHeaders.add(HEADER_NAME, "c");
|
||||||
|
headers.set(otherHeaders);
|
||||||
|
assertEquals("b,c", headers.get(HEADER_NAME).toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void addUncombinedHeaders() {
|
||||||
|
final CombinedHttpHeaders headers = newCombinedHttpHeaders();
|
||||||
|
headers.add(HEADER_NAME, "a");
|
||||||
|
final DefaultHttpHeaders otherHeaders = new DefaultHttpHeaders();
|
||||||
|
otherHeaders.add(HEADER_NAME, "b");
|
||||||
|
otherHeaders.add(HEADER_NAME, "c");
|
||||||
|
headers.add(otherHeaders);
|
||||||
|
assertEquals("a,b,c", headers.get(HEADER_NAME).toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void setUncombinedHeaders() {
|
||||||
|
final CombinedHttpHeaders headers = newCombinedHttpHeaders();
|
||||||
|
headers.add(HEADER_NAME, "a");
|
||||||
|
final DefaultHttpHeaders otherHeaders = new DefaultHttpHeaders();
|
||||||
|
otherHeaders.add(HEADER_NAME, "b");
|
||||||
|
otherHeaders.add(HEADER_NAME, "c");
|
||||||
|
headers.set(otherHeaders);
|
||||||
|
assertEquals("b,c", headers.get(HEADER_NAME).toString());
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void addCharSequencesCsvWithValueContainingComma() {
|
public void addCharSequencesCsvWithValueContainingComma() {
|
||||||
final CombinedHttpHeaders headers = newCombinedHttpHeaders();
|
final CombinedHttpHeaders headers = newCombinedHttpHeaders();
|
||||||
|
@ -316,7 +316,6 @@ public class DefaultHeaders<K, V, T extends Headers<K, V, T>> implements Headers
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public T addObject(K name, Iterable<?> values) {
|
public T addObject(K name, Iterable<?> values) {
|
||||||
checkNotNull(values, "values");
|
|
||||||
for (Object value : values) {
|
for (Object value : values) {
|
||||||
addObject(name, value);
|
addObject(name, value);
|
||||||
}
|
}
|
||||||
@ -325,7 +324,6 @@ public class DefaultHeaders<K, V, T extends Headers<K, V, T>> implements Headers
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public T addObject(K name, Object... values) {
|
public T addObject(K name, Object... values) {
|
||||||
checkNotNull(values, "values");
|
|
||||||
for (int i = 0; i < values.length; i++) {
|
for (int i = 0; i < values.length; i++) {
|
||||||
addObject(name, values[i]);
|
addObject(name, values[i]);
|
||||||
}
|
}
|
||||||
@ -379,25 +377,39 @@ public class DefaultHeaders<K, V, T extends Headers<K, V, T>> implements Headers
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public T add(Headers<? extends K, ? extends V, ?> headers) {
|
public T add(Headers<? extends K, ? extends V, ?> headers) {
|
||||||
checkNotNull(headers, "headers");
|
|
||||||
if (headers == this) {
|
if (headers == this) {
|
||||||
throw new IllegalArgumentException("can't add to itself.");
|
throw new IllegalArgumentException("can't add to itself.");
|
||||||
}
|
}
|
||||||
|
addImpl(headers);
|
||||||
|
return thisT();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void addImpl(Headers<? extends K, ? extends V, ?> headers) {
|
||||||
if (headers instanceof DefaultHeaders) {
|
if (headers instanceof DefaultHeaders) {
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
DefaultHeaders<K, V, T> defaultHeaders = (DefaultHeaders<K, V, T>) headers;
|
final DefaultHeaders<? extends K, ? extends V, T> defaultHeaders =
|
||||||
HeaderEntry<K, V> e = defaultHeaders.head.after;
|
(DefaultHeaders<? extends K, ? extends V, T>) headers;
|
||||||
|
HeaderEntry<? extends K, ? extends V> e = defaultHeaders.head.after;
|
||||||
|
if (defaultHeaders.hashingStrategy == hashingStrategy &&
|
||||||
|
defaultHeaders.nameValidator == nameValidator) {
|
||||||
|
// Fastest copy
|
||||||
|
while (e != defaultHeaders.head) {
|
||||||
|
add0(e.hash, index(e.hash), e.key, e.value);
|
||||||
|
e = e.after;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Fast copy
|
||||||
while (e != defaultHeaders.head) {
|
while (e != defaultHeaders.head) {
|
||||||
add(e.key, e.value);
|
add(e.key, e.value);
|
||||||
e = e.after;
|
e = e.after;
|
||||||
}
|
}
|
||||||
return thisT();
|
}
|
||||||
} else {
|
} else {
|
||||||
|
// Slow copy
|
||||||
for (Entry<? extends K, ? extends V> header : headers) {
|
for (Entry<? extends K, ? extends V> header : headers) {
|
||||||
add(header.getKey(), header.getValue());
|
add(header.getKey(), header.getValue());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return thisT();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -459,7 +471,6 @@ public class DefaultHeaders<K, V, T extends Headers<K, V, T>> implements Headers
|
|||||||
@Override
|
@Override
|
||||||
public T setObject(K name, Iterable<?> values) {
|
public T setObject(K name, Iterable<?> values) {
|
||||||
nameValidator.validateName(name);
|
nameValidator.validateName(name);
|
||||||
checkNotNull(values, "values");
|
|
||||||
|
|
||||||
int h = hashingStrategy.hashCode(name);
|
int h = hashingStrategy.hashCode(name);
|
||||||
int i = index(h);
|
int i = index(h);
|
||||||
@ -478,7 +489,6 @@ public class DefaultHeaders<K, V, T extends Headers<K, V, T>> implements Headers
|
|||||||
@Override
|
@Override
|
||||||
public T setObject(K name, Object... values) {
|
public T setObject(K name, Object... values) {
|
||||||
nameValidator.validateName(name);
|
nameValidator.validateName(name);
|
||||||
checkNotNull(values, "values");
|
|
||||||
|
|
||||||
int h = hashingStrategy.hashCode(name);
|
int h = hashingStrategy.hashCode(name);
|
||||||
int i = index(h);
|
int i = index(h);
|
||||||
@ -541,36 +551,20 @@ public class DefaultHeaders<K, V, T extends Headers<K, V, T>> implements Headers
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public T set(Headers<? extends K, ? extends V, ?> headers) {
|
public T set(Headers<? extends K, ? extends V, ?> headers) {
|
||||||
checkNotNull(headers, "headers");
|
if (headers != this) {
|
||||||
if (headers == this) {
|
|
||||||
return thisT();
|
|
||||||
}
|
|
||||||
clear();
|
clear();
|
||||||
if (headers instanceof DefaultHeaders) {
|
addImpl(headers);
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
DefaultHeaders<K, V, T> defaultHeaders = (DefaultHeaders<K, V, T>) headers;
|
|
||||||
HeaderEntry<K, V> e = defaultHeaders.head.after;
|
|
||||||
while (e != defaultHeaders.head) {
|
|
||||||
add(e.key, e.value);
|
|
||||||
e = e.after;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
add(headers);
|
|
||||||
}
|
}
|
||||||
return thisT();
|
return thisT();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public T setAll(Headers<? extends K, ? extends V, ?> headers) {
|
public T setAll(Headers<? extends K, ? extends V, ?> headers) {
|
||||||
checkNotNull(headers, "headers");
|
if (headers != this) {
|
||||||
if (headers == this) {
|
|
||||||
return thisT();
|
|
||||||
}
|
|
||||||
for (K key : headers.names()) {
|
for (K key : headers.names()) {
|
||||||
remove(key);
|
remove(key);
|
||||||
}
|
}
|
||||||
for (Entry<? extends K, ? extends V> entry : headers) {
|
addImpl(headers);
|
||||||
add(entry.getKey(), entry.getValue());
|
|
||||||
}
|
}
|
||||||
return thisT();
|
return thisT();
|
||||||
}
|
}
|
||||||
|
@ -152,6 +152,59 @@ public class DefaultHeadersTest {
|
|||||||
assertFalse(headers.contains(of("name"), of("value1")));
|
assertFalse(headers.contains(of("name"), of("value1")));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCopy() throws Exception {
|
||||||
|
TestDefaultHeaders headers = newInstance();
|
||||||
|
headers.addBoolean(of("boolean"), true);
|
||||||
|
headers.addLong(of("long"), Long.MAX_VALUE);
|
||||||
|
headers.addInt(of("int"), Integer.MIN_VALUE);
|
||||||
|
headers.addShort(of("short"), Short.MAX_VALUE);
|
||||||
|
headers.addChar(of("char"), Character.MAX_VALUE);
|
||||||
|
headers.addByte(of("byte"), Byte.MAX_VALUE);
|
||||||
|
headers.addDouble(of("double"), Double.MAX_VALUE);
|
||||||
|
headers.addFloat(of("float"), Float.MAX_VALUE);
|
||||||
|
long millis = System.currentTimeMillis();
|
||||||
|
headers.addTimeMillis(of("millis"), millis);
|
||||||
|
headers.addObject(of("object"), "Hello World");
|
||||||
|
headers.add(of("name"), of("value"));
|
||||||
|
|
||||||
|
headers = newInstance().add(headers);
|
||||||
|
|
||||||
|
assertTrue(headers.containsBoolean(of("boolean"), true));
|
||||||
|
assertFalse(headers.containsBoolean(of("boolean"), false));
|
||||||
|
|
||||||
|
assertTrue(headers.containsLong(of("long"), Long.MAX_VALUE));
|
||||||
|
assertFalse(headers.containsLong(of("long"), Long.MIN_VALUE));
|
||||||
|
|
||||||
|
assertTrue(headers.containsInt(of("int"), Integer.MIN_VALUE));
|
||||||
|
assertFalse(headers.containsInt(of("int"), Integer.MAX_VALUE));
|
||||||
|
|
||||||
|
assertTrue(headers.containsShort(of("short"), Short.MAX_VALUE));
|
||||||
|
assertFalse(headers.containsShort(of("short"), Short.MIN_VALUE));
|
||||||
|
|
||||||
|
assertTrue(headers.containsChar(of("char"), Character.MAX_VALUE));
|
||||||
|
assertFalse(headers.containsChar(of("char"), Character.MIN_VALUE));
|
||||||
|
|
||||||
|
assertTrue(headers.containsByte(of("byte"), Byte.MAX_VALUE));
|
||||||
|
assertFalse(headers.containsLong(of("byte"), Byte.MIN_VALUE));
|
||||||
|
|
||||||
|
assertTrue(headers.containsDouble(of("double"), Double.MAX_VALUE));
|
||||||
|
assertFalse(headers.containsDouble(of("double"), Double.MIN_VALUE));
|
||||||
|
|
||||||
|
assertTrue(headers.containsFloat(of("float"), Float.MAX_VALUE));
|
||||||
|
assertFalse(headers.containsFloat(of("float"), Float.MIN_VALUE));
|
||||||
|
|
||||||
|
assertTrue(headers.containsTimeMillis(of("millis"), millis));
|
||||||
|
// This test doesn't work on midnight, January 1, 1970 UTC
|
||||||
|
assertFalse(headers.containsTimeMillis(of("millis"), 0));
|
||||||
|
|
||||||
|
assertTrue(headers.containsObject(of("object"), "Hello World"));
|
||||||
|
assertFalse(headers.containsObject(of("object"), ""));
|
||||||
|
|
||||||
|
assertTrue(headers.contains(of("name"), of("value")));
|
||||||
|
assertFalse(headers.contains(of("name"), of("value1")));
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void canMixConvertedAndNormalValues() {
|
public void canMixConvertedAndNormalValues() {
|
||||||
TestDefaultHeaders headers = newInstance();
|
TestDefaultHeaders headers = newInstance();
|
||||||
|
@ -15,12 +15,14 @@
|
|||||||
*/
|
*/
|
||||||
package io.netty.microbench.headers;
|
package io.netty.microbench.headers;
|
||||||
|
|
||||||
|
import io.netty.handler.codec.Headers;
|
||||||
import io.netty.handler.codec.http.DefaultHttpHeaders;
|
import io.netty.handler.codec.http.DefaultHttpHeaders;
|
||||||
import io.netty.handler.codec.http2.DefaultHttp2Headers;
|
import io.netty.handler.codec.http2.DefaultHttp2Headers;
|
||||||
import io.netty.microbench.util.AbstractMicrobenchmark;
|
import io.netty.microbench.util.AbstractMicrobenchmark;
|
||||||
import io.netty.util.AsciiString;
|
import io.netty.util.AsciiString;
|
||||||
import org.openjdk.jmh.annotations.Benchmark;
|
import org.openjdk.jmh.annotations.Benchmark;
|
||||||
import org.openjdk.jmh.annotations.BenchmarkMode;
|
import org.openjdk.jmh.annotations.BenchmarkMode;
|
||||||
|
import org.openjdk.jmh.annotations.Fork;
|
||||||
import org.openjdk.jmh.annotations.Level;
|
import org.openjdk.jmh.annotations.Level;
|
||||||
import org.openjdk.jmh.annotations.Measurement;
|
import org.openjdk.jmh.annotations.Measurement;
|
||||||
import org.openjdk.jmh.annotations.Mode;
|
import org.openjdk.jmh.annotations.Mode;
|
||||||
@ -34,43 +36,78 @@ import org.openjdk.jmh.annotations.Warmup;
|
|||||||
import org.openjdk.jmh.infra.Blackhole;
|
import org.openjdk.jmh.infra.Blackhole;
|
||||||
|
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
@Threads(1)
|
@Threads(1)
|
||||||
@State(Scope.Benchmark)
|
@State(Scope.Benchmark)
|
||||||
@Warmup(iterations = 5)
|
@Fork(1)
|
||||||
@Measurement(iterations = 5)
|
@Warmup(iterations = 10)
|
||||||
|
@Measurement(iterations = 10)
|
||||||
@OutputTimeUnit(TimeUnit.NANOSECONDS)
|
@OutputTimeUnit(TimeUnit.NANOSECONDS)
|
||||||
public class HeadersBenchmark extends AbstractMicrobenchmark {
|
public class HeadersBenchmark extends AbstractMicrobenchmark {
|
||||||
|
|
||||||
|
private static String toHttpName(String name) {
|
||||||
|
return (name.startsWith(":")) ? name.substring(1) : name;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String toHttp2Name(String name) {
|
||||||
|
name = name.toLowerCase();
|
||||||
|
return (name.equals("host")) ? "xhost" : name;
|
||||||
|
}
|
||||||
|
|
||||||
@Param
|
@Param
|
||||||
ExampleHeaders.HeaderExample exampleHeader;
|
ExampleHeaders.HeaderExample exampleHeader;
|
||||||
|
|
||||||
AsciiString[] httpNames;
|
AsciiString[] httpNames;
|
||||||
|
AsciiString[] http2Names;
|
||||||
AsciiString[] httpValues;
|
AsciiString[] httpValues;
|
||||||
|
|
||||||
DefaultHttpHeaders httpHeaders;
|
DefaultHttpHeaders httpHeaders;
|
||||||
DefaultHttp2Headers http2Headers;
|
DefaultHttp2Headers http2Headers;
|
||||||
|
DefaultHttpHeaders emptyHttpHeaders;
|
||||||
|
DefaultHttp2Headers emptyHttp2Headers;
|
||||||
|
DefaultHttpHeaders emptyHttpHeadersNoValidate;
|
||||||
|
DefaultHttp2Headers emptyHttp2HeadersNoValidate;
|
||||||
|
SlowHeaders slowHttp2Headers;
|
||||||
|
|
||||||
@Setup(Level.Trial)
|
@Setup(Level.Trial)
|
||||||
public void setup() {
|
public void setup() {
|
||||||
Map<String, String> headers = ExampleHeaders.EXAMPLES.get(exampleHeader);
|
Map<String, String> headers = ExampleHeaders.EXAMPLES.get(exampleHeader);
|
||||||
httpNames = new AsciiString[headers.size()];
|
httpNames = new AsciiString[headers.size()];
|
||||||
|
http2Names = new AsciiString[headers.size()];
|
||||||
httpValues = new AsciiString[headers.size()];
|
httpValues = new AsciiString[headers.size()];
|
||||||
httpHeaders = new DefaultHttpHeaders(false);
|
httpHeaders = new DefaultHttpHeaders(false);
|
||||||
http2Headers = new DefaultHttp2Headers(false);
|
http2Headers = new DefaultHttp2Headers(false);
|
||||||
int idx = 0;
|
int idx = 0;
|
||||||
for (Map.Entry<String, String> header : headers.entrySet()) {
|
for (Map.Entry<String, String> header : headers.entrySet()) {
|
||||||
String name = header.getKey();
|
String name = header.getKey();
|
||||||
|
String httpName = toHttpName(name);
|
||||||
|
String http2Name = toHttp2Name(name);
|
||||||
String value = header.getValue();
|
String value = header.getValue();
|
||||||
httpNames[idx] = new AsciiString(name);
|
httpNames[idx] = new AsciiString(httpName);
|
||||||
|
http2Names[idx] = new AsciiString(http2Name);
|
||||||
httpValues[idx] = new AsciiString(value);
|
httpValues[idx] = new AsciiString(value);
|
||||||
|
httpHeaders.add(httpNames[idx], httpValues[idx]);
|
||||||
|
http2Headers.add(http2Names[idx], httpValues[idx]);
|
||||||
idx++;
|
idx++;
|
||||||
httpHeaders.add(new AsciiString(name), new AsciiString(value));
|
|
||||||
http2Headers.add(new AsciiString(name), new AsciiString(value));
|
|
||||||
}
|
}
|
||||||
|
slowHttp2Headers = new SlowHeaders(http2Headers);
|
||||||
|
emptyHttpHeaders = new DefaultHttpHeaders(true);
|
||||||
|
emptyHttp2Headers = new DefaultHttp2Headers(true);
|
||||||
|
emptyHttpHeadersNoValidate = new DefaultHttpHeaders(false);
|
||||||
|
emptyHttp2HeadersNoValidate = new DefaultHttp2Headers(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Setup(Level.Invocation)
|
||||||
|
public void setupEmptyHeaders() {
|
||||||
|
emptyHttpHeaders.clear();
|
||||||
|
emptyHttp2Headers .clear();
|
||||||
|
emptyHttpHeadersNoValidate.clear();
|
||||||
|
emptyHttp2HeadersNoValidate.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Benchmark
|
@Benchmark
|
||||||
@ -111,7 +148,7 @@ public class HeadersBenchmark extends AbstractMicrobenchmark {
|
|||||||
@Benchmark
|
@Benchmark
|
||||||
@BenchmarkMode(Mode.AverageTime)
|
@BenchmarkMode(Mode.AverageTime)
|
||||||
public void http2Remove(Blackhole bh) {
|
public void http2Remove(Blackhole bh) {
|
||||||
for (AsciiString name : httpNames) {
|
for (AsciiString name : http2Names) {
|
||||||
bh.consume(http2Headers.remove(name));
|
bh.consume(http2Headers.remove(name));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -119,7 +156,7 @@ public class HeadersBenchmark extends AbstractMicrobenchmark {
|
|||||||
@Benchmark
|
@Benchmark
|
||||||
@BenchmarkMode(Mode.AverageTime)
|
@BenchmarkMode(Mode.AverageTime)
|
||||||
public void http2Get(Blackhole bh) {
|
public void http2Get(Blackhole bh) {
|
||||||
for (AsciiString name : httpNames) {
|
for (AsciiString name : http2Names) {
|
||||||
bh.consume(http2Headers.get(name));
|
bh.consume(http2Headers.get(name));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -128,8 +165,8 @@ public class HeadersBenchmark extends AbstractMicrobenchmark {
|
|||||||
@BenchmarkMode(Mode.AverageTime)
|
@BenchmarkMode(Mode.AverageTime)
|
||||||
public DefaultHttp2Headers http2Put() {
|
public DefaultHttp2Headers http2Put() {
|
||||||
DefaultHttp2Headers headers = new DefaultHttp2Headers(false);
|
DefaultHttp2Headers headers = new DefaultHttp2Headers(false);
|
||||||
for (int i = 0; i < httpNames.length; i++) {
|
for (int i = 0; i < http2Names.length; i++) {
|
||||||
headers.add(httpNames[i], httpValues[i]);
|
headers.add(http2Names[i], httpValues[i]);
|
||||||
}
|
}
|
||||||
return headers;
|
return headers;
|
||||||
}
|
}
|
||||||
@ -141,4 +178,540 @@ public class HeadersBenchmark extends AbstractMicrobenchmark {
|
|||||||
bh.consume(entry);
|
bh.consume(entry);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Benchmark
|
||||||
|
@BenchmarkMode(Mode.AverageTime)
|
||||||
|
public void httpAddAllFastest(Blackhole bh) {
|
||||||
|
bh.consume(emptyHttpHeadersNoValidate.add(httpHeaders));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Benchmark
|
||||||
|
@BenchmarkMode(Mode.AverageTime)
|
||||||
|
public void httpAddAllFast(Blackhole bh) {
|
||||||
|
bh.consume(emptyHttpHeaders.add(httpHeaders));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Benchmark
|
||||||
|
@BenchmarkMode(Mode.AverageTime)
|
||||||
|
public void http2AddAllFastest(Blackhole bh) {
|
||||||
|
bh.consume(emptyHttp2HeadersNoValidate.add(http2Headers));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Benchmark
|
||||||
|
@BenchmarkMode(Mode.AverageTime)
|
||||||
|
public void http2AddAllFast(Blackhole bh) {
|
||||||
|
bh.consume(emptyHttp2Headers.add(http2Headers));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Benchmark
|
||||||
|
@BenchmarkMode(Mode.AverageTime)
|
||||||
|
public void http2AddAllSlow(Blackhole bh) {
|
||||||
|
bh.consume(emptyHttp2Headers.add(slowHttp2Headers));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final class SlowHeaders implements Headers<CharSequence, CharSequence, SlowHeaders> {
|
||||||
|
private final Headers<CharSequence, CharSequence, ? extends Headers> delegate;
|
||||||
|
private SlowHeaders(Headers<CharSequence, CharSequence, ? extends Headers> delegate) {
|
||||||
|
this.delegate = delegate;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CharSequence get(CharSequence name) {
|
||||||
|
return delegate.get(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CharSequence get(CharSequence name, CharSequence defaultValue) {
|
||||||
|
return delegate.get(name, defaultValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CharSequence getAndRemove(CharSequence name) {
|
||||||
|
return delegate.getAndRemove(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CharSequence getAndRemove(CharSequence name, CharSequence defaultValue) {
|
||||||
|
return delegate.getAndRemove(name, defaultValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<CharSequence> getAll(CharSequence name) {
|
||||||
|
return delegate.getAll(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<CharSequence> getAllAndRemove(CharSequence name) {
|
||||||
|
return delegate.getAllAndRemove(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Boolean getBoolean(CharSequence name) {
|
||||||
|
return delegate.getBoolean(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean getBoolean(CharSequence name, boolean defaultValue) {
|
||||||
|
return delegate.getBoolean(name, defaultValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Byte getByte(CharSequence name) {
|
||||||
|
return delegate.getByte(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte getByte(CharSequence name, byte defaultValue) {
|
||||||
|
return delegate.getByte(name, defaultValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Character getChar(CharSequence name) {
|
||||||
|
return delegate.getChar(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public char getChar(CharSequence name, char defaultValue) {
|
||||||
|
return delegate.getChar(name, defaultValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Short getShort(CharSequence name) {
|
||||||
|
return delegate.getShort(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public short getShort(CharSequence name, short defaultValue) {
|
||||||
|
return delegate.getShort(name, defaultValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Integer getInt(CharSequence name) {
|
||||||
|
return delegate.getInt(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getInt(CharSequence name, int defaultValue) {
|
||||||
|
return delegate.getInt(name, defaultValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Long getLong(CharSequence name) {
|
||||||
|
return delegate.getLong(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getLong(CharSequence name, long defaultValue) {
|
||||||
|
return delegate.getLong(name, defaultValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Float getFloat(CharSequence name) {
|
||||||
|
return delegate.getFloat(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public float getFloat(CharSequence name, float defaultValue) {
|
||||||
|
return delegate.getFloat(name, defaultValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Double getDouble(CharSequence name) {
|
||||||
|
return delegate.getDouble(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double getDouble(CharSequence name, double defaultValue) {
|
||||||
|
return delegate.getDouble(name, defaultValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Long getTimeMillis(CharSequence name) {
|
||||||
|
return delegate.getTimeMillis(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getTimeMillis(CharSequence name, long defaultValue) {
|
||||||
|
return delegate.getTimeMillis(name, defaultValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Boolean getBooleanAndRemove(CharSequence name) {
|
||||||
|
return delegate.getBooleanAndRemove(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean getBooleanAndRemove(CharSequence name, boolean defaultValue) {
|
||||||
|
return delegate.getBooleanAndRemove(name, defaultValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Byte getByteAndRemove(CharSequence name) {
|
||||||
|
return delegate.getByteAndRemove(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte getByteAndRemove(CharSequence name, byte defaultValue) {
|
||||||
|
return delegate.getByteAndRemove(name, defaultValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Character getCharAndRemove(CharSequence name) {
|
||||||
|
return delegate.getCharAndRemove(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public char getCharAndRemove(CharSequence name, char defaultValue) {
|
||||||
|
return delegate.getCharAndRemove(name, defaultValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Short getShortAndRemove(CharSequence name) {
|
||||||
|
return delegate.getShortAndRemove(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public short getShortAndRemove(CharSequence name, short defaultValue) {
|
||||||
|
return delegate.getShortAndRemove(name, defaultValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Integer getIntAndRemove(CharSequence name) {
|
||||||
|
return delegate.getIntAndRemove(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getIntAndRemove(CharSequence name, int defaultValue) {
|
||||||
|
return delegate.getIntAndRemove(name, defaultValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Long getLongAndRemove(CharSequence name) {
|
||||||
|
return delegate.getLongAndRemove(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getLongAndRemove(CharSequence name, long defaultValue) {
|
||||||
|
return delegate.getLongAndRemove(name, defaultValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Float getFloatAndRemove(CharSequence name) {
|
||||||
|
return delegate.getFloatAndRemove(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public float getFloatAndRemove(CharSequence name, float defaultValue) {
|
||||||
|
return delegate.getFloatAndRemove(name, defaultValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Double getDoubleAndRemove(CharSequence name) {
|
||||||
|
return delegate.getDoubleAndRemove(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double getDoubleAndRemove(CharSequence name, double defaultValue) {
|
||||||
|
return delegate.getDoubleAndRemove(name, defaultValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Long getTimeMillisAndRemove(CharSequence name) {
|
||||||
|
return delegate.getTimeMillisAndRemove(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getTimeMillisAndRemove(CharSequence name, long defaultValue) {
|
||||||
|
return delegate.getTimeMillisAndRemove(name, defaultValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean contains(CharSequence name) {
|
||||||
|
return delegate.contains(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean contains(CharSequence name, CharSequence value) {
|
||||||
|
return delegate.contains(name, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean containsObject(CharSequence name, Object value) {
|
||||||
|
return delegate.containsObject(name, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean containsBoolean(CharSequence name, boolean value) {
|
||||||
|
return delegate.containsBoolean(name, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean containsByte(CharSequence name, byte value) {
|
||||||
|
return delegate.containsByte(name, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean containsChar(CharSequence name, char value) {
|
||||||
|
return delegate.containsChar(name, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean containsShort(CharSequence name, short value) {
|
||||||
|
return delegate.containsShort(name, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean containsInt(CharSequence name, int value) {
|
||||||
|
return delegate.containsInt(name, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean containsLong(CharSequence name, long value) {
|
||||||
|
return delegate.containsLong(name, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean containsFloat(CharSequence name, float value) {
|
||||||
|
return delegate.containsFloat(name, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean containsDouble(CharSequence name, double value) {
|
||||||
|
return delegate.containsDouble(name, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean containsTimeMillis(CharSequence name, long value) {
|
||||||
|
return delegate.containsTimeMillis(name, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int size() {
|
||||||
|
return delegate.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isEmpty() {
|
||||||
|
return delegate.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<CharSequence> names() {
|
||||||
|
return delegate.names();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SlowHeaders add(CharSequence name, CharSequence value) {
|
||||||
|
delegate.add(name, value);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SlowHeaders add(CharSequence name, Iterable<? extends CharSequence> values) {
|
||||||
|
delegate.add(name, values);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SlowHeaders add(CharSequence name, CharSequence... values) {
|
||||||
|
delegate.add(name, values);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SlowHeaders addObject(CharSequence name, Object value) {
|
||||||
|
delegate.addObject(name, value);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SlowHeaders addObject(CharSequence name, Iterable<?> values) {
|
||||||
|
delegate.addObject(name, values);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SlowHeaders addObject(CharSequence name, Object... values) {
|
||||||
|
delegate.addObject(name, values);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SlowHeaders addBoolean(CharSequence name, boolean value) {
|
||||||
|
delegate.addBoolean(name, value);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SlowHeaders addByte(CharSequence name, byte value) {
|
||||||
|
delegate.addByte(name, value);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SlowHeaders addChar(CharSequence name, char value) {
|
||||||
|
delegate.addChar(name, value);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SlowHeaders addShort(CharSequence name, short value) {
|
||||||
|
delegate.addShort(name, value);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SlowHeaders addInt(CharSequence name, int value) {
|
||||||
|
delegate.addInt(name, value);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SlowHeaders addLong(CharSequence name, long value) {
|
||||||
|
delegate.addLong(name, value);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SlowHeaders addFloat(CharSequence name, float value) {
|
||||||
|
delegate.addFloat(name, value);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SlowHeaders addDouble(CharSequence name, double value) {
|
||||||
|
delegate.addDouble(name, value);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SlowHeaders addTimeMillis(CharSequence name, long value) {
|
||||||
|
delegate.addTimeMillis(name, value);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SlowHeaders add(Headers<? extends CharSequence, ? extends CharSequence, ?> headers) {
|
||||||
|
delegate.add(headers);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SlowHeaders set(CharSequence name, CharSequence value) {
|
||||||
|
delegate.set(name, value);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SlowHeaders set(CharSequence name, Iterable<? extends CharSequence> values) {
|
||||||
|
delegate.set(name, values);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SlowHeaders set(CharSequence name, CharSequence... values) {
|
||||||
|
delegate.set(name, values);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SlowHeaders setObject(CharSequence name, Object value) {
|
||||||
|
delegate.setObject(name, value);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SlowHeaders setObject(CharSequence name, Iterable<?> values) {
|
||||||
|
delegate.setObject(name, values);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SlowHeaders setObject(CharSequence name, Object... values) {
|
||||||
|
delegate.setObject(name, values);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SlowHeaders setBoolean(CharSequence name, boolean value) {
|
||||||
|
delegate.setBoolean(name, value);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SlowHeaders setByte(CharSequence name, byte value) {
|
||||||
|
delegate.setByte(name, value);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SlowHeaders setChar(CharSequence name, char value) {
|
||||||
|
delegate.setChar(name, value);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SlowHeaders setShort(CharSequence name, short value) {
|
||||||
|
delegate.setShort(name, value);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SlowHeaders setInt(CharSequence name, int value) {
|
||||||
|
delegate.setInt(name, value);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SlowHeaders setLong(CharSequence name, long value) {
|
||||||
|
delegate.setLong(name, value);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SlowHeaders setFloat(CharSequence name, float value) {
|
||||||
|
delegate.setFloat(name, value);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SlowHeaders setDouble(CharSequence name, double value) {
|
||||||
|
delegate.setDouble(name, value);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SlowHeaders setTimeMillis(CharSequence name, long value) {
|
||||||
|
delegate.setTimeMillis(name, value);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SlowHeaders set(Headers<? extends CharSequence, ? extends CharSequence, ?> headers) {
|
||||||
|
delegate.set(headers);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SlowHeaders setAll(Headers<? extends CharSequence, ? extends CharSequence, ?> headers) {
|
||||||
|
delegate.setAll(headers);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean remove(CharSequence name) {
|
||||||
|
return delegate.remove(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SlowHeaders clear() {
|
||||||
|
delegate.clear();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Iterator<Entry<CharSequence, CharSequence>> iterator() {
|
||||||
|
return delegate.iterator();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user