Performance Measurer in Java+Aspect

thekashyap 0 Tallied Votes 147 Views Share

------------------------------------------------------------
Intro:
This is a small program that measures the performance of given java classes.
In snippet there are 2 classes:
1. TestClass.java contains all java classes that are being measured for performance, I've picked up Narue's Sorting Algorithms as AUT (application under test)
2. AJPerf.java: contains the aspect that actually does the work of measuring.
------------------------------------------------------------
Requirements:
Here are the tools/versions used:
- AspectJ Compiler 1.5.2 built on Friday Jun 30, 2006 at 09:30:27 GMT
Can be downloaded from here.
- java version "1.5.0_09"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_09-b03)
Java HotSpot(TM) Client VM (build 1.5.0_09-b03, mixed mode, sharing)
Can be downloaded from here.

I was using Windows NT 5.0 build 2195 Service Pack 4, but should work on all platforms due to Java.
------------------------------------------------------------
Here is how to use it for your class(s):
1. Install aspectJ compiler and JRE/JDK 1.5+
2. Look for TODO in AJPerf.java and make required modifications. Just 3 of them as I see it.
3. Compile using aspectJ compiler. (ajc)
4. Run using aspectJ runner. (aj)
5. Copy and paste the output to excel sheet. Goto Data->Text to columns...
Select "Delimited" and press Next
Check "Other" and type "#" in edit box next to it.
Click finish.
-------------------------------
Example output:
Here is what I had to do if it helps:
E:\Temp\AJPerf> set CLASSPATH=%CLASSPATH%:/home/om1/aspectj1.5/lib/aspectjlib.jar:/home/om1/aspectj1.5/lib/aspectjrt.jar:/home/om1/aspectj1.5/lib/aspectjtools.jar:/home/om1/aspectj1.5/lib/aspectjweaver.jar
E:\Temp\AJPerf> ajc -1.5 -d . *.java
E:\Temp\AJPerf> aj -classpath E:\AspectJ\lib\aspectjweaver.jar;.;E:\AspectJ\lib\aspectjrt.jar;E:\AspectJ\lib\aspectjtools.jar;E:\AspectJ\lib\aspectjlib.jar AJPerf


The OUTPUT:

Function Name#Total Time#Number of calls#Time per call
void in.kash.test.TestClass.SortSelection.push_down(Integer[], int, int)#23483420#2900#8097.0
void in.kash.test.TestClass.SortInsertion.shell_sort(Integer[], int)#971352#100#9713.0
void in.kash.test.TestClass.SortInsertion.insertion_sort(Integer[], int)#2366772#200#11833.0
void in.kash.test.TestClass.SortExchange.quicksort(Integer[], int, int)#1239543#100#12395.0
void in.kash.test.TestClass.SortExchange.quicksort(Integer[], int)#21682929#100#216829.0
void in.kash.test.TestClass.SortExchange.bubble_sort(Integer[], int)#843949#100#8439.0
void in.kash.test.TestClass.main(String[])#210874287#1#2.10874287E8
void in.kash.test.TestClass.SortSelection.selection_sort(Integer[], int)#1347096#100#13470.0
void in.kash.test.TestClass.SortSelection.heapsort(Integer[], int)#44056719#100#440567.0
E:\Temp\AJPerf>

//There are 2 files below
//Classes whose performance is being measured are in TestClass.java
//AJPerf is the aspect class that measures the performance.

/*
 *
 * Filename       : AJPerf.java
 * Author         : Kashyap Bhatt
 * History        : Created on May 4, 2007
 *
 * export CLASSPATH=$CLASSPATH:/home/om1/aspectj1.5/lib/aspectjlib.jar:/home/om1/aspectj1.5/lib/aspectjrt.jar:/home/om1/aspectj1.5/lib/aspectjtools.jar:/home/om1/aspectj1.5/lib/aspectjweaver.jar
 * export PATH=$PATH:~om1/aspectj1.5/bin/
 * ajc -1.5 -d . *.java
 * aj -classpath E:\AspectJ\lib\aspectjweaver.jar;.;E:\AspectJ\lib\aspectjrt.jar;E:\AspectJ\lib\aspectjtools.jar;E:\AspectJ\lib\aspectjlib.jar AJPerf
 *
 */

//TODO: import classes of your application.
import in.kash.test.* ;
import in.kash.test.TestClass.* ;

import java.util.Stack ;
import java.util.HashMap ;

