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 components;
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 }