]> source.dussan.org Git - aspectj.git/commitdiff
Enhancement for Bugzilla Bug 49743
authoraclement <aclement>
Wed, 1 Sep 2004 10:30:07 +0000 (10:30 +0000)
committeraclement <aclement>
Wed, 1 Sep 2004 10:30:07 +0000 (10:30 +0000)
   performance improvements for runtime library
(From Matthew)

14 files changed:
lib/test/aspectjrt.jar
runtime/src/org/aspectj/runtime/reflect/AdviceSignatureImpl.java
runtime/src/org/aspectj/runtime/reflect/CatchClauseSignatureImpl.java
runtime/src/org/aspectj/runtime/reflect/ConstructorSignatureImpl.java
runtime/src/org/aspectj/runtime/reflect/Factory.java
runtime/src/org/aspectj/runtime/reflect/FieldSignatureImpl.java
runtime/src/org/aspectj/runtime/reflect/InitializerSignatureImpl.java
runtime/src/org/aspectj/runtime/reflect/MethodSignatureImpl.java
runtime/src/org/aspectj/runtime/reflect/SignatureImpl.java
runtime/src/org/aspectj/runtime/reflect/SourceLocationImpl.java
runtime/src/org/aspectj/runtime/reflect/StringMaker.java
runtime/testsrc/RuntimeModuleTests.java
runtime/testsrc/org/aspectj/runtime/reflect/RuntimePerformanceTest.java [new file with mode: 0644]
runtime/testsrc/org/aspectj/runtime/reflect/SignatureTest.java

index 976e2737ea134b4124a5130aabcda90f2428c80f..c4febb32373845a205bbc185c5bc6d22258cdca2 100644 (file)
Binary files a/lib/test/aspectjrt.jar and b/lib/test/aspectjrt.jar differ
index 029d4e6dedc8e2cbbb4319c133b1490faf919e6a..7efe2cd7dc0598a756df6a3e20755ab262f24603 100644 (file)
@@ -39,7 +39,7 @@ class AdviceSignatureImpl extends CodeSignatureImpl implements AdviceSignature {
         return returnType;
     }
 
