From ff5aec0c78f18fcd4ef95afabe521f9c1427a028 Mon Sep 17 00:00:00 2001 From: Trustin Lee Date: Fri, 8 Feb 2013 18:21:07 +0900 Subject: [PATCH] Replace TypeParameterFinder with TypeParameterMatcher - We can avoid reflective matching using byte code generation. - Better matching performance when message type is Object --- .../handler/codec/ByteToMessageCodec.java | 9 ++-- .../handler/codec/MessageToMessageCodec.java | 18 +++---- ...rFinder.java => TypeParameterMatcher.java} | 54 ++++++++++++++----- .../ChannelInboundMessageHandlerAdapter.java | 9 ++-- .../ChannelOutboundMessageHandlerAdapter.java | 9 ++-- 5 files changed, 63 insertions(+), 36 deletions(-) rename common/src/main/java/io/netty/util/internal/{TypeParameterFinder.java => TypeParameterMatcher.java} (52%) diff --git a/codec/src/main/java/io/netty/handler/codec/ByteToMessageCodec.java b/codec/src/main/java/io/netty/handler/codec/ByteToMessageCodec.java index ffa62e6ad3..7d71c11543 100644 --- a/codec/src/main/java/io/netty/handler/codec/ByteToMessageCodec.java +++ b/codec/src/main/java/io/netty/handler/codec/ByteToMessageCodec.java @@ -22,12 +22,12 @@ import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundByteHandler; import io.netty.channel.ChannelOutboundMessageHandler; import io.netty.channel.ChannelPromise; -import io.netty.util.internal.TypeParameterFinder; +import io.netty.util.internal.TypeParameterMatcher; public abstract class ByteToMessageCodec extends ChannelDuplexHandler implements ChannelInboundByteHandler, ChannelOutboundMessageHandler { - private final Class acceptedOutboundMsgType; + private final TypeParameterMatcher outboundMsgMatcher; private final MessageToByteEncoder encoder = new MessageToByteEncoder() { @Override public boolean acceptOutboundMessage(Object msg) throws Exception { @@ -60,8 +60,7 @@ public abstract class ByteToMessageCodec extends ChannelDuplexHandler @SuppressWarnings("rawtypes") Class parameterizedHandlerType, int messageTypeParamIndex) { - acceptedOutboundMsgType = - TypeParameterFinder.findActualTypeParameter(this, parameterizedHandlerType, messageTypeParamIndex); + outboundMsgMatcher = TypeParameterMatcher.find(this, parameterizedHandlerType, messageTypeParamIndex); } @Override @@ -105,7 +104,7 @@ public abstract class ByteToMessageCodec extends ChannelDuplexHandler } public boolean acceptOutboundMessage(Object msg) throws Exception { - return acceptedOutboundMsgType.isInstance(msg); + return outboundMsgMatcher.match(msg); } protected abstract void encode(ChannelHandlerContext ctx, I msg, ByteBuf out) throws Exception; diff --git a/codec/src/main/java/io/netty/handler/codec/MessageToMessageCodec.java b/codec/src/main/java/io/netty/handler/codec/MessageToMessageCodec.java index 3d5622c3df..8c93207331 100644 --- a/codec/src/main/java/io/netty/handler/codec/MessageToMessageCodec.java +++ b/codec/src/main/java/io/netty/handler/codec/MessageToMessageCodec.java @@ -24,7 +24,7 @@ import io.netty.channel.ChannelInboundMessageHandlerAdapter; import io.netty.channel.ChannelOutboundMessageHandler; import io.netty.channel.ChannelOutboundMessageHandlerAdapter; import io.netty.channel.ChannelPromise; -import io.netty.util.internal.TypeParameterFinder; +import io.netty.util.internal.TypeParameterMatcher; /** * A Codec for on-the-fly encoding/decoding of message. @@ -97,12 +97,12 @@ public abstract class MessageToMessageCodec } }; - private final Class acceptedInboundMsgType; - private final Class acceptedOutboundMsgType; + private final TypeParameterMatcher inboundMsgMatcher; + private final TypeParameterMatcher outboundMsgMatcher; protected MessageToMessageCodec() { - acceptedInboundMsgType = TypeParameterFinder.findActualTypeParameter(this, MessageToMessageCodec.class, 0); - acceptedOutboundMsgType = TypeParameterFinder.findActualTypeParameter(this, MessageToMessageCodec.class, 1); + inboundMsgMatcher = TypeParameterMatcher.find(this, MessageToMessageCodec.class, 0); + outboundMsgMatcher = TypeParameterMatcher.find(this, MessageToMessageCodec.class, 1); } protected MessageToMessageCodec( @@ -113,9 +113,9 @@ public abstract class MessageToMessageCodec Class parameterizedOutboundHandlerType, int outboundMessageTypeParamIndex) { - acceptedInboundMsgType = TypeParameterFinder.findActualTypeParameter( + inboundMsgMatcher = TypeParameterMatcher.find( this, parameterizedInboundHandlerType, inboundMessageTypeParamIndex); - acceptedOutboundMsgType = TypeParameterFinder.findActualTypeParameter( + outboundMsgMatcher = TypeParameterMatcher.find( this, parameterizedOutboundHandlerType, outboundMessageTypeParamIndex); } @@ -158,7 +158,7 @@ public abstract class MessageToMessageCodec * @param msg the message */ public boolean acceptInboundMessage(Object msg) throws Exception { - return acceptedInboundMsgType.isInstance(msg); + return inboundMsgMatcher.match(msg); } /** @@ -167,7 +167,7 @@ public abstract class MessageToMessageCodec * @param msg the message */ public boolean acceptOutboundMessage(Object msg) throws Exception { - return acceptedOutboundMsgType.isInstance(msg); + return outboundMsgMatcher.match(msg); } protected abstract Object encode(ChannelHandlerContext ctx, OUTBOUND_IN msg) throws Exception; diff --git a/common/src/main/java/io/netty/util/internal/TypeParameterFinder.java b/common/src/main/java/io/netty/util/internal/TypeParameterMatcher.java similarity index 52% rename from common/src/main/java/io/netty/util/internal/TypeParameterFinder.java rename to common/src/main/java/io/netty/util/internal/TypeParameterMatcher.java index 5c7b93bbd7..3ee45b9219 100644 --- a/common/src/main/java/io/netty/util/internal/TypeParameterFinder.java +++ b/common/src/main/java/io/netty/util/internal/TypeParameterMatcher.java @@ -21,21 +21,31 @@ import java.lang.reflect.Type; import java.util.IdentityHashMap; import java.util.Map; -public final class TypeParameterFinder { +public abstract class TypeParameterMatcher { - private static final ThreadLocal, Class>> typeMap = new ThreadLocal, Class>>() { + private static final TypeParameterMatcher NOOP = new TypeParameterMatcher() { @Override - protected Map, Class> initialValue() { - return new IdentityHashMap, Class>(); + public boolean match(Object msg) { + return true; } }; - public static Class findActualTypeParameter( + private static final ThreadLocal, TypeParameterMatcher>> typeMap = + new ThreadLocal, TypeParameterMatcher>>() { + @Override + protected Map, TypeParameterMatcher> initialValue() { + return new IdentityHashMap, TypeParameterMatcher>(); + } + }; + + public static TypeParameterMatcher find( final Object object, final Class parameterizedSuperClass, final int typeParamIndex) { - final Map, Class> typeMap = TypeParameterFinder.typeMap.get(); + + final Map, TypeParameterMatcher> typeMap = TypeParameterMatcher.typeMap.get(); final Class thisClass = object.getClass(); - Class messageType = typeMap.get(thisClass); - if (messageType == null) { + + TypeParameterMatcher matcher = typeMap.get(thisClass); + if (matcher == null) { Class currentClass = thisClass; for (;;) { if (currentClass.getSuperclass() == parameterizedSuperClass) { @@ -45,17 +55,37 @@ public final class TypeParameterFinder { "cannot determine the type of the type parameter of " + thisClass.getSimpleName()); } - messageType = (Class) types[0]; + Class messageType = (Class) types[0]; + if (messageType == Object.class) { + matcher = NOOP; + } else { + matcher = new ReflectiveMatcher(messageType); + } break; } currentClass = currentClass.getSuperclass(); } - typeMap.put(thisClass, messageType); + typeMap.put(thisClass, matcher); } - return messageType; + return matcher; } - private TypeParameterFinder() { } + public abstract boolean match(Object msg); + + private static final class ReflectiveMatcher extends TypeParameterMatcher { + private final Class type; + + ReflectiveMatcher(Class type) { + this.type = type; + } + + @Override + public boolean match(Object msg) { + return type.isInstance(msg); + } + } + + TypeParameterMatcher() { } } diff --git a/transport/src/main/java/io/netty/channel/ChannelInboundMessageHandlerAdapter.java b/transport/src/main/java/io/netty/channel/ChannelInboundMessageHandlerAdapter.java index 8ad0732357..c4c785344f 100644 --- a/transport/src/main/java/io/netty/channel/ChannelInboundMessageHandlerAdapter.java +++ b/transport/src/main/java/io/netty/channel/ChannelInboundMessageHandlerAdapter.java @@ -17,7 +17,7 @@ package io.netty.channel; import io.netty.buffer.MessageBuf; import io.netty.buffer.Unpooled; -import io.netty.util.internal.TypeParameterFinder; +import io.netty.util.internal.TypeParameterMatcher; /** * {@link ChannelHandler} which handles inbound messages of a specific type. @@ -44,7 +44,7 @@ import io.netty.util.internal.TypeParameterFinder; public abstract class ChannelInboundMessageHandlerAdapter extends ChannelStateHandlerAdapter implements ChannelInboundMessageHandler { - private final Class acceptedMsgType; + private final TypeParameterMatcher msgMatcher; protected ChannelInboundMessageHandlerAdapter() { this(ChannelInboundMessageHandlerAdapter.class, 0); @@ -54,8 +54,7 @@ public abstract class ChannelInboundMessageHandlerAdapter @SuppressWarnings("rawtypes") Class parameterizedHandlerType, int messageTypeParamIndex) { - acceptedMsgType = TypeParameterFinder.findActualTypeParameter( - this, parameterizedHandlerType, messageTypeParamIndex); + msgMatcher = TypeParameterMatcher.find(this, parameterizedHandlerType, messageTypeParamIndex); } @Override @@ -126,7 +125,7 @@ public abstract class ChannelInboundMessageHandlerAdapter * @param msg the message */ public boolean acceptInboundMessage(Object msg) throws Exception { - return acceptedMsgType.isInstance(msg); + return msgMatcher.match(msg); } /** diff --git a/transport/src/main/java/io/netty/channel/ChannelOutboundMessageHandlerAdapter.java b/transport/src/main/java/io/netty/channel/ChannelOutboundMessageHandlerAdapter.java index bf6ac1971e..d8db9dc00d 100644 --- a/transport/src/main/java/io/netty/channel/ChannelOutboundMessageHandlerAdapter.java +++ b/transport/src/main/java/io/netty/channel/ChannelOutboundMessageHandlerAdapter.java @@ -17,7 +17,7 @@ package io.netty.channel; import io.netty.buffer.MessageBuf; import io.netty.buffer.Unpooled; -import io.netty.util.internal.TypeParameterFinder; +import io.netty.util.internal.TypeParameterMatcher; /** * Abstract base class which handles messages of a specific type. @@ -27,7 +27,7 @@ import io.netty.util.internal.TypeParameterFinder; public abstract class ChannelOutboundMessageHandlerAdapter extends ChannelOperationHandlerAdapter implements ChannelOutboundMessageHandler { - private final Class acceptedMsgType; + private final TypeParameterMatcher msgMatcher; protected ChannelOutboundMessageHandlerAdapter() { this(ChannelOutboundMessageHandlerAdapter.class, 0); @@ -37,8 +37,7 @@ public abstract class ChannelOutboundMessageHandlerAdapter @SuppressWarnings("rawtypes") Class parameterizedHandlerType, int messageTypeParamIndex) { - acceptedMsgType = TypeParameterFinder.findActualTypeParameter( - this, parameterizedHandlerType, messageTypeParamIndex); + msgMatcher = TypeParameterMatcher.find(this, parameterizedHandlerType, messageTypeParamIndex); } @Override @@ -57,7 +56,7 @@ public abstract class ChannelOutboundMessageHandlerAdapter * @param msg the message */ public boolean acceptOutboundMessage(Object msg) throws Exception { - return acceptedMsgType.isInstance(msg); + return msgMatcher.match(msg); } @Override