Remove synchronization overhead on generateName.

Motivation:

Changing the chache of generated names to use a cache per thread. This will remove the bottleneck when many eventloops are used and names need to generate.

Modifications:

Use a FastThreadLocal to store the cached names.

Result:

Less locking between threads.
This commit is contained in:
Norman Maurer 2015-10-28 15:38:14 +01:00
parent 69b5aefd09
commit 8ecfd58714

View File

@ -19,6 +19,7 @@ import io.netty.channel.Channel.Unsafe;
import io.netty.util.ReferenceCountUtil; import io.netty.util.ReferenceCountUtil;
import io.netty.util.concurrent.EventExecutor; import io.netty.util.concurrent.EventExecutor;
import io.netty.util.concurrent.EventExecutorGroup; import io.netty.util.concurrent.EventExecutorGroup;
import io.netty.util.concurrent.FastThreadLocal;
import io.netty.util.internal.OneTimeTask; import io.netty.util.internal.OneTimeTask;
import io.netty.util.internal.PlatformDependent; import io.netty.util.internal.PlatformDependent;
import io.netty.util.internal.StringUtil; import io.netty.util.internal.StringUtil;
@ -46,15 +47,13 @@ final class DefaultChannelPipeline implements ChannelPipeline {
static final InternalLogger logger = InternalLoggerFactory.getInstance(DefaultChannelPipeline.class); static final InternalLogger logger = InternalLoggerFactory.getInstance(DefaultChannelPipeline.class);
@SuppressWarnings("unchecked") private static final FastThreadLocal<Map<Class<?>, String>> nameCaches =
private static final WeakHashMap<Class<?>, String>[] nameCaches = new FastThreadLocal<Map<Class<?>, String>>() {
new WeakHashMap[Runtime.getRuntime().availableProcessors()]; @Override
protected Map<Class<?>, String> initialValue() throws Exception {
static { return new WeakHashMap<Class<?>, String>();
for (int i = 0; i < nameCaches.length; i ++) {
nameCaches[i] = new WeakHashMap<Class<?>, String>();
} }
} };
final AbstractChannel channel; final AbstractChannel channel;
@ -261,15 +260,12 @@ final class DefaultChannelPipeline implements ChannelPipeline {
} }
private String generateName(ChannelHandler handler) { private String generateName(ChannelHandler handler) {
WeakHashMap<Class<?>, String> cache = nameCaches[(int) (Thread.currentThread().getId() % nameCaches.length)]; Map<Class<?>, String> cache = nameCaches.get();
Class<?> handlerType = handler.getClass(); Class<?> handlerType = handler.getClass();
String name; String name = cache.get(handlerType);
synchronized (cache) { if (name == null) {
name = cache.get(handlerType); name = generateName0(handlerType);
if (name == null) { cache.put(handlerType, name);
name = generateName0(handlerType);
cache.put(handlerType, name);
}
} }
synchronized (this) { synchronized (this) {