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 }