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.util.internal.ObjectUtil.checkNotNull;
|
||||
import io.netty.handler.codec.http.HttpRequest;
|
||||
import io.netty.util.internal.InternalThreadLocalMap;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Comparator;
|
||||
@ -197,7 +197,7 @@ public final class ClientCookieEncoder extends CookieEncoder {
|
||||
if (!cookiesIt.hasNext()) {
|
||||
encode(buf, firstCookie);
|
||||
} else {
|
||||
List<Cookie> cookiesList = new ArrayList<Cookie>();
|
||||
List<Cookie> cookiesList = InternalThreadLocalMap.get().arrayList();
|
||||
cookiesList.add(firstCookie);
|
||||
while (cookiesIt.hasNext()) {
|
||||
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.MultiPartStatus;
|
||||
import io.netty.handler.codec.http.multipart.HttpPostRequestDecoder.NotEnoughDataDecoderException;
|
||||
import io.netty.util.internal.InternalThreadLocalMap;
|
||||
import io.netty.util.internal.StringUtil;
|
||||
|
||||
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 ','
|
||||
*/
|
||||
private static String[] splitMultipartHeaderValues(String svalue) {
|
||||
List<String> values = new ArrayList<String>(1);
|
||||
List<String> values = InternalThreadLocalMap.get().arrayList(1);
|
||||
boolean inQuote = false;
|
||||
boolean escapeNext = false;
|
||||
int start = 0;
|
||||
|
@ -22,6 +22,7 @@ import io.netty.util.concurrent.FastThreadLocalThread;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.CharsetDecoder;
|
||||
import java.nio.charset.CharsetEncoder;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.IdentityHashMap;
|
||||
import java.util.Map;
|
||||
@ -34,6 +35,8 @@ import java.util.WeakHashMap;
|
||||
*/
|
||||
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 InternalThreadLocalMap getIfSet() {
|
||||
@ -144,6 +147,9 @@ public final class InternalThreadLocalMap extends UnpaddedInternalThreadLocalMap
|
||||
if (charsetDecoderCache != null) {
|
||||
count ++;
|
||||
}
|
||||
if (arrayList != null) {
|
||||
count ++;
|
||||
}
|
||||
|
||||
for (Object o: indexedVariables) {
|
||||
if (o != UNSET) {
|
||||
@ -182,6 +188,21 @@ public final class InternalThreadLocalMap extends UnpaddedInternalThreadLocalMap
|
||||
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() {
|
||||
return futureListenerStackDepth;
|
||||
}
|
||||
|
@ -16,7 +16,6 @@
|
||||
package io.netty.util.internal;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Formatter;
|
||||
import java.util.List;
|
||||
|
||||
@ -91,7 +90,7 @@ public final class StringUtil {
|
||||
*/
|
||||
public static String[] split(String value, char delim) {
|
||||
final int end = value.length();
|
||||
final List<String> res = new ArrayList<String>();
|
||||
final List<String> res = InternalThreadLocalMap.get().arrayList();
|
||||
|
||||
int start = 0;
|
||||
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) {
|
||||
final int end = value.length();
|
||||
final List<String> res = new ArrayList<String>();
|
||||
final List<String> res = InternalThreadLocalMap.get().arrayList();
|
||||
|
||||
int start = 0;
|
||||
int cpt = 1;
|
||||
|
@ -21,6 +21,7 @@ import io.netty.util.concurrent.FastThreadLocal;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.CharsetDecoder;
|
||||
import java.nio.charset.CharsetEncoder;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
@ -51,6 +52,9 @@ class UnpaddedInternalThreadLocalMap {
|
||||
Map<Charset, CharsetEncoder> charsetEncoderCache;
|
||||
Map<Charset, CharsetDecoder> charsetDecoderCache;
|
||||
|
||||
// ArrayList-related thread-locals
|
||||
ArrayList<Object> arrayList;
|
||||
|
||||
UnpaddedInternalThreadLocalMap(Object[] indexedVariables) {
|
||||
this.indexedVariables = indexedVariables;
|
||||
}
|
||||
|
@ -15,7 +15,8 @@
|
||||
*/
|
||||
package io.netty.handler.ssl;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import io.netty.util.internal.InternalThreadLocalMap;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
@ -33,7 +34,7 @@ public final class IdentityCipherSuiteFilter implements CipherSuiteFilter {
|
||||
if (ciphers == null) {
|
||||
return defaultCiphers.toArray(new String[defaultCiphers.size()]);
|
||||
} else {
|
||||
List<String> newCiphers = new ArrayList<String>(supportedCiphers.size());
|
||||
List<String> newCiphers = InternalThreadLocalMap.get().arrayList(supportedCiphers.size());
|
||||
for (String c : ciphers) {
|
||||
if (c == null) {
|
||||
break;
|
||||
|
@ -19,6 +19,7 @@ import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.ByteBufAllocator;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import io.netty.util.internal.EmptyArrays;
|
||||
import io.netty.util.internal.InternalThreadLocalMap;
|
||||
import io.netty.util.internal.PlatformDependent;
|
||||
import io.netty.util.internal.StringUtil;
|
||||
import io.netty.util.internal.logging.InternalLogger;
|
||||
@ -42,7 +43,6 @@ import java.nio.ByteBuffer;
|
||||
import java.nio.ReadOnlyBufferException;
|
||||
import java.security.Principal;
|
||||
import java.security.cert.Certificate;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
@ -1025,7 +1025,7 @@ public final class OpenSslEngine extends SSLEngine {
|
||||
|
||||
@Override
|
||||
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
|
||||
enabled.add(PROTOCOL_SSL_V2_HELLO);
|
||||
|
||||
|
@ -15,8 +15,9 @@
|
||||
*/
|
||||
package io.netty.handler.ssl;
|
||||
|
||||
import io.netty.util.internal.InternalThreadLocalMap;
|
||||
|
||||
import javax.net.ssl.SSLEngine;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
@ -40,10 +41,10 @@ public final class SupportedCipherSuiteFilter implements CipherSuiteFilter {
|
||||
|
||||
final List<String> newCiphers;
|
||||
if (ciphers == null) {
|
||||
newCiphers = new ArrayList<String>(defaultCiphers.size());
|
||||
newCiphers = InternalThreadLocalMap.get().arrayList(defaultCiphers.size());
|
||||
ciphers = defaultCiphers;
|
||||
} else {
|
||||
newCiphers = new ArrayList<String>(supportedCiphers.size());
|
||||
newCiphers = InternalThreadLocalMap.get().arrayList(supportedCiphers.size());
|
||||
}
|
||||
for (String c : ciphers) {
|
||||
if (c == null) {
|
||||
|
@ -20,6 +20,7 @@ import io.netty.buffer.ByteBufUtil;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import io.netty.util.internal.EmptyArrays;
|
||||
import io.netty.util.concurrent.FastThreadLocal;
|
||||
import io.netty.util.internal.InternalThreadLocalMap;
|
||||
|
||||
import javax.net.ssl.ManagerFactoryParameters;
|
||||
import javax.net.ssl.TrustManager;
|
||||
@ -31,7 +32,6 @@ import java.security.NoSuchAlgorithmException;
|
||||
import java.security.cert.CertificateEncodingException;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.regex.Pattern;
|
||||
@ -151,7 +151,7 @@ public final class FingerprintTrustManagerFactory extends SimpleTrustManagerFact
|
||||
throw new NullPointerException("fingerprints");
|
||||
}
|
||||
|
||||
List<byte[]> list = new ArrayList<byte[]>();
|
||||
List<byte[]> list = InternalThreadLocalMap.get().arrayList();
|
||||
for (byte[] f: fingerprints) {
|
||||
if (f == null) {
|
||||
break;
|
||||
@ -171,7 +171,7 @@ public final class FingerprintTrustManagerFactory extends SimpleTrustManagerFact
|
||||
throw new NullPointerException("fingerprints");
|
||||
}
|
||||
|
||||
List<byte[]> list = new ArrayList<byte[]>();
|
||||
List<byte[]> list = InternalThreadLocalMap.get().arrayList();
|
||||
for (String f: fingerprints) {
|
||||
if (f == null) {
|
||||
break;
|
||||
|
Loading…
Reference in New Issue
Block a user