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
-~----------~----~----~----~------~----~------~--~---

Reply via email to