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 }