aspect AJPerf {

//TODO: Change pointcut myClass(), but putting names of your classes.
    pointcut myClass(): within(TestClass) || within(SortInsertion)
                || within(SortExchange) || within(SortSelection) ;

    pointcut myMethod(): myClass() && execution(* *(..)) ;

    pointcut myConstructor(): myClass() && execution(new(..)) ;

    before (): myMethod() || myConstructor() {
        traceEntry( "" + thisJoinPointStaticPart.getSignature() ) ;
    }

    after(): myMethod() || myConstructor() {
        traceExit( "" + thisJoinPointStaticPart.getSignature() ) ;
    }

    public static class MethodPerfInfo {
        public long mTotalTime ;
        public long mNumCalls ;
        MethodPerfInfo() { mTotalTime = 0; mNumCalls = 0; }
        public String toString() { return "mTotalTime = " + mTotalTime + " mNumCalls = " + mNumCalls + "\n" ; }
    }

    private static Stack<Long> mTimeStack = new Stack<Long>() ;
    private static HashMap<String, MethodPerfInfo> mOutMap = new HashMap<String, MethodPerfInfo>(1000) ;

    void traceEntry( String s ) {
        //sop("==>" + s) ;
        mTimeStack.push(new Long(System.nanoTime())) ;
        if( ! mOutMap.containsKey(s) )
            mOutMap.put( s, new MethodPerfInfo() ) ;
    }

    void traceExit( String s ) {
        //sop("<==" + s) ;
        MethodPerfInfo obj = mOutMap.get( s ) ;
        obj.mTotalTime += System.nanoTime() - (mTimeStack.pop()).longValue() ;
        obj.mNumCalls++ ;
        mOutMap.put( s, obj ) ;
    }

    private static void sop( String s ) { System.out.println(s) ; }

    public static void main(String[] args) {
//TODO: call your applications's main here.
        TestClass.main(args) ;

        sop( "\n\nThe OUTPUT:\n" ) ;
        Object[] func_names = mOutMap.keySet().toArray() ;
        sop("Function Name#Total Time(nano)#Number of calls#Time per call(nano)" ) ;
        for( int i = 0; i < func_names.length; i++ ) {
            MethodPerfInfo obj = mOutMap.get(func_names[i]) ;
            sop(func_names[i] + "#" + obj.mTotalTime + "#" + obj.mNumCalls + "#" + Double.toString(obj.mTotalTime/obj.mNumCalls) ) ;
        }
    }
}

//--------------------End of AJPerf.java-------------------

/*
 * Filename       : TestClass.java
 * Author         : Kashyap Bhatt
 * History        : Created on May 4, 2007
 */
package in.kash.test;

import java.math.*;

public class TestClass {

    public static void main ( String[] args ) {
        Integer[] a = new Integer[20];
        Integer[] b ;

        for( int xxx = 0; xxx < 100; xxx++ ) {
            for ( int i = 0; i < 20; i++ ) {
                a[i] = new Integer( (int)(Math.random() * 100) );
            }
            //save a
            b = a ;

            /*System.out.println ( "Before: " );

            for ( int i = 0; i < a.length; i++ ) {
                System.out.print ( i + " " );
            }
            System.out.println ( "" );*/

            SortInsertion.insertion_sort( a, a.length ) ;

            a = b ;
            SortInsertion.shell_sort( a, a.length ) ;

            a = b ;
            SortExchange.bubble_sort( a, a.length ) ;
            a = b ;
            SortExchange.quicksort( a, a.length ) ;

            a = b ;
            SortSelection.selection_sort( a, a.length ) ;
            a = b ;
            SortSelection.heapsort( a, a.length ) ;

            /*System.out.println ( "After: " );
            for ( int i = 0; i < a.length; i++ ) {
                System.out.print ( i + " " );
            }
            System.out.println ( "" );*/
        }
    }

    public TestClass() {
        //System.out.println( "Inside TestClass()" ) ;
    }


    /*
     * Source: http://www.daniweb.com/code/snippet77.html
     * modified to make it NON-generic.
     */

    public static class SortInsertion {
        // Insertion sort
        public static void insertion_sort ( Integer[] list, int size ) {
            for ( int i = 1; i < size; i++ ) {
                Integer save = list[i];
                int j = i;

                while ( j >= 1 && save.compareTo ( list[j - 1] ) < 0 ) {
                    list[j] = list[j - 1];
                    --j;
                }

                list[j] = save;
            }
        }

        // Shell sort
        public static
        void shell_sort ( Integer[] list, int size ) {
            int h = 1;

            while ( h <= size / 9 ) {
                h = 3 * h + 1;
            }

            while ( h > 0 ) {
                for ( int i = h; i < size; i++ ) {
                    Integer save = list[i];
                    int j = i;

                    while ( j >= h && save.compareTo ( list[j - h] ) < 0 ) {
                        list[j] = list[j - h];
                        j -= h;
                    }

                    list[j] = save;
                }

                h /= 3;
            }
        }
    }

    public static class SortExchange {
        // Bubble sort
        public static
        void bubble_sort ( Integer[] list, int size ) {
            int bound = size - 1;

            while ( bound > 0 ) {
                int new_bound = 0;

                for ( int i = 0; i < bound; i++ ) {
                    if ( list[i].compareTo ( list[i + 1] ) > 0 ) {
                        Integer save = list[i];
                        list[i] = list[i + 1];
                        list[i + 1] = save;

                        new_bound = i;
                    }
                }

                bound = new_bound;
            }
        }

