diff options
author | aclement <aclement> | 2004-09-01 10:30:07 +0000 |
---|---|---|
committer | aclement <aclement> | 2004-09-01 10:30:07 +0000 |
commit | 438e61c998298b48830d5be76668df45629a1eb0 (patch) | |
tree | 96234fe0bd9bd7740dbc9c4a51b7ddc5edead31f /runtime | |
parent | 3dcc2dd68179b687ba785ad3352ba7eabde387c5 (diff) | |
download | aspectj-438e61c998298b48830d5be76668df45629a1eb0.tar.gz aspectj-438e61c998298b48830d5be76668df45629a1eb0.zip |
Enhancement for Bugzilla Bug 49743
performance improvements for runtime library
(From Matthew)
Diffstat (limited to 'runtime')
13 files changed, 177 insertions, 16 deletions
diff --git a/runtime/src/org/aspectj/runtime/reflect/AdviceSignatureImpl.java b/runtime/src/org/aspectj/runtime/reflect/AdviceSignatureImpl.java index 029d4e6de..7efe2cd7d 100644 --- a/runtime/src/org/aspectj/runtime/reflect/AdviceSignatureImpl.java +++ b/runtime/src/org/aspectj/runtime/reflect/AdviceSignatureImpl.java @@ -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())); diff --git a/runtime/src/org/aspectj/runtime/reflect/CatchClauseSignatureImpl.java b/runtime/src/org/aspectj/runtime/reflect/CatchClauseSignatureImpl.java index a0ca7dbdb..15d9dcaa3 100644 --- a/runtime/src/org/aspectj/runtime/reflect/CatchClauseSignatureImpl.java +++ b/runtime/src/org/aspectj/runtime/reflect/CatchClauseSignatureImpl.java @@ -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()) + ")"; } } diff --git a/runtime/src/org/aspectj/runtime/reflect/ConstructorSignatureImpl.java b/runtime/src/org/aspectj/runtime/reflect/ConstructorSignatureImpl.java index c9576baaa..520cfdf09 100644 --- a/runtime/src/org/aspectj/runtime/reflect/ConstructorSignatureImpl.java +++ b/runtime/src/org/aspectj/runtime/reflect/ConstructorSignatureImpl.java @@ -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())); diff --git a/runtime/src/org/aspectj/runtime/reflect/Factory.java b/runtime/src/org/aspectj/runtime/reflect/Factory.java index 1c2b2f2bb..01bc8eff3 100644 --- a/runtime/src/org/aspectj/runtime/reflect/Factory.java +++ b/runtime/src/org/aspectj/runtime/reflect/Factory.java @@ -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); } } diff --git a/runtime/src/org/aspectj/runtime/reflect/FieldSignatureImpl.java b/runtime/src/org/aspectj/runtime/reflect/FieldSignatureImpl.java index b04f23525..c56ca5212 100644 --- a/runtime/src/org/aspectj/runtime/reflect/FieldSignatureImpl.java +++ b/runtime/src/org/aspectj/runtime/reflect/FieldSignatureImpl.java @@ -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())); diff --git a/runtime/src/org/aspectj/runtime/reflect/InitializerSignatureImpl.java b/runtime/src/org/aspectj/runtime/reflect/InitializerSignatureImpl.java index d7301d8ac..740ec07f3 100644 --- a/runtime/src/org/aspectj/runtime/reflect/InitializerSignatureImpl.java +++ b/runtime/src/org/aspectj/runtime/reflect/InitializerSignatureImpl.java @@ -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())); diff --git a/runtime/src/org/aspectj/runtime/reflect/MethodSignatureImpl.java b/runtime/src/org/aspectj/runtime/reflect/MethodSignatureImpl.java index 1ec8c6914..7e667425d 100644 --- a/runtime/src/org/aspectj/runtime/reflect/MethodSignatureImpl.java +++ b/runtime/src/org/aspectj/runtime/reflect/MethodSignatureImpl.java @@ -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())); diff --git a/runtime/src/org/aspectj/runtime/reflect/SignatureImpl.java b/runtime/src/org/aspectj/runtime/reflect/SignatureImpl.java index 9c8d226ac..9045880e0 100644 --- a/runtime/src/org/aspectj/runtime/reflect/SignatureImpl.java +++ b/runtime/src/org/aspectj/runtime/reflect/SignatureImpl.java @@ -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; + } + } diff --git a/runtime/src/org/aspectj/runtime/reflect/SourceLocationImpl.java b/runtime/src/org/aspectj/runtime/reflect/SourceLocationImpl.java index d69bec612..b55877dc4 100644 --- a/runtime/src/org/aspectj/runtime/reflect/SourceLocationImpl.java +++ b/runtime/src/org/aspectj/runtime/reflect/SourceLocationImpl.java @@ -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(); } } diff --git a/runtime/src/org/aspectj/runtime/reflect/StringMaker.java b/runtime/src/org/aspectj/runtime/reflect/StringMaker.java index e014defb4..a2a1122c0 100644 --- a/runtime/src/org/aspectj/runtime/reflect/StringMaker.java +++ b/runtime/src/org/aspectj/runtime/reflect/StringMaker.java @@ -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) { diff --git a/runtime/testsrc/RuntimeModuleTests.java b/runtime/testsrc/RuntimeModuleTests.java index 61bc7a869..a5a4c0768 100644 --- a/runtime/testsrc/RuntimeModuleTests.java +++ b/runtime/testsrc/RuntimeModuleTests.java @@ -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 index 000000000..592bcd6a3 --- /dev/null +++ b/runtime/testsrc/org/aspectj/runtime/reflect/RuntimePerformanceTest.java @@ -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 diff --git a/runtime/testsrc/org/aspectj/runtime/reflect/SignatureTest.java b/runtime/testsrc/org/aspectj/runtime/reflect/SignatureTest.java index b8170d649..533280fcd 100644 --- a/runtime/testsrc/org/aspectj/runtime/reflect/SignatureTest.java +++ b/runtime/testsrc/org/aspectj/runtime/reflect/SignatureTest.java @@ -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))); + } } |