hadoop-common-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From cutt...@apache.org
Subject svn commit: r510188 - in /lucene/hadoop/trunk: CHANGES.txt src/java/org/apache/hadoop/util/ReflectionUtils.java src/test/org/apache/hadoop/util/ src/test/org/apache/hadoop/util/TestReflectionUtils.java
Date Wed, 21 Feb 2007 20:32:52 GMT
Author: cutting
Date: Wed Feb 21 12:32:51 2007
New Revision: 510188

URL: http://svn.apache.org/viewvc?view=rev&rev=510188
Log:
HADOOP-1017.  Cache constructors.  Contributed by Ron Bodkin.

Added:
    lucene/hadoop/trunk/src/test/org/apache/hadoop/util/
    lucene/hadoop/trunk/src/test/org/apache/hadoop/util/TestReflectionUtils.java
Modified:
    lucene/hadoop/trunk/CHANGES.txt
    lucene/hadoop/trunk/src/java/org/apache/hadoop/util/ReflectionUtils.java

Modified: lucene/hadoop/trunk/CHANGES.txt
URL: http://svn.apache.org/viewvc/lucene/hadoop/trunk/CHANGES.txt?view=diff&rev=510188&r1=510187&r2=510188
==============================================================================
--- lucene/hadoop/trunk/CHANGES.txt (original)
+++ lucene/hadoop/trunk/CHANGES.txt Wed Feb 21 12:32:51 2007
@@ -78,6 +78,9 @@
     namenode and jobtracker with include and exclude files.  (Wendy
     Chien via cutting)
 
+24. HADOOP-1017.  Cache constructors, for improved performance.
+    (Ron Bodkin via cutting)
+
 
 Release 0.11.2 - 2007-02-16
 

Modified: lucene/hadoop/trunk/src/java/org/apache/hadoop/util/ReflectionUtils.java
URL: http://svn.apache.org/viewvc/lucene/hadoop/trunk/src/java/org/apache/hadoop/util/ReflectionUtils.java?view=diff&rev=510188&r1=510187&r2=510188
==============================================================================
--- lucene/hadoop/trunk/src/java/org/apache/hadoop/util/ReflectionUtils.java (original)
+++ lucene/hadoop/trunk/src/java/org/apache/hadoop/util/ReflectionUtils.java Wed Feb 21 12:32:51
2007
@@ -21,6 +21,8 @@
 import java.lang.reflect.Constructor;
 import java.io.*;
 import java.lang.management.*;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
 
 import org.apache.commons.logging.Log;
 import org.apache.hadoop.conf.*;
@@ -33,6 +35,12 @@
 public class ReflectionUtils {
     
     private static final Class[] emptyArray = new Class[]{};
+    /** 
+     * Cache of constructors for each class. Pins the classes so they
+     * can't be garbage collected until ReflectionUtils can be collected.
+     */
+    private static final Map<Class<?>, Constructor<?>> CONSTRUCTOR_CACHE
= 
+        new ConcurrentHashMap<Class<?>, Constructor<?>>();
 
     /**
      * Check and set 'configuration' if necessary.
@@ -61,8 +69,12 @@
     public static Object newInstance(Class theClass, Configuration conf) {
         Object result;
         try {
-            Constructor meth = theClass.getDeclaredConstructor(emptyArray);
-            meth.setAccessible(true);
+            Constructor meth = CONSTRUCTOR_CACHE.get(theClass);
+            if (meth == null) {
+              meth = theClass.getDeclaredConstructor(emptyArray);
+              meth.setAccessible(true);
+              CONSTRUCTOR_CACHE.put(theClass, meth);
+            }
             result = meth.newInstance();
         } catch (Exception e) {
             throw new RuntimeException(e);
@@ -152,4 +164,14 @@
         }
       }
     }
+
+    // methods to support testing
+    static void clearCache() {
+      CONSTRUCTOR_CACHE.clear();
+    }
+    
+    static int getCacheSize() {
+      return CONSTRUCTOR_CACHE.size();
+    }
+
 }

Added: lucene/hadoop/trunk/src/test/org/apache/hadoop/util/TestReflectionUtils.java
URL: http://svn.apache.org/viewvc/lucene/hadoop/trunk/src/test/org/apache/hadoop/util/TestReflectionUtils.java?view=auto&rev=510188
==============================================================================
--- lucene/hadoop/trunk/src/test/org/apache/hadoop/util/TestReflectionUtils.java (added)
+++ lucene/hadoop/trunk/src/test/org/apache/hadoop/util/TestReflectionUtils.java Wed Feb 21
12:32:51 2007
@@ -0,0 +1,91 @@
+package org.apache.hadoop.util;
+
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.HashMap;
+
+import junit.framework.TestCase;
+
+public class TestReflectionUtils extends TestCase {
+
+    private static Class toConstruct[] = { String.class, TestReflectionUtils.class, HashMap.class
};
+    private Throwable failure = null;
+
+    public void setUp() {
+      ReflectionUtils.clearCache();
+    }
+    
+    public void testCache() throws Exception {
+      assertEquals(0, cacheSize());
+      doTestCache();
+      assertEquals(toConstruct.length, cacheSize());
+      ReflectionUtils.clearCache();
+      assertEquals(0, cacheSize());
+    }
+    
+    
+    private void doTestCache() {
+      for (int i=0; i<toConstruct.length; i++) {
+          Class cl = toConstruct[i];
+          Object x = ReflectionUtils.newInstance(cl, null);
+          Object y = ReflectionUtils.newInstance(cl, null);
+          assertEquals(cl, x.getClass());
+          assertEquals(cl, y.getClass());
+      }
+    }
+    
+    public void testThreadSafe() throws Exception {
+      Thread[] th = new Thread[32];
+      for (int i=0; i<th.length; i++) {
+          th[i] = new Thread() {
+            public void run() {
+            try {
+              doTestCache();
+            } catch (Throwable t) {
+              failure = t;
+            }
+          }
+        };
+        th[i].start();
+      }
+      for (int i=0; i<th.length; i++) {
+        th[i].join();
+      }
+      if (failure != null) {
+        failure.printStackTrace();
+        fail(failure.getMessage());
+      }
+    }
+    
+    private int cacheSize() throws Exception {
+      return ReflectionUtils.getCacheSize();
+    }
+    
+    public void testCantCreate() {
+      try {
+        ReflectionUtils.newInstance(NoDefaultCtor.class, null);
+        fail("invalid call should fail");
+      } catch (RuntimeException rte) {
+        assertEquals(NoSuchMethodException.class, rte.getCause().getClass());
+      }
+    }
+    
+    public void testCacheDoesntLeak() throws Exception {
+      int iterations=9999; // very fast, but a bit less reliable - bigger numbers force GC
+      for (int i=0; i<iterations; i++) {
+        URLClassLoader loader = new URLClassLoader(new URL[0], getClass().getClassLoader());
+        Class cl = Class.forName("org.apache.hadoop.util.TestReflectionUtils$LoadedInChild",
false, loader);
+        Object o = ReflectionUtils.newInstance(cl, null);
+        assertEquals(cl, o.getClass());
+      }
+      System.gc();
+      assertTrue(cacheSize()+" too big", cacheSize()<iterations);
+    }
+    
+    private static class LoadedInChild {
+    }
+    
+    public static class NoDefaultCtor {
+      public NoDefaultCtor(int x) {}
+    }
+}



Mime
View raw message