Backport InternalThreadLocalMap reusable ArrayList
Motivation:
See https://github.com/netty/netty/issues/3411.
Backport perf improvements on 4.0 and make AsyncHttpClient DNS modules
backports easier to maintain.
Modifications:
Cherry-picked b7415a3307
Result:
Reuse a thread local ArrayList to avoid allocations.
This commit is contained in:
parent
fdefbba9a0
commit
4608ecf374
@ -22,8 +22,8 @@ import static io.netty.handler.codec.http.cookie.CookieUtil.stripTrailingSeparat
|
|||||||
import static io.netty.handler.codec.http.cookie.CookieUtil.stripTrailingSeparatorOrNull;
|
import static io.netty.handler.codec.http.cookie.CookieUtil.stripTrailingSeparatorOrNull;
|
||||||
import static io.netty.util.internal.ObjectUtil.checkNotNull;
|
import static io.netty.util.internal.ObjectUtil.checkNotNull;
|
||||||
import io.netty.handler.codec.http.HttpRequest;
|
import io.netty.handler.codec.http.HttpRequest;
|
||||||
|
import io.netty.util.internal.InternalThreadLocalMap;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
@ -197,7 +197,7 @@ public final class ClientCookieEncoder extends CookieEncoder {
|
|||||||
if (!cookiesIt.hasNext()) {
|
if (!cookiesIt.hasNext()) {
|
||||||
encode(buf, firstCookie);
|
encode(buf, firstCookie);
|
||||||
} else {
|
} else {
|
||||||
List<Cookie> cookiesList = new ArrayList<Cookie>();
|
List<Cookie> cookiesList = InternalThreadLocalMap.get().arrayList();
|
||||||
cookiesList.add(firstCookie);
|
cookiesList.add(firstCookie);
|
||||||
while (cookiesIt.hasNext()) {
|
while (cookiesIt.hasNext()) {
|
||||||
cookiesList.add(cookiesIt.next());
|
cookiesList.add(cookiesIt.next());
|
||||||
|
@ -28,6 +28,7 @@ import io.netty.handler.codec.http.multipart.HttpPostRequestDecoder.EndOfDataDec
|
|||||||
import io.netty.handler.codec.http.multipart.HttpPostRequestDecoder.ErrorDataDecoderException;
|
import io.netty.handler.codec.http.multipart.HttpPostRequestDecoder.ErrorDataDecoderException;
|
||||||
import io.netty.handler.codec.http.multipart.HttpPostRequestDecoder.MultiPartStatus;
|
import io.netty.handler.codec.http.multipart.HttpPostRequestDecoder.MultiPartStatus;
|
||||||
import io.netty.handler.codec.http.multipart.HttpPostRequestDecoder.NotEnoughDataDecoderException;
|
import io.netty.handler.codec.http.multipart.HttpPostRequestDecoder.NotEnoughDataDecoderException;
|
||||||
|
import io.netty.util.internal.InternalThreadLocalMap;
|
||||||
import io.netty.util.internal.StringUtil;
|
import io.netty.util.internal.StringUtil;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@ -1812,7 +1813,7 @@ public class HttpPostMultipartRequestDecoder implements InterfaceHttpPostRequest
|
|||||||
* @return an array of String where values that were separated by ';' or ','
|
* @return an array of String where values that were separated by ';' or ','
|
||||||
*/
|
*/
|
||||||
private static String[] splitMultipartHeaderValues(String svalue) {
|
private static String[] splitMultipartHeaderValues(String svalue) {
|
||||||
List<String> values = new ArrayList<String>(1);
|
List<String> values = InternalThreadLocalMap.get().arrayList(1);
|
||||||
boolean inQuote = false;
|
boolean inQuote = false;
|
||||||
boolean escapeNext = false;
|
boolean escapeNext = false;
|
||||||
int start = 0;
|
int start = 0;
|
||||||
|
@ -22,6 +22,7 @@ import io.netty.util.concurrent.FastThreadLocalThread;
|
|||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
||||||
import java.nio.charset.CharsetDecoder;
|
import java.nio.charset.CharsetDecoder;
|
||||||
import java.nio.charset.CharsetEncoder;
|
import java.nio.charset.CharsetEncoder;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.IdentityHashMap;
|
import java.util.IdentityHashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@ -34,6 +35,8 @@ import java.util.WeakHashMap;
|
|||||||
*/
|
*/
|
||||||
public final class InternalThreadLocalMap extends UnpaddedInternalThreadLocalMap {
|
public final class InternalThreadLocalMap extends UnpaddedInternalThreadLocalMap {
|
||||||
|
|
||||||
|
private static final int DEFAULT_ARRAY_LIST_INITIAL_CAPACITY = 8;
|
||||||
|
|
||||||
public static final Object UNSET = new Object();
|
public static final Object UNSET = new Object();
|
||||||
|
|
||||||
public static InternalThreadLocalMap getIfSet() {
|
public static InternalThreadLocalMap getIfSet() {
|
||||||
@ -144,6 +147,9 @@ public final class InternalThreadLocalMap extends UnpaddedInternalThreadLocalMap
|
|||||||
if (charsetDecoderCache != null) {
|
if (charsetDecoderCache != null) {
|
||||||
count ++;
|
count ++;
|
||||||
}
|
}
|
||||||
|
if (arrayList != null) {
|
||||||
|
count ++;
|
||||||
|
}
|
||||||
|
|
||||||
for (Object o: indexedVariables) {
|
for (Object o: indexedVariables) {
|
||||||
if (o != UNSET) {
|
if (o != UNSET) {
|
||||||
@ -182,6 +188,21 @@ public final class InternalThreadLocalMap extends UnpaddedInternalThreadLocalMap
|
|||||||
return cache;
|
return cache;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public <E> ArrayList<E> arrayList() {
|
||||||
|
return arrayList(DEFAULT_ARRAY_LIST_INITIAL_CAPACITY);
|
||||||
|
}
|
||||||
|
|
||||||
|
public <E> ArrayList<E> arrayList(int minCapacity) {
|
||||||
|
ArrayList<E> list = (ArrayList<E>) arrayList;
|
||||||
|
if (list == null) {
|
||||||
|
list = (ArrayList<E>) new ArrayList<Object>(minCapacity);
|
||||||
|
} else {
|
||||||
|
list.clear();
|
||||||
|
list.ensureCapacity(minCapacity);
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
public int futureListenerStackDepth() {
|
public int futureListenerStackDepth() {
|
||||||
return futureListenerStackDepth;
|
return futureListenerStackDepth;
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,6 @@
|
|||||||
package io.netty.util.internal;
|
package io.netty.util.internal;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Formatter;
|
import java.util.Formatter;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@ -91,7 +90,7 @@ public final class StringUtil {
|
|||||||
*/
|
*/
|
||||||
public static String[] split(String value, char delim) {
|
public static String[] split(String value, char delim) {
|
||||||
final int end = value.length();
|
final int end = value.length();
|
||||||
final List<String> res = new ArrayList<String>();
|
final List<String> res = InternalThreadLocalMap.get().arrayList();
|
||||||
|
|
||||||
int start = 0;
|
int start = 0;
|
||||||
for (int i = 0; i < end; i ++) {
|
for (int i = 0; i < end; i ++) {
|
||||||
@ -133,7 +132,7 @@ public final class StringUtil {
|
|||||||
*/
|
*/
|
||||||
public static String[] split(String value, char delim, int maxParts) {
|
public static String[] split(String value, char delim, int maxParts) {
|
||||||
final int end = value.length();
|
final int end = value.length();
|
||||||
final List<String> res = new ArrayList<String>();
|
final List<String> res = InternalThreadLocalMap.get().arrayList();
|
||||||
|
|
||||||
int start = 0;
|
int start = 0;
|
||||||
int cpt = 1;
|
int cpt = 1;
|
||||||
|
@ -21,6 +21,7 @@ import io.netty.util.concurrent.FastThreadLocal;
|
|||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
||||||
import java.nio.charset.CharsetDecoder;
|
import java.nio.charset.CharsetDecoder;
|
||||||
import java.nio.charset.CharsetEncoder;
|
import java.nio.charset.CharsetEncoder;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
@ -51,6 +52,9 @@ class UnpaddedInternalThreadLocalMap {
|
|||||||
Map<Charset, CharsetEncoder> charsetEncoderCache;
|
Map<Charset, CharsetEncoder> charsetEncoderCache;
|
||||||
Map<Charset, CharsetDecoder> charsetDecoderCache;
|
Map<Charset, CharsetDecoder> charsetDecoderCache;
|
||||||
|
|
||||||
|
// ArrayList-related thread-locals
|
||||||
|
ArrayList<Object> arrayList;
|
||||||
|
|
||||||
UnpaddedInternalThreadLocalMap(Object[] indexedVariables) {
|
UnpaddedInternalThreadLocalMap(Object[] indexedVariables) {
|
||||||
this.indexedVariables = indexedVariables;
|
this.indexedVariables = indexedVariables;
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,8 @@
|
|||||||
*/
|
*/
|
||||||
package io.netty.handler.ssl;
|
package io.netty.handler.ssl;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import io.netty.util.internal.InternalThreadLocalMap;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
@ -33,7 +34,7 @@ public final class IdentityCipherSuiteFilter implements CipherSuiteFilter {
|
|||||||
if (ciphers == null) {
|
if (ciphers == null) {
|
||||||
return defaultCiphers.toArray(new String[defaultCiphers.size()]);
|
return defaultCiphers.toArray(new String[defaultCiphers.size()]);
|
||||||
} else {
|
} else {
|
||||||
List<String> newCiphers = new ArrayList<String>(supportedCiphers.size());
|
List<String> newCiphers = InternalThreadLocalMap.get().arrayList(supportedCiphers.size());
|
||||||
for (String c : ciphers) {
|
for (String c : ciphers) {
|
||||||
if (c == null) {
|
if (c == null) {
|
||||||
break;
|
break;
|
||||||
|
@ -19,6 +19,7 @@ import io.netty.buffer.ByteBuf;
|
|||||||
import io.netty.buffer.ByteBufAllocator;
|
import io.netty.buffer.ByteBufAllocator;
|
||||||
import io.netty.buffer.Unpooled;
|
import io.netty.buffer.Unpooled;
|
||||||
import io.netty.util.internal.EmptyArrays;
|
import io.netty.util.internal.EmptyArrays;
|
||||||
|
import io.netty.util.internal.InternalThreadLocalMap;
|
||||||
import io.netty.util.internal.PlatformDependent;
|
import io.netty.util.internal.PlatformDependent;
|
||||||
import io.netty.util.internal.StringUtil;
|
import io.netty.util.internal.StringUtil;
|
||||||
import io.netty.util.internal.logging.InternalLogger;
|
import io.netty.util.internal.logging.InternalLogger;
|
||||||
@ -42,7 +43,6 @@ import java.nio.ByteBuffer;
|
|||||||
import java.nio.ReadOnlyBufferException;
|
import java.nio.ReadOnlyBufferException;
|
||||||
import java.security.Principal;
|
import java.security.Principal;
|
||||||
import java.security.cert.Certificate;
|
import java.security.cert.Certificate;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
@ -1025,7 +1025,7 @@ public final class OpenSslEngine extends SSLEngine {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String[] getEnabledProtocols() {
|
public String[] getEnabledProtocols() {
|
||||||
List<String> enabled = new ArrayList<String>();
|
List<String> enabled = InternalThreadLocalMap.get().arrayList();
|
||||||
// Seems like there is no way to explict disable SSLv2Hello in openssl so it is always enabled
|
// Seems like there is no way to explict disable SSLv2Hello in openssl so it is always enabled
|
||||||
enabled.add(PROTOCOL_SSL_V2_HELLO);
|
enabled.add(PROTOCOL_SSL_V2_HELLO);
|
||||||
|
|
||||||
|
@ -15,8 +15,9 @@
|
|||||||
*/
|
*/
|
||||||
package io.netty.handler.ssl;
|
package io.netty.handler.ssl;
|
||||||
|
|
||||||
|
import io.netty.util.internal.InternalThreadLocalMap;
|
||||||
|
|
||||||
import javax.net.ssl.SSLEngine;
|
import javax.net.ssl.SSLEngine;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
@ -40,10 +41,10 @@ public final class SupportedCipherSuiteFilter implements CipherSuiteFilter {
|
|||||||
|
|
||||||
final List<String> newCiphers;
|
final List<String> newCiphers;
|
||||||
if (ciphers == null) {
|
if (ciphers == null) {
|
||||||
newCiphers = new ArrayList<String>(defaultCiphers.size());
|
newCiphers = InternalThreadLocalMap.get().arrayList(defaultCiphers.size());
|
||||||
ciphers = defaultCiphers;
|
ciphers = defaultCiphers;
|
||||||
} else {
|
} else {
|
||||||
newCiphers = new ArrayList<String>(supportedCiphers.size());
|
newCiphers = InternalThreadLocalMap.get().arrayList(supportedCiphers.size());
|
||||||
}
|
}
|
||||||
for (String c : ciphers) {
|
for (String c : ciphers) {
|
||||||
if (c == null) {
|
if (c == null) {
|
||||||
|
@ -20,6 +20,7 @@ import io.netty.buffer.ByteBufUtil;
|
|||||||
import io.netty.buffer.Unpooled;
|
import io.netty.buffer.Unpooled;
|
||||||
import io.netty.util.internal.EmptyArrays;
|
import io.netty.util.internal.EmptyArrays;
|
||||||
import io.netty.util.concurrent.FastThreadLocal;
|
import io.netty.util.concurrent.FastThreadLocal;
|
||||||
|
import io.netty.util.internal.InternalThreadLocalMap;
|
||||||
|
|
||||||
import javax.net.ssl.ManagerFactoryParameters;
|
import javax.net.ssl.ManagerFactoryParameters;
|
||||||
import javax.net.ssl.TrustManager;
|
import javax.net.ssl.TrustManager;
|
||||||
@ -31,7 +32,6 @@ import java.security.NoSuchAlgorithmException;
|
|||||||
import java.security.cert.CertificateEncodingException;
|
import java.security.cert.CertificateEncodingException;
|
||||||
import java.security.cert.CertificateException;
|
import java.security.cert.CertificateException;
|
||||||
import java.security.cert.X509Certificate;
|
import java.security.cert.X509Certificate;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
@ -151,7 +151,7 @@ public final class FingerprintTrustManagerFactory extends SimpleTrustManagerFact
|
|||||||
throw new NullPointerException("fingerprints");
|
throw new NullPointerException("fingerprints");
|
||||||
}
|
}
|
||||||
|
|
||||||
List<byte[]> list = new ArrayList<byte[]>();
|
List<byte[]> list = InternalThreadLocalMap.get().arrayList();
|
||||||
for (byte[] f: fingerprints) {
|
for (byte[] f: fingerprints) {
|
||||||
if (f == null) {
|
if (f == null) {
|
||||||
break;
|
break;
|
||||||
@ -171,7 +171,7 @@ public final class FingerprintTrustManagerFactory extends SimpleTrustManagerFact
|
|||||||
throw new NullPointerException("fingerprints");
|
throw new NullPointerException("fingerprints");
|
||||||
}
|
}
|
||||||
|
|
||||||
List<byte[]> list = new ArrayList<byte[]>();
|
List<byte[]> list = InternalThreadLocalMap.get().arrayList();
|
||||||
for (String f: fingerprints) {
|
for (String f: fingerprints) {
|
||||||
if (f == null) {
|
if (f == null) {
|
||||||
break;
|
break;
|
||||||
|
Loading…
Reference in New Issue
Block a user