-    String toString(StringMaker sm) {
+    protected String createToString(StringMaker sm) {
         //XXX this signature needs a lot of work        
         StringBuffer buf = new StringBuffer("ADVICE: ");
         buf.append(sm.makeModifiersString(getModifiers()));
index a0ca7dbdb0ab85cacb79206632844ef14b689cf1..15d9dcaa3b713063dc0d9a68ec44106a13629d67 100644 (file)
@@ -41,7 +41,7 @@ class CatchClauseSignatureImpl extends SignatureImpl implements CatchClauseSigna
         return parameterName;
     }
     
-    String toString(StringMaker sm) {
+    protected String createToString(StringMaker sm) {
         return "catch(" + sm.makeTypeName(getParameterType()) + ")";
     }    
 }
index c9576baaa57950c1d4136d9091638df0157ccae8..520cfdf09ef8cbf776d2ab0ad9af2693f9146faf 100644 (file)
@@ -29,7 +29,7 @@ class ConstructorSignatureImpl extends CodeSignatureImpl implements ConstructorS
     
     public String getName() { return "<init>"; }
     
-    String toString(StringMaker sm) {
+    protected String createToString(StringMaker sm) {
         StringBuffer buf = new StringBuffer();
         buf.append(sm.makeModifiersString(getModifiers()));
         buf.append(sm.makePrimaryTypeName(getDeclaringType(),getDeclaringTypeName()));
index 1c2b2f2bb571848b3169547841b14c3c4cac8f39..01bc8eff346c82dc06580680f5d47766cfd784bd 100644 (file)
@@ -148,6 +148,6 @@ public final class Factory {
 
     public SourceLocation makeSourceLoc(int line, int col)
     {
-        return new SourceLocationImpl(lexicalClass, this.filename, line, col);
+        return new SourceLocationImpl(lexicalClass, this.filename, line);
     }
 }
index b04f23525e443fddebcf5772fed172f887b84598..c56ca52124a1709c6be83b3fe02983b569464a33 100644 (file)
@@ -35,7 +35,7 @@ public class FieldSignatureImpl extends MemberSignatureImpl implements FieldSign
         return fieldType;
     }
     
-    String toString(StringMaker sm) {
+    protected String createToString(StringMaker sm) {
         StringBuffer buf = new StringBuffer();
         buf.append(sm.makeModifiersString(getModifiers()));
         if (sm.includeArgs) buf.append(sm.makeTypeName(getFieldType()));
index d7301d8acec0fad2af8531d720bf998e0223b315..740ec07f3a5a900aee3b111631ae88eeb87dc560 100644 (file)
@@ -32,7 +32,7 @@ class InitializerSignatureImpl extends CodeSignatureImpl implements InitializerS
        return Modifier.isStatic(getModifiers()) ? "<clinit>": "<init>";
     }
 
-    String toString(StringMaker sm) {
+    protected String createToString(StringMaker sm) {
         StringBuffer buf = new StringBuffer();
         buf.append(sm.makeModifiersString(getModifiers()));    
         buf.append(sm.makePrimaryTypeName(getDeclaringType(),getDeclaringTypeName()));
index 1ec8c69147230e7dbb0179bfe6b2f9a6fe868506..7e667425d45a4cfb33a324d2ef4c491b013abfce 100644 (file)
@@ -38,7 +38,7 @@ class MethodSignatureImpl extends CodeSignatureImpl implements MethodSignature {
         return returnType;
     }
     
-    String toString(StringMaker sm) {
+    protected String createToString(StringMaker sm) {
         StringBuffer buf = new StringBuffer();
         buf.append(sm.makeModifiersString(getModifiers()));
         if (sm.includeArgs) buf.append(sm.makeTypeName(getReturnType()));
index 9c8d226ac2754885bb3331ecb827bfad20cae5ac..9045880e012ec711c1bf9beff6f8be59a9c0d75e 100644 (file)
@@ -16,14 +16,19 @@ package org.aspectj.runtime.reflect;
 
 import org.aspectj.lang.Signature;
 
+import java.lang.ref.SoftReference;
 import java.util.Hashtable;
 import java.util.StringTokenizer;
 
 abstract class SignatureImpl implements Signature {
+
+       private static boolean useCache = true;
+       
     int modifiers = -1;
     String name;
     String declaringTypeName;
     Class declaringType;
+    SoftReference toStringCacheRef;
     
     SignatureImpl(int modifiers, String name, Class declaringType) {
         this.modifiers = modifiers;
@@ -31,7 +36,24 @@ abstract class SignatureImpl implements Signature {
         this.declaringType = declaringType;
     }
     
-    abstract String toString(StringMaker sm);
+    protected abstract String createToString (StringMaker sm);
+    
+    /* Use a soft cache for the short, middle and long String representations */
+       String toString (StringMaker sm) {
+               String[] toStringCache = null;
+               if (toStringCacheRef == null || toStringCacheRef.get() == null) {
+                       toStringCache = new String[3];
+                       if (useCache) toStringCacheRef = new SoftReference(toStringCache);
+               }
+               else {
+                       toStringCache = (String[])toStringCacheRef.get();
+               }
+               
+               if (toStringCache[sm.cacheOffset] == null) {
+                       toStringCache[sm.cacheOffset] = createToString(sm);
+               }
+               return toStringCache[sm.cacheOffset];
+       }
     
     public final String toString() { return toString(StringMaker.middleStringMaker); }
     public final String toShortString() { return toString(StringMaker.shortStringMaker); }
@@ -92,7 +114,7 @@ abstract class SignatureImpl implements Signature {
     }
     
     // lazy version
-    String stringRep;
+    private String stringRep;
     ClassLoader lookupClassLoader = null;
     
     public void setLookupClassLoader(ClassLoader loader) {
@@ -193,4 +215,16 @@ abstract class SignatureImpl implements Signature {
         for (int i = 0; i < N; i++) ret[i]= makeClass(st.nextToken());
         return ret;
     }
+
+       /*
+        * Used for testing
+        */
+       static void setUseCache (boolean b) {
+               useCache = b;
+       }
+
+       static boolean getUseCache () {
+               return useCache;
+       }
+
 }
index d69bec6129d431625ced07f5c39335daedf5b1f8..b55877dc48830da5ff4b7c6a80dae6ea6f6f3155 100644 (file)
@@ -20,23 +20,20 @@ class SourceLocationImpl implements SourceLocation {
     Class withinType;
     String fileName;
     int line;
-    int column;
     
-    SourceLocationImpl(Class withinType, String fileName, int line, int column) {
+    SourceLocationImpl(Class withinType, String fileName, int line) {
         this.withinType = withinType;
         this.fileName = fileName;
         this.line = line;
-        this.column = column;
     }
     
     public Class getWithinType() { return withinType; }
     public String getFileName() { return fileName; }
     public int getLine() { return line; }
-    public int getColumn() { return column; }
+    public int getColumn() { return -1; }
     
     public String toString() {
-       return getFileName() + ":" + getLine() +
-               ((getColumn() == -1) ? ""  : ":" + getColumn());
+       return getFileName() + ":" + getLine();
     }
 }
 
index e014defb442d1d3055d90035eeb8a9aeed5af995..a2a1122c0ac32a2f4bce4630c72b1fa3c4b9b920 100644 (file)
@@ -26,6 +26,7 @@ class StringMaker {
     boolean includeJoinPointTypeName = true;
     boolean includeEnclosingPoint = true;
     boolean shortKindName = true;
+    int cacheOffset;
     
     static StringMaker shortStringMaker;
     static {
@@ -39,6 +40,7 @@ class StringMaker {
         shortStringMaker.includeJoinPointTypeName = false;
         shortStringMaker.includeEnclosingPoint = false;
         
+               shortStringMaker.cacheOffset = 0;
     }
     
     static StringMaker middleStringMaker;
@@ -49,6 +51,8 @@ class StringMaker {
         middleStringMaker.includeThrows = false;
         middleStringMaker.includeModifiers = false;
         middleStringMaker.shortPrimaryTypeNames = false;
+
+               shortStringMaker.cacheOffset = 1;
     }
     
     static StringMaker longStringMaker;
@@ -60,6 +64,8 @@ class StringMaker {
         longStringMaker.includeModifiers = true;
         longStringMaker.shortPrimaryTypeNames = false;
         longStringMaker.shortKindName = false;
+
+               longStringMaker.cacheOffset = 2;
     }
     
     String makeKindName(String name) {
index 61bc7a86950ee13a5f10ad94505de6782350127f..a5a4c0768cbb885bdbd62cd93466770a59b6c882 100644 (file)
@@ -17,6 +17,7 @@ import java.io.*;
 
 import org.aspectj.lang.*;
 import org.aspectj.runtime.reflect.JoinPointImplTest;
+import org.aspectj.runtime.reflect.RuntimePerformanceTest;
 import org.aspectj.runtime.reflect.SignatureTest;
 
 import junit.framework.*;
@@ -27,7 +28,8 @@ public class RuntimeModuleTests extends TestCase {
         TestSuite suite = new TestSuite(RuntimeModuleTests.class.getName());
         suite.addTestSuite(RuntimeModuleTests.class); // minimum 1 test (testNothing)
         suite.addTestSuite(SignatureTest.class);
-        suite.addTestSuite(JoinPointImplTest.class);
+               suite.addTestSuite(JoinPointImplTest.class);
+               suite.addTestSuite(RuntimePerformanceTest.class);
         return suite;
     }
 
diff --git a/runtime/testsrc/org/aspectj/runtime/reflect/RuntimePerformanceTest.java b/runtime/testsrc/org/aspectj/runtime/reflect/RuntimePerformanceTest.java
new file mode 100644 (file)
index 0000000..592bcd6
--- /dev/null
@@ -0,0 +1,111 @@
+/*******************************************************************************
+ * Copyright (c) 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     Matthew Webster - initial implementation
+ *******************************************************************************/
+package org.aspectj.runtime.reflect;
+
+import java.lang.reflect.Method;
+import java.util.Timer;
+import java.util.TimerTask;
+
+import org.aspectj.lang.Signature;
+
+import junit.framework.TestCase;
+
+public class RuntimePerformanceTest extends TestCase {
+
+       private static final Timer timer = new Timer(true);
+       private static final long TIMEOUT = 10000;
+       private static final long ITERATIONS = 1000000;
+       private static final long WARMUP_ITERATIONS = 10000;
+       private static final long EXPECTED_RATIO = 10;
+       private static final Factory factory = new Factory("RutimePerformanceTest.java",RuntimePerformanceTest.class);
+
+       private boolean savedUseCaches;
+       private Method method;
+       private Signature signature;
+
+       private TimerTask task;
+       private boolean abort;
+
+       public RuntimePerformanceTest(String name) {
+               super(name);
+       }
+
+       protected void setUp() throws Exception {
+               super.setUp();
+               
+               /* Save default state */
+               savedUseCaches = SignatureImpl.getUseCache();
+               
+               /* If a test takes too long we can kill it and fail */
+               abort = false;
+               task = new TimerTask() {
+                       public void run () {
+                               abort = true;   
+                       }
+               };
+               timer.schedule(task,TIMEOUT);
+       }
+       
+       protected void tearDown() throws Exception {
+               super.tearDown();
+               
+               /* Restore default state */
+               SignatureImpl.setUseCache(savedUseCaches);
+
+               task.cancel();
+       }
+
+       public void testToString () {
+               Signature signature = makeMethodSig("test");
+
+               SignatureImpl.setUseCache(false);
+               warmUp(signature);
+               long noCache = invokeSignatureToString(signature,ITERATIONS/EXPECTED_RATIO);
+               System.out.println("noCache=" + noCache);
+
+               SignatureImpl.setUseCache(true);
+               warmUp(signature);
+               long cache = invokeSignatureToString(signature,ITERATIONS);
+               System.out.println("cache=" + cache);
+
+               long ratio = (EXPECTED_RATIO*noCache/cache);
+               System.out.println("ratio=" + ratio);
+               assertTrue("Using cache should be " + EXPECTED_RATIO + " times faster: " + ratio,(ratio > EXPECTED_RATIO));
+       }
+       
+       private long invokeSignatureToString (Signature sig, long iterations) {
+               long start = System.currentTimeMillis();
+               String s;
+
+               for (long l = 0; !abort && (l < iterations); l++) {
+                       s = sig.toShortString();
+                       s = sig.toString();
+                       s = sig.toLongString();
+               }
+               if (abort) throw new RuntimeException("invokeSignatureToString aborted after " + (TIMEOUT/1000) + " seconds");
+
+               long finish = System.currentTimeMillis();
+               return (finish-start);          
+       }
+       
+       private void warmUp (Signature sig) {
+               invokeSignatureToString(sig,WARMUP_ITERATIONS);  
+       }
+       
+       private Signature makeMethodSig (String methodName) {
+               Class clazz = getClass();
+               Class[] parameterTypes = new Class[] { String.class };
+               String[] parameterNames = new String[] { "s" };
+               Class[] exceptionTypes = new Class[] {};
+               Class returnType = Void.TYPE;
+               return factory.makeMethodSig(1,methodName,clazz,parameterTypes,parameterNames,exceptionTypes,returnType);
+       }
+}
\ No newline at end of file
index b8170d6496a2abe567a9cefb192981d483e1d83a..533280fcd382b9d463065799298a1829bd3e44d7 100644 (file)
@@ -20,4 +20,15 @@ public class SignatureTest extends TestCase {
                assertEquals(SignatureTest.class.getName(),fsi.getDeclaringTypeName());
                assertSame(fsi.getDeclaringTypeName(),fsi.getDeclaringTypeName()); // should be cached.
        }
+       
+       public void testToShortMiddleLongString () {
+               MethodSignatureImpl msi = new MethodSignatureImpl(0,"test",SignatureTest.class,new Class[] { String.class, Integer.TYPE }, new String[] { "s", "i" }, new Class[] {}, Runnable.class);
+               String shortString = msi.toShortString();
+               assertSame(shortString,msi.toShortString()); // should be cached.
+               String middleString = msi.toString();
+               assertSame(middleString,msi.toString()); // should be cached.
+               String longString = msi.toLongString();
+               assertSame(longString,msi.toLongString()); // should be cached.
+               assertTrue("String representations should be different",!(shortString.equals(middleString) || middleString.equals(longString) || longString.equals(shortString)));
+       }
 }