001    // TimeProfiler.java
002    // Last edited Lee Lin 10/6/2003
003    
004    // Modified by Omair S. Malik 11/02/2007
005    // Using System.nanoTime() instead of System.currentTimeMillis()
006    
007    package test;
008    
009    /**
010     * <b>TimeProfiler </b> objects allow a programmer to profile the running time
011     * of his or her code. It abstracts away any calls to System.nanoTime()
012     * and also keeps a set of statistics to allow the programmer to check
013     * worst-case time, best-case time, and average time. TimeProfilers are mutable.
014     * 
015     * @specfield worst-case-time : integer longest observed time in nanoseconds
016     * @specfield best-case-time : integer shorted observed time in nanoseconds
017     * @specfield average-time : integer average number of nanoseconds per trial
018     * @specfield timing : boolean state of timer (on or off)
019     */
020    
021    public class TimeProfiler {
022    
023            // Abstraction Function AF(c): For all concrete instances, c,
024            // 1. c.slow = worst-case-time
025            // 2. c.fast = best-case-time
026            // 3. c.mean = average-time
027            // 4. Timer is off when (temp == -1), on otherwise
028    
029            // Rep Invariant: For all concrete instances, c,
030            // 1. c.slow <= c.fast
031            // 2. c.numTrials >= 0
032            // 3. c.name != null
033            // 4. mean == 0 if numTrials == 0
034            // (double) total / numTrials otherwise
035            // 5. temp >= -1, temp <= System.nanoTime()
036    
037            private long temp;
038    
039            private long total;
040    
041            private int numTrials;
042    
043            private long slow;
044    
045            private long fast;
046    
047            private double mean;
048    
049            private String name;
050    
051            /*
052             * @effects timer begins off and the best-case, worst-case. and average
053             * times not defined until after the first trial.
054             */
055            public TimeProfiler() {
056                    this("Nameless Test");
057            }
058    
059            /*
060             * @effects timer begins off and the best-case, worst-case. and average
061             * times not defined until after the first trial.
062             */
063            public TimeProfiler(String name) {
064                    this.name = name;
065                    total = 0;
066                    numTrials = 0;
067                    slow = Long.MIN_VALUE;
068                    fast = Long.MAX_VALUE;
069                    mean = 0;
070                    temp = -1;
071            }
072    
073            /**
074             * Starts the timer
075             * 
076             * @modifies this
077             * @effects turns on timing
078             */
079            public void start() {
080                    temp = System.nanoTime();
081            }
082    
083            /**
084             * Stops the timer and records the data.
085             * 
086             * @requires (timing == true) which means this.start() called since last
087             *           time stop() called
088             * @modifies this
089             * @effects turns off timing, updates worst,best, and average time based on
090             *          this trial
091             */
092            public void stop() {
093                    temp = System.nanoTime() - temp;
094                    if (temp > slow)
095                            slow = temp;
096                    if (temp < fast)
097                            fast = temp;
098                    numTrials++;
099                    total += temp;
100                    mean = (double) total / numTrials;
101                    temp = -1;
102            }
103    
104            /**
105             * returns a formatted String with stats on slowest start-stop time, fastest
106             * start-stop time, average time, total records, and aggregate time
107             */
108            public String stats() {
109                    StringBuffer product = new StringBuffer();
110                    product.append("\n***** Stats for ").append(name);
111                    product.append("\nAggregate Time: ").append(total);
112                    product.append("\nAverage Time: ").append(mean);
113                    product.append("\nSlowest time: ").append(slow);
114                    product.append("\nFastest time: ").append(fast);
115                    product.append("\nTotal Trials: ").append(numTrials);
116                    return product.toString();
117            }
118    
119            public String toString() {
120                    return stats();
121            }
122    }