You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by us...@apache.org on 2011/12/18 18:36:21 UTC

svn commit: r1220464 - in /lucene/dev/branches/branch_3x: ./ lucene/ lucene/src/java/org/apache/lucene/util/ lucene/src/test/org/apache/lucene/util/ solr/

Author: uschindler
Date: Sun Dec 18 17:36:21 2011
New Revision: 1220464

URL: http://svn.apache.org/viewvc?rev=1220464&view=rev
Log:
Merged revision(s) 1220458 from lucene/dev/trunk:
LUCENE-3653:  Improve the sophisticated™ backwards layers (VirtualMethod) and instantiation cost in AttributeSource/AttributeFactory (new reflection cache using ConcurrentHashMap has lockless get)

Added:
    lucene/dev/branches/branch_3x/lucene/src/java/org/apache/lucene/util/WeakIdentityMap.java
      - copied unchanged from r1220458, lucene/dev/trunk/lucene/src/java/org/apache/lucene/util/WeakIdentityMap.java
    lucene/dev/branches/branch_3x/lucene/src/test/org/apache/lucene/util/TestWeakIdentityMap.java
      - copied unchanged from r1220458, lucene/dev/trunk/lucene/src/test/org/apache/lucene/util/TestWeakIdentityMap.java
Modified:
    lucene/dev/branches/branch_3x/   (props changed)
    lucene/dev/branches/branch_3x/lucene/   (props changed)
    lucene/dev/branches/branch_3x/lucene/CHANGES.txt
    lucene/dev/branches/branch_3x/lucene/NOTICE.txt
    lucene/dev/branches/branch_3x/lucene/src/java/org/apache/lucene/util/AttributeSource.java
    lucene/dev/branches/branch_3x/lucene/src/java/org/apache/lucene/util/VirtualMethod.java
    lucene/dev/branches/branch_3x/solr/   (props changed)
    lucene/dev/branches/branch_3x/solr/NOTICE.txt

Modified: lucene/dev/branches/branch_3x/lucene/CHANGES.txt
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_3x/lucene/CHANGES.txt?rev=1220464&r1=1220463&r2=1220464&view=diff
==============================================================================
--- lucene/dev/branches/branch_3x/lucene/CHANGES.txt (original)
+++ lucene/dev/branches/branch_3x/lucene/CHANGES.txt Sun Dec 18 17:36:21 2011
@@ -100,6 +100,12 @@ Bug fixes
   double precision and to compute age to be how long ago the searcher
   was replaced with a new searcher (Mike McCandless)
 
+Optimizations
+
+* LUCENE-3653: Improve concurrency in VirtualMethod and AttributeSource by
+  using a WeakIdentityMap based on a ConcurrentHashMap.  (Uwe Schindler,
+  Gerrit Jansen van Vuuren)
+
 Documentation
 
 * LUCENE-3597: Fixed incorrect grouping documentation. (Martijn van Groningen, Robert Muir)

Modified: lucene/dev/branches/branch_3x/lucene/NOTICE.txt
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_3x/lucene/NOTICE.txt?rev=1220464&r1=1220463&r2=1220464&view=diff
==============================================================================
--- lucene/dev/branches/branch_3x/lucene/NOTICE.txt (original)
+++ lucene/dev/branches/branch_3x/lucene/NOTICE.txt Sun Dec 18 17:36:21 2011
@@ -80,6 +80,9 @@ the same name. The implementation part i
 Lucene sorting code. In-place stable mergesort was borrowed from CGLIB,
 which is Apache-licensed.
 
+The class org.apache.lucene.util.WeakIdentityMap was derived from
+the Apache CXF project and is Apache License 2.0.
+
 The Google Code Prettify is Apache License 2.0.
 See http://code.google.com/p/google-code-prettify/
 

Modified: lucene/dev/branches/branch_3x/lucene/src/java/org/apache/lucene/util/AttributeSource.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_3x/lucene/src/java/org/apache/lucene/util/AttributeSource.java?rev=1220464&r1=1220463&r2=1220464&view=diff
==============================================================================
--- lucene/dev/branches/branch_3x/lucene/src/java/org/apache/lucene/util/AttributeSource.java (original)
+++ lucene/dev/branches/branch_3x/lucene/src/java/org/apache/lucene/util/AttributeSource.java Sun Dec 18 17:36:21 2011
@@ -22,7 +22,6 @@ import java.util.Collections;
 import java.util.NoSuchElementException;
 import java.util.Iterator;
 import java.util.LinkedHashMap;
