Author: limpbizkit
Date: Tue May 5 18:02:14 2009
New Revision: 939
Modified:
trunk/src/com/google/inject/ConstructorInjector.java
trunk/src/com/google/inject/ConstructorInjectorStore.java
trunk/src/com/google/inject/InjectorImpl.java
trunk/src/com/google/inject/MembersInjectorImpl.java
trunk/src/com/google/inject/SingleMethodInjector.java
trunk/src/com/google/inject/SingleParameterInjector.java
trunk/src/com/google/inject/internal/Errors.java
trunk/src/com/google/inject/internal/InternalContext.java
Log:
Some low-hanging fruit optimizations.
These make the code worse, but they make performance significantly better
so they're justified.
These changes result in 55% more throughput on the PerformanceComparison
benchmark. We're back to beating Guice 1.0 on that benchmark (by 8% in one
measurement).
Modified: trunk/src/com/google/inject/ConstructorInjector.java
==============================================================================
--- trunk/src/com/google/inject/ConstructorInjector.java (original)
+++ trunk/src/com/google/inject/ConstructorInjector.java Tue May 5
18:02:14 2009
@@ -19,7 +19,6 @@
import com.google.inject.internal.ConstructionContext;
import com.google.inject.internal.Errors;
import com.google.inject.internal.ErrorsException;
-import com.google.inject.internal.ImmutableList;
import com.google.inject.internal.ImmutableSet;
import com.google.inject.internal.InternalContext;
import com.google.inject.spi.InjectionPoint;
@@ -34,13 +33,13 @@
class ConstructorInjector<T> {
private final ImmutableSet<InjectionPoint> injectableMembers;
- private final ImmutableList<SingleParameterInjector<?>>
parameterInjectors;
+ private final SingleParameterInjector<?>[] parameterInjectors;
private final ConstructionProxy<T> constructionProxy;
private final MembersInjectorImpl<T> membersInjector;
ConstructorInjector(ImmutableSet<InjectionPoint> injectableMembers,
ConstructionProxy<T> constructionProxy,
- ImmutableList<SingleParameterInjector<?>> parameterInjectors,
+ SingleParameterInjector<?>[] parameterInjectors,
MembersInjectorImpl<T> membersInjector)
throws ErrorsException {
this.injectableMembers = injectableMembers;
Modified: trunk/src/com/google/inject/ConstructorInjectorStore.java
==============================================================================
--- trunk/src/com/google/inject/ConstructorInjectorStore.java (original)
+++ trunk/src/com/google/inject/ConstructorInjectorStore.java Tue May 5
18:02:14 2009
@@ -64,7 +64,7 @@
throw errors.toException();
}
- ImmutableList<SingleParameterInjector<?>> constructorParameterInjectors
+ SingleParameterInjector<?>[] constructorParameterInjectors
=
injector.getParametersInjectors(injectionPoint.getDependencies(), errors);
MembersInjectorImpl<T> membersInjector =
injector.membersInjectorStore.get(type, errors);
Modified: trunk/src/com/google/inject/InjectorImpl.java
==============================================================================
--- trunk/src/com/google/inject/InjectorImpl.java (original)
+++ trunk/src/com/google/inject/InjectorImpl.java Tue May 5 18:02:14 2009
@@ -79,9 +79,9 @@
if (parent != null) {
localContext = parent.localContext;
} else {
- localContext = new ThreadLocal<InternalContext[]>() {
- protected InternalContext[] initialValue() {
- return new InternalContext[1];
+ localContext = new ThreadLocal<InternalContext>() {
+ protected InternalContext initialValue() {
+ return new InternalContext();
}
};
}
@@ -681,7 +681,7 @@
/**
* Returns parameter injectors, or {...@code null} if there are no
parameters.
*/
- ImmutableList<SingleParameterInjector<?>> getParametersInjectors(
+ SingleParameterInjector<?>[] getParametersInjectors(
List<Dependency<?>> parameters, Errors errors) throws
ErrorsException {
if (parameters.isEmpty()) {
return null;
@@ -699,7 +699,7 @@
}
errors.throwIfNewErrors(numErrorsBefore);
- return ImmutableList.of(result);
+ return result;
}
<T> SingleParameterInjector<T> createParameterInjector(final
Dependency<T> dependency,
@@ -793,23 +793,16 @@
return getProvider(type).get();
}
- final ThreadLocal<InternalContext[]> localContext;
+ final ThreadLocal<InternalContext> localContext;
/** Looks up thread local context. Creates (and removes) a new context
if necessary. */
<T> T callInContext(ContextualCallable<T> callable) throws
ErrorsException {
- InternalContext[] reference = localContext.get();
- if (reference[0] == null) {
- reference[0] = new InternalContext();
- try {
- return callable.call(reference[0]);
- } finally {
- // Only remove the context if this call created it.
- localContext.remove();
- }
- }
- else {
- // Someone else will clean up this context.
- return callable.call(reference[0]);
+ InternalContext reference = localContext.get();
+ reference.acquire();
+ try {
+ return callable.call(reference);
+ } finally {
+ reference.release();
}
}
Modified: trunk/src/com/google/inject/MembersInjectorImpl.java
==============================================================================
--- trunk/src/com/google/inject/MembersInjectorImpl.java (original)
+++ trunk/src/com/google/inject/MembersInjectorImpl.java Tue May 5
18:02:14 2009
@@ -94,11 +94,14 @@
}
void injectMembers(T t, Errors errors, InternalContext context) {
- for (SingleMemberInjector injector : memberInjectors) {
- injector.inject(errors, context, t);
+ // optimization: use manual for/each to save allocating an iterator
here
+ for (int i = 0, size = memberInjectors.size(); i < size; i++) {
+ memberInjectors.get(i).inject(errors, context, t);
}
- for (MembersInjector<? super T> userMembersInjector :
userMembersInjectors) {
+ // optimization: use manual for/each to save allocating an iterator
here
+ for (int i = 0, size = userMembersInjectors.size(); i < size; i++) {
+ MembersInjector<? super T> userMembersInjector =
userMembersInjectors.get(i);
try {
userMembersInjector.injectMembers(t);
} catch (RuntimeException e) {
Modified: trunk/src/com/google/inject/SingleMethodInjector.java
==============================================================================
--- trunk/src/com/google/inject/SingleMethodInjector.java (original)
+++ trunk/src/com/google/inject/SingleMethodInjector.java Tue May 5
18:02:14 2009
@@ -21,7 +21,6 @@
import com.google.inject.internal.BytecodeGen.Visibility;
import com.google.inject.internal.Errors;
import com.google.inject.internal.ErrorsException;
-import com.google.inject.internal.ImmutableList;
import com.google.inject.internal.InternalContext;
import com.google.inject.spi.InjectionPoint;
import java.lang.reflect.InvocationTargetException;
@@ -33,7 +32,7 @@
*/
class SingleMethodInjector implements SingleMemberInjector {
final MethodInvoker methodInvoker;
- final ImmutableList<SingleParameterInjector<?>> parameterInjectors;
+ final SingleParameterInjector<?>[] parameterInjectors;
final InjectionPoint injectionPoint;
public SingleMethodInjector(InjectorImpl injector, InjectionPoint
injectionPoint, Errors errors)
Modified: trunk/src/com/google/inject/SingleParameterInjector.java
==============================================================================
--- trunk/src/com/google/inject/SingleParameterInjector.java (original)
+++ trunk/src/com/google/inject/SingleParameterInjector.java Tue May 5
18:02:14 2009
@@ -21,7 +21,6 @@
import com.google.inject.internal.InternalContext;
import com.google.inject.internal.InternalFactory;
import com.google.inject.spi.Dependency;
-import java.util.List;
/**
* Resolves a single parameter, to be used in a constructor or method
invocation.
@@ -50,18 +49,21 @@
* Returns an array of parameter values.
*/
static Object[] getAll(Errors errors, InternalContext context,
- List<SingleParameterInjector<?>> parameterInjectors) throws
ErrorsException {
+ SingleParameterInjector<?>[] parameterInjectors) throws
ErrorsException {
if (parameterInjectors == null) {
return NO_ARGUMENTS;
}
int numErrorsBefore = errors.size();
- Object[] parameters = new Object[parameterInjectors.size()];
- int i = 0;
- for (SingleParameterInjector<?> parameterInjector :
parameterInjectors) {
+ int size = parameterInjectors.length;
+ Object[] parameters = new Object[size];
+
+ // optimization: use manual for/each to save allocating an iterator
here
+ for (int i = 0; i < size; i++) {
+ SingleParameterInjector<?> parameterInjector = parameterInjectors[i];
try {
- parameters[i++] = parameterInjector.inject(errors, context);
+ parameters[i] = parameterInjector.inject(errors, context);
} catch (ErrorsException e) {
errors.merge(e.getErrors());
}
Modified: trunk/src/com/google/inject/internal/Errors.java
==============================================================================
--- trunk/src/com/google/inject/internal/Errors.java (original)
+++ trunk/src/com/google/inject/internal/Errors.java Tue May 5 18:02:14
2009
@@ -64,24 +64,40 @@
private static final boolean allowNullsBadBadBad
= "I'm a bad
hack".equals(System.getProperty("guice.allow.nulls.bad.bad.bad"));
- private final List<Message> errors;
+ /**
+ * The root errors object. Used to access the list of error messages.
+ */
+ private final Errors root;
+
+ /**
+ * The parent errors object. Used to obtain the chain of source objects.
+ */
private final Errors parent;
+
+ /**
+ * The leaf source for errors added here.
+ */
private final Object source;
+ /**
+ * null unless (root == this) and error messages exist. Never an empty
list.
+ */
+ private List<Message> errors; // lazy, use getErrorsForAdd()
+
public Errors() {
- this.errors = Lists.newArrayList();
+ this.root = this;
this.parent = null;
this.source = SourceProvider.UNKNOWN_SOURCE;
}
public Errors(Object source) {
- this.errors = Lists.newArrayList();
+ this.root = this;
this.parent = null;
this.source = source;
}
private Errors(Errors parent, Object source) {
- this.errors = parent.errors;
+ this.root = parent.root;
this.parent = parent;
this.source = source;
}
@@ -367,17 +383,17 @@
public Errors merge(Collection<Message> messages) {
for (Message message : messages) {
- errors.add(merge(message));
+ addMessage(merge(message));
}
return this;
}
public Errors merge(Errors moreErrors) {
- if (moreErrors.errors == errors) {
+ if (moreErrors.root == root || moreErrors.root.errors == null) {
return this;
}
- merge(moreErrors.errors);
+ merge(moreErrors.root.errors);
return this;
}
@@ -404,7 +420,7 @@
}
public boolean hasErrors() {
- return !errors.isEmpty();
+ return root.errors != null;
}
public Errors addMessage(String messageFormat, Object... arguments) {
@@ -418,7 +434,10 @@
}
public Errors addMessage(Message message) {
- errors.add(message);
+ if (root.errors == null) {
+ root.errors = Lists.newArrayList();
+ }
+ root.errors.add(message);
return this;
}
@@ -430,8 +449,11 @@
}
public List<Message> getMessages() {
- List<Message> result = Lists.newArrayList(errors);
+ if (root.errors == null) {
+ return ImmutableList.of();
+ }
+ List<Message> result = Lists.newArrayList(root.errors);
Collections.sort(result, new Comparator<Message>() {
public int compare(Message a, Message b) {
return a.getSource().compareTo(b.getSource());
@@ -520,7 +542,7 @@
}
public int size() {
- return errors.size();
+ return root.errors == null ? 0 : root.errors.size();
}
private static abstract class Converter<T> {
Modified: trunk/src/com/google/inject/internal/InternalContext.java
==============================================================================
--- trunk/src/com/google/inject/internal/InternalContext.java (original)
+++ trunk/src/com/google/inject/internal/InternalContext.java Tue May 5
18:02:14 2009
@@ -16,8 +16,8 @@
package com.google.inject.internal;
+import static com.google.inject.internal.Preconditions.checkState;
import com.google.inject.spi.Dependency;
-import java.util.HashMap;
import java.util.Map;
/**
@@ -28,25 +28,31 @@
*/
public final class InternalContext {
- private Map<Object, ConstructionContext<?>> constructionContexts;
+ private Map<Object, ConstructionContext<?>> constructionContexts =
Maps.newHashMap();
private Dependency dependency;
+ private int acquired = 0;
@SuppressWarnings("unchecked")
public <T> ConstructionContext<T> getConstructionContext(Object key) {
- if (constructionContexts == null) {
- constructionContexts = new HashMap<Object, ConstructionContext<?>>();
- ConstructionContext<T> constructionContext = new
ConstructionContext<T>();
+ ConstructionContext<T> constructionContext
+ = (ConstructionContext<T>) constructionContexts.get(key);
+ if (constructionContext == null) {
+ constructionContext = new ConstructionContext<T>();
constructionContexts.put(key, constructionContext);
- return constructionContext;
}
- else {
- ConstructionContext<T> constructionContext
- = (ConstructionContext<T>) constructionContexts.get(key);
- if (constructionContext == null) {
- constructionContext = new ConstructionContext<T>();
- constructionContexts.put(key, constructionContext);
- }
- return constructionContext;
+ return constructionContext;
+ }
+
+ public void acquire() {
+ acquired++;
+ }
+
+ public void release() {
+ checkState(acquired > 0);
+ acquired--;
+ if (acquired == 0) {
+ constructionContexts.clear();
+ dependency = null;
}
}
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups
"google-guice-dev" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/google-guice-dev?hl=en
-~----------~----~----~----~------~----~------~--~---