Some small optimizations. Getting sources still takes the most time of all (~40%), followed by reflective access on the methods and fields of classes. There's not much we can do here, aside from the often-suggested compile-time code-gen DI.
git-svn-id: https://google-guice.googlecode.com/svn/trunk@1050 d779f126-a31b-0410-b53b-1d3aecad763e
diff --git a/src/com/google/inject/Key.java b/src/com/google/inject/Key.java
index 9cfdb77..2422945 100644
--- a/src/com/google/inject/Key.java
+++ b/src/com/google/inject/Key.java
@@ -20,7 +20,6 @@
import com.google.inject.internal.MoreTypes;
import static com.google.inject.internal.Preconditions.checkArgument;
import static com.google.inject.internal.Preconditions.checkNotNull;
-import com.google.inject.internal.ToStringBuilder;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
@@ -195,10 +194,7 @@
}
@Override public final String toString() {
- return new ToStringBuilder(Key.class)
- .add("type", typeLiteral)
- .add("annotation", annotationStrategy)
- .toString();
+ return "Key[type=" + typeLiteral + ", annotation=" + annotationStrategy + "]";
}
/**
@@ -296,7 +292,7 @@
* Returns a new key of the specified type with the same annotation as this
* key.
*/
- <T> Key<T> ofType(TypeLiteral<T> type) {
+ public <T> Key<T> ofType(TypeLiteral<T> type) {
return new Key<T>(type, annotationStrategy);
}
diff --git a/src/com/google/inject/TypeLiteral.java b/src/com/google/inject/TypeLiteral.java
index 8036113..27dc48b 100644
--- a/src/com/google/inject/TypeLiteral.java
+++ b/src/com/google/inject/TypeLiteral.java
@@ -82,7 +82,7 @@
protected TypeLiteral() {
this.type = getSuperclassTypeParameter(getClass());
this.rawType = (Class<? super T>) MoreTypes.getRawType(type);
- this.hashCode = MoreTypes.hashCode(type);
+ this.hashCode = type.hashCode();
}
/**
@@ -92,7 +92,7 @@
TypeLiteral(Type type) {
this.type = canonicalize(checkNotNull(type, "type"));
this.rawType = (Class<? super T>) MoreTypes.getRawType(this.type);
- this.hashCode = MoreTypes.hashCode(this.type);
+ this.hashCode = this.type.hashCode();
}
/**
@@ -151,7 +151,7 @@
}
@Override public final String toString() {
- return MoreTypes.toString(type);
+ return MoreTypes.typeToString(type);
}
/**
diff --git a/src/com/google/inject/internal/InjectorImpl.java b/src/com/google/inject/internal/InjectorImpl.java
index 7938bab..98f3808 100644
--- a/src/com/google/inject/internal/InjectorImpl.java
+++ b/src/com/google/inject/internal/InjectorImpl.java
@@ -54,6 +54,8 @@
* @see InjectorBuilder
*/
final class InjectorImpl implements Injector, Lookups {
+ public static final TypeLiteral<String> STRING_TYPE = TypeLiteral.get(String.class);
+
final State state;
final InjectorImpl parent;
final BindingsMultimap bindingsMultimap = new BindingsMultimap();
@@ -271,7 +273,7 @@
private <T> BindingImpl<T> convertConstantStringBinding(Key<T> key, Errors errors)
throws ErrorsException {
// Find a constant string binding.
- Key<String> stringKey = key.ofType(String.class);
+ Key<String> stringKey = key.ofType(STRING_TYPE);
BindingImpl<String> stringBinding = state.getExplicitBinding(stringKey);
if (stringBinding == null || !stringBinding.isConstant()) {
return null;
diff --git a/src/com/google/inject/internal/MoreTypes.java b/src/com/google/inject/internal/MoreTypes.java
index 3f4b771..78f60ef 100644
--- a/src/com/google/inject/internal/MoreTypes.java
+++ b/src/com/google/inject/internal/MoreTypes.java
@@ -105,9 +105,11 @@
* type is {@link Serializable}.
*/
public static Type canonicalize(Type type) {
- if (type instanceof ParameterizedTypeImpl
- || type instanceof GenericArrayTypeImpl
- || type instanceof WildcardTypeImpl) {
+ if (type instanceof Class) {
+ Class<?> c = (Class<?>) type;
+ return c.isArray() ? new GenericArrayTypeImpl(canonicalize(c.getComponentType())) : c;
+
+ } else if (type instanceof CompositeType) {
return type;
} else if (type instanceof ParameterizedType) {
@@ -119,10 +121,6 @@
GenericArrayType g = (GenericArrayType) type;
return new GenericArrayTypeImpl(g.getGenericComponentType());
- } else if (type instanceof Class && ((Class<?>) type).isArray()) {
- Class<?> c = (Class<?>) type;
- return new GenericArrayTypeImpl(c.getComponentType());
-
} else if (type instanceof WildcardType) {
WildcardType w = (WildcardType) type;
return new WildcardTypeImpl(w.getUpperBounds(), w.getLowerBounds());
@@ -222,86 +220,12 @@
}
}
- /**
- * Returns the hashCode of {@code type}.
- */
- public static int hashCode(Type type) {
- if (type instanceof Class) {
- // Class specifies hashCode().
- return type.hashCode();
-
- } else if (type instanceof ParameterizedType) {
- ParameterizedType p = (ParameterizedType) type;
- return Arrays.hashCode(p.getActualTypeArguments())
- ^ p.getRawType().hashCode()
- ^ hashCodeOrZero(p.getOwnerType());
-
- } else if (type instanceof GenericArrayType) {
- return hashCode(((GenericArrayType) type).getGenericComponentType());
-
- } else if (type instanceof WildcardType) {
- WildcardType w = (WildcardType) type;
- return Arrays.hashCode(w.getLowerBounds()) ^ Arrays.hashCode(w.getUpperBounds());
-
- } else {
- // This isn't a type we support. Probably a type variable
- return hashCodeOrZero(type);
- }
- }
-
private static int hashCodeOrZero(Object o) {
return o != null ? o.hashCode() : 0;
}
- public static String toString(Type type) {
- if (type instanceof Class<?>) {
- return ((Class) type).getName();
-
- } else if (type instanceof ParameterizedType) {
- ParameterizedType parameterizedType = (ParameterizedType) type;
- Type[] arguments = parameterizedType.getActualTypeArguments();
- Type ownerType = parameterizedType.getOwnerType();
- StringBuilder stringBuilder = new StringBuilder();
- if (ownerType != null) {
- stringBuilder.append(toString(ownerType)).append(".");
- }
- stringBuilder.append(toString(parameterizedType.getRawType()));
- if (arguments.length > 0) {
- stringBuilder
- .append("<")
- .append(toString(arguments[0]));
- for (int i = 1; i < arguments.length; i++) {
- stringBuilder.append(", ").append(toString(arguments[i]));
- }
- }
- return stringBuilder.append(">").toString();
-
- } else if (type instanceof GenericArrayType) {
- return toString(((GenericArrayType) type).getGenericComponentType()) + "[]";
-
- } else if (type instanceof WildcardType) {
- WildcardType wildcardType = (WildcardType) type;
- Type[] lowerBounds = wildcardType.getLowerBounds();
- Type[] upperBounds = wildcardType.getUpperBounds();
-
- if (upperBounds.length != 1 || lowerBounds.length > 1) {
- throw new UnsupportedOperationException("Unsupported wildcard type " + type);
- }
-
- if (lowerBounds.length == 1) {
- if (upperBounds[0] != Object.class) {
- throw new UnsupportedOperationException("Unsupported wildcard type " + type);
- }
- return "? super " + toString(lowerBounds[0]);
- } else if (upperBounds[0] == Object.class) {
- return "?";
- } else {
- return "? extends " + toString(upperBounds[0]);
- }
-
- } else {
- return type.toString();
- }
+ public static String typeToString(Type type) {
+ return type instanceof Class ? ((Class) type).getName() : type.toString();
}
/**
@@ -508,11 +432,26 @@
}
@Override public int hashCode() {
- return MoreTypes.hashCode(this);
+ return Arrays.hashCode(typeArguments)
+ ^ rawType.hashCode()
+ ^ hashCodeOrZero(ownerType);
}
@Override public String toString() {
- return MoreTypes.toString(this);
+ StringBuilder stringBuilder = new StringBuilder(30 * (typeArguments.length + 1));
+ if (ownerType != null) {
+ stringBuilder.append(typeToString(ownerType)).append(".");
+ }
+ stringBuilder.append(typeToString(rawType));
+ if (typeArguments.length > 0) {
+ stringBuilder
+ .append("<")
+ .append(typeToString(typeArguments[0]));
+ for (int i = 1; i < typeArguments.length; i++) {
+ stringBuilder.append(", ").append(typeToString(typeArguments[i]));
+ }
+ }
+ return stringBuilder.append(">").toString();
}
private static final long serialVersionUID = 0;
@@ -540,11 +479,11 @@
}
@Override public int hashCode() {
- return MoreTypes.hashCode(this);
+ return componentType.hashCode();
}
@Override public String toString() {
- return MoreTypes.toString(this);
+ return typeToString(componentType) + "[]";
}
private static final long serialVersionUID = 0;
@@ -597,11 +536,19 @@
}
@Override public int hashCode() {
- return MoreTypes.hashCode(this);
+ // this equals Arrays.hashCode(getLowerBounds()) ^ Arrays.hashCode(getUpperBounds());
+ return (lowerBound != null ? 31 + lowerBound.hashCode() : 1)
+ ^ (31 + upperBound.hashCode());
}
@Override public String toString() {
- return MoreTypes.toString(this);
+ if (lowerBound != null) {
+ return "? super " + typeToString(lowerBound);
+ } else if (upperBound == Object.class) {
+ return "?";
+ } else {
+ return "? extends " + typeToString(upperBound);
+ }
}
private static final long serialVersionUID = 0;
diff --git a/src/com/google/inject/internal/WeakKeySet.java b/src/com/google/inject/internal/WeakKeySet.java
index 32e0e93..58a9c2c 100644
--- a/src/com/google/inject/internal/WeakKeySet.java
+++ b/src/com/google/inject/internal/WeakKeySet.java
@@ -33,13 +33,18 @@
* keys whose class names are equal but class loaders are different. This shouldn't be an issue
* in practice.
*/
- private Set<String> backingSet = Sets.newHashSet();
+ private Set<String> backingSet;
public boolean add(Key<?> key) {
+ if (backingSet == null) {
+ backingSet = Sets.newHashSet();
+ }
return backingSet.add(key.toString());
}
public boolean contains(Object o) {
- return o instanceof Key && backingSet.contains(o.toString());
+ // avoid calling key.toString() if the backing set is empty. toString is expensive in aggregate,
+ // and most WeakKeySets are empty in practice (because they're used by top-level injectors)
+ return backingSet != null && o instanceof Key && backingSet.contains(o.toString());
}
}
diff --git a/test/com/google/inject/util/TypesTest.java b/test/com/google/inject/util/TypesTest.java
index 9168021..546f061 100644
--- a/test/com/google/inject/util/TypesTest.java
+++ b/test/com/google/inject/util/TypesTest.java
@@ -153,14 +153,14 @@
}
public void testToString() {
- Assert.assertEquals("java.lang.String", MoreTypes.toString(String.class));
- assertEquals("java.lang.String[][]", MoreTypes.toString(stringArray));
+ Assert.assertEquals("java.lang.String", MoreTypes.typeToString(String.class));
+ assertEquals("java.lang.String[][]", MoreTypes.typeToString(stringArray));
assertEquals("java.util.Map<java.lang.String, java.lang.Integer>",
- MoreTypes.toString(mapStringInteger));
+ MoreTypes.typeToString(mapStringInteger));
assertEquals("java.util.List<java.lang.String[][]>",
- MoreTypes.toString(listStringArray));
+ MoreTypes.typeToString(listStringArray));
assertEquals(innerFloatDouble.toString(),
- MoreTypes.toString(innerFloatDouble));
+ MoreTypes.typeToString(innerFloatDouble));
}
static class Owning<A> {}