-import java.util.WeakHashMap;
 import java.util.LinkedList;
 import java.util.Map;
 import java.util.Map.Entry;
@@ -57,8 +56,8 @@ public class AttributeSource {
     public static final AttributeFactory DEFAULT_ATTRIBUTE_FACTORY = new DefaultAttributeFactory();
     
     private static final class DefaultAttributeFactory extends AttributeFactory {
-      private static final WeakHashMap<Class<? extends Attribute>, WeakReference<Class<? extends AttributeImpl>>> attClassImplMap =
-        new WeakHashMap<Class<? extends Attribute>, WeakReference<Class<? extends AttributeImpl>>>();
+      private static final WeakIdentityMap<Class<? extends Attribute>, WeakReference<Class<? extends AttributeImpl>>> attClassImplMap =
+        WeakIdentityMap.newConcurrentHashMap();
       
       private DefaultAttributeFactory() {}
     
@@ -74,29 +73,28 @@ public class AttributeSource {
       }
       
       private static Class<? extends AttributeImpl> getClassForInterface(Class<? extends Attribute> attClass) {
-        synchronized(attClassImplMap) {
-          final WeakReference<Class<? extends AttributeImpl>> ref = attClassImplMap.get(attClass);
-          Class<? extends AttributeImpl> clazz = (ref == null) ? null : ref.get();
-          if (clazz == null) {
-            try {
-              // TODO: Remove when TermAttribute is removed!
-              // This is a "sophisticated backwards compatibility hack"
-              // (enforce new impl for this deprecated att):
-              if (TermAttribute.class.equals(attClass)) {
-                clazz = CharTermAttributeImpl.class;
-              } else {
-                clazz = Class.forName(attClass.getName() + "Impl", true, attClass.getClassLoader())
-                  .asSubclass(AttributeImpl.class);
-              }
-              attClassImplMap.put(attClass,
-                new WeakReference<Class<? extends AttributeImpl>>(clazz)
-              );
-            } catch (ClassNotFoundException e) {
-              throw new IllegalArgumentException("Could not find implementing class for " + attClass.getName());
+        final WeakReference<Class<? extends AttributeImpl>> ref = attClassImplMap.get(attClass);
+        Class<? extends AttributeImpl> clazz = (ref == null) ? null : ref.get();
+        if (clazz == null) {
+          // we have the slight chance that another thread may do the same, but who cares?
+          try {
+            // TODO: Remove when TermAttribute is removed!
+            // This is a "sophisticated backwards compatibility hack"
+            // (enforce new impl for this deprecated att):
+            if (TermAttribute.class.equals(attClass)) {
+              clazz = CharTermAttributeImpl.class;
+            } else {
+              clazz = Class.forName(attClass.getName() + "Impl", true, attClass.getClassLoader())
+                .asSubclass(AttributeImpl.class);
             }
+            attClassImplMap.put(attClass,
+              new WeakReference<Class<? extends AttributeImpl>>(clazz)
+            );
+          } catch (ClassNotFoundException e) {
+            throw new IllegalArgumentException("Could not find implementing class for " + attClass.getName());
           }
-          return clazz;
         }
+        return clazz;
       }
     }
   }
@@ -207,30 +205,28 @@ public class AttributeSource {
   }
   
   /** a cache that stores all interfaces for known implementation classes for performance (slow reflection) */
-  private static final WeakHashMap<Class<? extends AttributeImpl>,LinkedList<WeakReference<Class<? extends Attribute>>>> knownImplClasses =
-    new WeakHashMap<Class<? extends AttributeImpl>,LinkedList<WeakReference<Class<? extends Attribute>>>>();
+  private static final WeakIdentityMap<Class<? extends AttributeImpl>,LinkedList<WeakReference<Class<? extends Attribute>>>> knownImplClasses =
+    WeakIdentityMap.newConcurrentHashMap();
   
   static LinkedList<WeakReference<Class<? extends Attribute>>> getAttributeInterfaces(final Class<? extends AttributeImpl> clazz) {
-    synchronized(knownImplClasses) {
-      LinkedList<WeakReference<Class<? extends Attribute>>> foundInterfaces = knownImplClasses.get(clazz);
-      if (foundInterfaces == null) {
-        // we have a strong reference to the class instance holding all interfaces in the list (parameter "att"),
-        // so all WeakReferences are never evicted by GC
-        knownImplClasses.put(clazz, foundInterfaces = new LinkedList<WeakReference<Class<? extends Attribute>>>());
-        // find all interfaces that this attribute instance implements
-        // and that extend the Attribute interface
-        Class<?> actClazz = clazz;
-        do {
-          for (Class<?> curInterface : actClazz.getInterfaces()) {
-            if (curInterface != Attribute.class && Attribute.class.isAssignableFrom(curInterface)) {
-              foundInterfaces.add(new WeakReference<Class<? extends Attribute>>(curInterface.asSubclass(Attribute.class)));
-            }
+    LinkedList<WeakReference<Class<? extends Attribute>>> foundInterfaces = knownImplClasses.get(clazz);
+    if (foundInterfaces == null) {
+      // we have the slight chance that another thread may do the same, but who cares?
+      foundInterfaces = new LinkedList<WeakReference<Class<? extends Attribute>>>();
+      // find all interfaces that this attribute instance implements
+      // and that extend the Attribute interface
+      Class<?> actClazz = clazz;
+      do {
+        for (Class<?> curInterface : actClazz.getInterfaces()) {
+          if (curInterface != Attribute.class && Attribute.class.isAssignableFrom(curInterface)) {
+            foundInterfaces.add(new WeakReference<Class<? extends Attribute>>(curInterface.asSubclass(Attribute.class)));
           }
-          actClazz = actClazz.getSuperclass();
-        } while (actClazz != null);
-      }
-      return foundInterfaces;
+        }
+        actClazz = actClazz.getSuperclass();
+      } while (actClazz != null);
+      knownImplClasses.put(clazz, foundInterfaces);
     }
+    return foundInterfaces;
   }
   
   /** <b>Expert:</b> Adds a custom AttributeImpl instance with one or more Attribute interfaces.

Modified: lucene/dev/branches/branch_3x/lucene/src/java/org/apache/lucene/util/VirtualMethod.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_3x/lucene/src/java/org/apache/lucene/util/VirtualMethod.java?rev=1220464&r1=1220463&r2=1220464&view=diff
==============================================================================
--- lucene/dev/branches/branch_3x/lucene/src/java/org/apache/lucene/util/VirtualMethod.java (original)
+++ lucene/dev/branches/branch_3x/lucene/src/java/org/apache/lucene/util/VirtualMethod.java Sun Dec 18 17:36:21 2011
@@ -20,7 +20,6 @@ package org.apache.lucene.util;
 import java.lang.reflect.Method;
 import java.util.Collections;
 import java.util.HashSet;
-import java.util.WeakHashMap;
 import java.util.Set;
 
 /**
@@ -64,8 +63,7 @@ public final class VirtualMethod<C> {
   private final Class<C> baseClass;
   private final String method;
   private final Class<?>[] parameters;
-  private final WeakHashMap<Class<? extends C>, Integer> cache =
-    new WeakHashMap<Class<? extends C>, Integer>();
+  private final WeakIdentityMap<Class<? extends C>, Integer> cache = WeakIdentityMap.newConcurrentHashMap();
 
   /**
    * Creates a new instance for the given {@code baseClass} and method declaration.
@@ -93,9 +91,10 @@ public final class VirtualMethod<C> {
    * in the inheritance path between {@code baseClass} and the given subclass {@code subclazz}.
    * @return 0 iff not overridden, else the distance to the base class
    */
-  public synchronized int getImplementationDistance(final Class<? extends C> subclazz) {
+  public int getImplementationDistance(final Class<? extends C> subclazz) {
     Integer distance = cache.get(subclazz);
     if (distance == null) {
+      // we have the slight chance that another thread may do the same, but who cares?
       cache.put(subclazz, distance = Integer.valueOf(reflectImplementationDistance(subclazz)));
     }
     return distance.intValue();

Modified: lucene/dev/branches/branch_3x/solr/NOTICE.txt
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_3x/solr/NOTICE.txt?rev=1220464&r1=1220463&r2=1220464&view=diff
==============================================================================
--- lucene/dev/branches/branch_3x/solr/NOTICE.txt (original)
+++ lucene/dev/branches/branch_3x/solr/NOTICE.txt Sun Dec 18 17:36:21 2011
@@ -60,6 +60,9 @@ the same name. The implementation part i
 Lucene sorting code. In-place stable mergesort was borrowed from CGLIB,
 which is Apache-licensed.
 
+The class org.apache.lucene.util.WeakIdentityMap was derived from
+the Apache CXF project and is Apache License 2.0.
+
 The Google Code Prettify is Apache License 2.0.
 See http://code.google.com/p/google-code-prettify/