        // Quicksort
        private static void quicksort ( Integer[] list, int l, int r ) {
            int[] stack = new int[50];
            int m, top = 0;
            Integer pivot;

            while ( true ) {
                while ( r > l + 10 ) {
                    // Median of three partition
                    m = ( l + r ) / 2;

                    if ( list[l].compareTo ( list[m] ) > 0 ) {
                        Integer save = list[l];
                        list[l] = list[m];
                        list[m] = save;
                    }
                    if ( list[l].compareTo ( list[r] ) > 0 ) {
                        Integer save = list[l];
                        list[l] = list[r];
                        list[r] = save;
                    }
                    if ( list[m].compareTo ( list[r] ) > 0 ) {
                        Integer save = list[m];
                        list[m] = list[r];
                        list[r] = save;
                    }

                    if ( r - l <= 2 ) {
                        break;
                    }

                    pivot = list[m];
                    list[m] = list[r - 1];
                    list[r - 1] = pivot;

                    int i = l;
                    int j = r - 1;

                    while ( true ) {
                        while ( list[++i].compareTo ( pivot ) < 0 ) {
                            // No body
                        }
                        while ( list[--j].compareTo ( pivot ) > 0 ) {
                            // No body
                        }

                        if ( j < i ) {
                            break;
                        }

                        Integer save = list[i];
                        list[i] = list[j];
                        list[j] = save;
                    }

                    pivot = list[i];
                    list[i] = list[r - 1];
                    list[r - 1] = pivot;

                    // Simulated recursive calls
                    if ( j - l > r - i ) {
                        stack[top++] = l;
                        stack[top++] = j;
                        l = i + 1;
                    } else {
                        stack[top++] = i + 1;
                        stack[top++] = r;
                        r = j;
                    }
                }

                if ( top == 0 ) {
                    break;
                }

                r = stack[--top];
                l = stack[--top];
            }
        }

        public static
        void quicksort ( Integer[] list, int size ) {
            quicksort ( list, 0, size - 1 );
            SortInsertion.insertion_sort ( list, size );
        }
    }

    public static class SortSelection {
        // Selection sort
        public static
        void selection_sort ( Integer[] list, int size ) {
            for ( int i = 0; i < size - 1; i++ ) {
                int min = i;

                for ( int j = i + 1; j < size; j++ ) {
                    if ( list[j].compareTo ( list[min] ) < 0 ) {
                        min = j;
                    }
                }

                if ( min != i ) {
                    Integer save = list[i];
                    list[i] = list[min];
                    list[min] = save;
                }
            }
        }

        // Heapsort
        private static void push_down ( Integer[] list, int l, int r ) {
            int i, j;

            for ( i = l; ( j = i * 2 + 1 ) <= r; i = j ) {
                if ( j + 1 <= r && list[j + 1].compareTo ( list[j] ) > 0 ) {
                    ++j;
                }

                Integer save = list[i];
                list[i] = list[j];
                list[j] = save;
            }

            while ( true ) {
                j = ( i - 1 ) / 2;

                if ( j < l || j == i || list[j].compareTo ( list[i] ) > 0 ) {
                    break;
                }

                Integer save = list[i];
                list[i] = list[j];
                list[j] = save;

                i = j;
            }
        }

        public static
        void heapsort ( Integer[] list, int size ) {
            if ( size-- < 2 ) {
                return;
            }

            int i;

            for ( i = ( size - 1 ) / 2; i >= 0; i-- ) {
                push_down ( list, i, size );
            }

            while ( size > 0 ) {
                Integer save = list[size];
                list[size] = list[0];
                list[0] = save;

                push_down ( list, 0, --size );
            }
        }
    }

}
peter_budo 2,532 Code tags enforcer Team Colleague Featured Poster

You didn't elaborated what you try to achive

Expecting people to use some uknown/custome libraries in the CLASSPATH

You are missing even basic explanation what each sort method is about, what it does

Good code, but you loosing on documentation grounds

thekashyap 193 Practically a Posting Shark

@Peter:

Thanks.

>> You didn't elaborated what you try to achive
From Intro "This is a small program that measures the performance of given java classes."
One can use it when they wanna find out what to optimize in their code by looking at figures.

>> Expecting people to use some uknown/custome libraries in the CLASSPATH
That's an example (intentionally put in there to help others remember that they need to add aspect's jar files to their classpath). None of the jar files there are "unknown/custom" all are aspectJ's whose link is also posted.
What ppl are supposed to do is
"3. Compile using aspectJ compiler. (ajc)
4. Run using aspectJ runner. (aj)"

>> You are missing even basic explanation what each sort method is about, what it does
the methods themselves are irrelevant (not even my code as mentioned in code as well as explanation, along with link to the source and credit to author).
But you're right, I haven't put enough comments in code that I wrote. It doesn't seem possible to edit it now, so hope ppl can understand, it's pretty simple.

thekashyap 193 Practically a Posting Shark

BTW: This thread was teh trigger for me to write this snippet. May be you'll get context (what is this program trying to achieve) from there as well.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.