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 other; 008 009 010 /** 011 * <b>TimeProfiler </b> objects allow a programmer to profile the running time 012 * of his or her code. It abstracts away any calls to System.nanoTime() and also 013 * keeps a set of statistics to allow the programmer to check worst-case time, 014 * best-case time, and average time. TimeProfilers are mutable. 015 * 016 * @specfield worst-case-time : integer longest observed time in nanoseconds 017 * @specfield best-case-time : integer shorted observed time in nanoseconds 018 * @specfield average-time : integer average number of nanoseconds per trial 019 * @specfield timing : boolean state of timer (on or off) 020 */ 021 022 public class TimeProfiler 023 { 024 025 // Abstraction Function AF(c): For all concrete instances, c, 026 // 1. c.slow = worst-case-time 027 // 2. c.fast = best-case-time 028 // 3. c.mean = average-time 029 // 4. Timer is off when (temp == -1), on otherwise 030 031 // Rep Invariant: For all concrete instances, c, 032 // 1. c.slow <= c.fast 033 // 2. c.numTrials >= 0 034 // 3. c.name != null 035 // 4. mean == 0 if numTrials == 0 036 // (double) total / numTrials otherwise 037 // 5. temp >= -1, temp <= System.nanoTime() 038 039 private long temp; 040 041 private long total; 042 043 private int numTrials; 044 045 private long slow; 046 047 private long fast; 048 049 private double mean; 050 051 //private String name; 052 053 /* 054 * @effects timer begins off and the best-case, worst-case. and average 055 * times not defined until after the first trial. 056 */ 057 public TimeProfiler() 058 { 059 this("Nameless Test"); 060 } 061 062 /* 063 * @effects timer begins off and the best-case, worst-case. and average 064 * times not defined until after the first trial. 065 */ 066 public TimeProfiler(String name) 067 { 068 //this.name = name; 069 total = 0; 070 numTrials = 0; 071 slow = Long.MIN_VALUE; 072 fast = Long.MAX_VALUE; 073 mean = 0; 074 temp = -1; 075 } 076 077 /** 078 * Starts the timer 079 * 080 * @modifies this 081 * @effects turns on timing 082 */ 083 public void start() 084 { 085 temp = System.nanoTime(); 086 } 087 088 /** 089 * Stops the timer and records the data. 090 * 091 * @requires (timing == true) which means this.start() called since last 092 * time stop() called 093 * @modifies this 094 * @effects turns off timing, updates worst,best, and average time based on 095 * this trial 096 */ 097 public long stop() 098 { 099 long time = temp = System.nanoTime() - temp; 100 if (temp > slow) 101 slow = temp; 102 if (temp < fast) 103 fast = temp; 104 numTrials++; 105 total += temp; 106 mean = (double) total / numTrials; 107 temp = -1; 108 return time; 109 } 110 111 /** 112 * returns a formatted String with stats on slowest start-stop time, fastest 113 * start-stop time, average time, total records, and aggregate time 114 */ 115 public String stats() 116 { 117 StringBuffer product = new StringBuffer(); 118 product.append(mean); 119 // product.append("\n***** Stats for ").append(name); 120 // product.append("\nAggregate Time: ").append(total); 121 // product.append("\nAverage Time: ").append(mean); 122 // product.append("\nSlowest time: ").append(slow); 123 // product.append("\nFastest time: ").append(fast); 124 // product.append("\nTotal Trials: ").append(numTrials); 125 return product.toString(); 126 } 127 128 public String toString() 129 { 130 return stats(); 131 } 132 133 static abstract class Profiler 134 { 135 public void init() 136 { 137 } 138 139 abstract void profiledLoop(); 140 141 public void preLoop() 142 { 143 } 144 145 public void run(int printEvery, int max) 146 { 147 StringBuffer s = new StringBuffer(""); 148 init(); 149 TimeProfiler profiler = new TimeProfiler(); 150 for (int i = 0; i < max; i++) 151 { 152 if (i % printEvery == 0) 153 { 154 String temp = i + "\t" + (long)profiler.mean; 155 System.out.println(temp); 156 s.append(temp); 157 profiler = new TimeProfiler(); 158 } 159 preLoop(); 160 profiler.start(); 161 profiledLoop(); 162 profiler.stop(); 163 } 164 } 165 } 166 167 // static class ExtendProfiler extends Profiler 168 // { 169 // Path<GeoSegment> r; 170 // GeoPoint left = new GeoPoint(-10, 0); 171 // GeoPoint right = new GeoPoint(10, 0); 172 // GeoSegment ltor = new GeoSegment("left to right", left, right); 173 // GeoSegment rtol = new GeoSegment("left to right", right, left); 174 // 175 // public void init() 176 // { 177 // List<GeoSegment> goals = new LinkedList<GeoSegment>(); 178 // goals.add(ltor); 179 // r = new RoutePath(ltor, goals); 180 // } 181 // 182 // void profiledLoop() 183 // { 184 // r = r.extend(rtol); 185 // r = r.extend(ltor); 186 // } 187 // } 188 // 189 // static class CostProfiler extends Profiler 190 // { 191 // Path<GeoSegment> r; 192 // GeoPoint left = new GeoPoint(-10, 0); 193 // GeoPoint right = new GeoPoint(10, 0); 194 // GeoSegment ltor = new GeoSegment("left to right", left, right); 195 // GeoSegment rtol = new GeoSegment("left to right", right, left); 196 // 197 // public void init() 198 // { 199 // List<GeoSegment> goals = new LinkedList<GeoSegment>(); 200 // goals.add(ltor); 201 // r = new RoutePath(ltor, goals); 202 // } 203 // 204 // public void preLoop() 205 // { 206 // r = r.extend(rtol); 207 // r = r.extend(ltor); 208 // } 209 // 210 // void profiledLoop() 211 // { 212 // r.cost(); 213 // } 214 // } 215 // 216 // static class AddNodeProfiler extends Profiler 217 // { 218 // int lat = 0; 219 // Path<GeoSegment> r; 220 // GeoPoint p1; 221 // GeoPoint p2; 222 // GeoSegment s; 223 // Graph<GeoSegment> g = new RelationshipGraph<GeoSegment>(); 224 // 225 // public void init() 226 // { 227 // p1 = new GeoPoint(lat, 0); 228 // lat++; 229 // p2 = new GeoPoint(lat, 0); 230 // s = new GeoSegment("foo", p1, p2); 231 // 232 // List<GeoSegment> goals = new LinkedList<GeoSegment>(); 233 // goals.add(s); 234 // r = new RoutePath(s, goals); 235 // } 236 // 237 // public void preLoop() 238 // { 239 // p1 = new GeoPoint(lat, 0); 240 // lat++; 241 // p2 = new GeoPoint(lat, 0); 242 // s = new GeoSegment("foo", p1, p2); 243 // } 244 // 245 // void profiledLoop() 246 // { 247 // g.addNode(s); 248 // } 249 // } 250 // 251 // static class GetChildrenProfiler extends Profiler 252 // { 253 // int lat = 0; 254 // Path<GeoSegment> r; 255 // GeoPoint p1; 256 // GeoPoint p2; 257 // GeoSegment s; 258 // Graph<GeoSegment> g = new RelationshipGraph<GeoSegment>(); 259 // 260 // public void init() 261 // { 262 // p1 = new GeoPoint(lat, 0); 263 // lat++; 264 // p2 = new GeoPoint(lat, 0); 265 // s = new GeoSegment("foo", p1, p2); 266 // 267 // List<GeoSegment> goals = new LinkedList<GeoSegment>(); 268 // goals.add(s); 269 // r = new RoutePath(s, goals); 270 // } 271 // 272 // public void preLoop() 273 // { 274 // p1 = new GeoPoint(lat, 0); 275 // lat++; 276 // p2 = new GeoPoint(lat, 0); 277 // s = new GeoSegment("foo", p1, p2); 278 // g.addNode(s); 279 // } 280 // 281 // void profiledLoop() 282 // { 283 // g.getChildren(s).iterator().hasNext(); 284 // } 285 // } 286 287 public static void main(String[] args) 288 { 289 // new ExtendProfiler().run(100, 2000); 290 // new CostProfiler().run(100, 2000); 291 // new AddNodeProfiler().run(100, 10000); 292 // new GetChildrenProfiler().run(100, 10000); 293 } 294 }