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    }