001/**
002 * Copyright 2001 Sun Microsystems, Inc.
003 * 
004 * See the file "license.terms" for information on usage and
005 * redistribution of this file, and for a DISCLAIMER OF ALL 
006 * WARRANTIES.
007 */
008package com.sun.speech.freetts.util;
009
010import java.text.DecimalFormat;
011
012/**
013 * Keeps track of execution times.
014 */
015public class Timer {
016    private final static DecimalFormat timeFormatter 
017        = new DecimalFormat("###0.0000");
018    private final static DecimalFormat percentFormatter 
019        = new DecimalFormat("###0.00%");
020    private String name;
021    private long startTime;
022    private long curTime;
023    private long count;
024    private double sum;
025    private long minTime = Long.MAX_VALUE;
026    private long maxTime = 0L;
027    private boolean notReliable; // if true, timing is not reliable
028
029    /**
030     * Creates a timer.
031     *
032     * @param name the name of the timer
033     */
034    public Timer(String name) {
035         this.name = name;
036         reset();
037    }
038
039    /**
040     * Resets the timer as if it has never run before.
041     */
042    public void reset() {
043        startTime = 0L;
044        count = 0L;
045        sum = 0L;
046        minTime = Long.MAX_VALUE;
047        maxTime = 0L;
048        notReliable = false;
049    }
050
051    /**
052     * Starts the timer running.
053     */
054    public void start() {
055        if (startTime != 0L) {
056            notReliable = true;
057        // throw new IllegalStateException("timer stutter start " + name);
058        }
059        startTime = System.currentTimeMillis();
060    }
061
062
063    /**
064     * Returns the current time.
065     *
066     * @return the current time
067     */
068    public long getCurrentTime() {
069        return curTime;
070    }
071
072    /**
073     * Stops the timer.
074     *
075     * @param verbose if <code>true</code>, print out details from
076     *  this run; otherwise, don't print the details
077     */
078    public void stop(boolean verbose) {
079        if (startTime == 0L) {
080            notReliable = true;
081        }
082        curTime = System.currentTimeMillis() - startTime;
083        startTime = 0L;
084        if (curTime > maxTime) {
085            maxTime = curTime;
086        }
087        if (curTime < minTime) {
088            minTime = curTime;
089        }
090        count++;
091        sum += curTime;
092        if (verbose) {
093            showTimesShort(0L);
094        }
095    }
096
097    /**
098     * Stops the timer.
099     */
100    public void stop() {
101        stop(false);
102    }
103
104    /**
105     * Formats times into a standard format.
106     *
107     * @param time the time (in milliseconds) to be formatted
108     *
109     * @return a string representation of the time.
110     */
111    private String fmtTime(long time) {
112        return fmtTime(time/1000.0);
113    }
114
115    /**
116     * Formats times into a standard format.
117     *
118     * @param time the time (in seconds) to be formatted
119     *
120     * @return a string representation of the time.
121     */
122    private String fmtTime(double time) {
123        return Utilities.pad(timeFormatter.format(time) + "s", 10);
124    }
125
126    /**
127     * Shows detailed timing stats. If overall is non-zero, it represents
128     * the overall processing time and a percentage of overall
129     * time for this timer should be calculated and displayed.
130     *
131     * @param overall the overall processing time in milliseconds or 0.
132     */
133    public void showTimesLong(long overall) {
134        System.out.println(" Timer:    " + name);
135        System.out.println(" Count:    " + count);
136
137        if (notReliable) {
138                System.out.println(" Not reliable");
139        } else {
140            if (count == 1) {
141                System.out.println(" Cur Time: " + fmtTime(curTime));
142            } else if (count > 1) {
143                System.out.println(" Min Time: " + fmtTime(minTime));
144                System.out.println(" Max Time: " + fmtTime(maxTime));
145                System.out.println(" Avg Time: " 
146                        + fmtTime(sum / count / 1000.0));
147                System.out.println(" Tot Time: " + fmtTime(sum /1000.0));
148                if (overall != 0) {
149                    System.out.println(" Percent:  " 
150                            + percentFormatter.format(sum / overall));
151                }
152            }
153        }
154        System.out.println();
155    }
156
157    /**
158     * Shows the timing stats title.
159     *
160     * @param title shows the title and column headings for the time
161     *  display
162     */
163    public static void showTimesShortTitle(String title) {
164        String titleBar =
165             "# ----------------------------- " + title +
166             "----------------------------------------------------------- ";
167        System.out.println(Utilities.pad(titleBar, 78));
168        System.out.print(Utilities.pad("# Name", 15) + " ");
169        System.out.print(Utilities.pad("Count", 6));
170        System.out.print(Utilities.pad("CurTime", 10));
171        System.out.print(Utilities.pad("MinTime", 10));
172        System.out.print(Utilities.pad("MaxTime", 10));
173        System.out.print(Utilities.pad("AvgTime", 10));
174        System.out.print(Utilities.pad("TotTime", 10));
175        System.out.print(Utilities.pad("% Total", 8));
176        System.out.println();
177    }
178    /**
179     * Shows brief timing stats. If overall is non-zero, it represents
180     * the overall processing time and a percentage of overall
181     * time for this timer should be calculated and displayed.
182     *
183     * @param overall the overall processing time in milliseconds or 0.
184     */
185    public void showTimesShort(long overall) {
186        double avgTime  = 0.0;
187        double overallPercent = 0;
188
189        /*
190        if (curTime == 0) {
191            return;
192        }
193        */
194
195        if (count == 0) {
196            return;
197        }
198        
199        if (count > 0) {
200            avgTime = sum / count / 1000.0;
201        }
202
203        if (overall != 0) {
204            overallPercent = sum / overall;
205        }
206
207        if (notReliable) {
208            System.out.print(Utilities.pad(name, 15) + " ");
209            System.out.println("Not reliable.");
210        } else {
211            System.out.print(Utilities.pad(name, 15) + " ");
212            System.out.print(Utilities.pad("" + count, 6));
213            System.out.print(fmtTime(curTime));
214            System.out.print(fmtTime(minTime));
215            System.out.print(fmtTime(maxTime));
216            System.out.print(fmtTime(avgTime));
217            System.out.print(fmtTime(sum / 1000.0));
218            System.out.print(percentFormatter.format(overallPercent));
219            System.out.println();
220        }
221    }
222
223    /**
224     * Shows timing stats. If overall is non-zero, it represents
225     * the overall processing time and a percentage of overall
226     * time for this timer should be calculated and displayed.
227     *
228     * @param overall the overall processing time in milliseconds or 0.
229     */
230    public void showTimes(long overall) {
231        showTimesShort(overall);
232    }
233
234    /**
235     * Shows timing stats. No overall percentage is shown with this
236     * method.
237     */
238    public void showTimes() {
239        // showTimes(0L);
240        showTimesShort(0L);
241    }
242
243    /**
244     * The main program for performing simple tests. Creates a timer
245     * uses it and shows its output.
246     *
247     * @param args      program arguments (not used)
248     */
249    public static void main(String[] args) {
250           Timer timer = new Timer("testTimer");
251           Timer overallTimer = new Timer("overall");
252           timer.showTimes(0L);
253
254           overallTimer.start();
255
256           for (int i = 0; i < 5; i++) {
257               timer.start();
258               try {
259                   Thread.sleep(i * 1000L);
260                } catch (InterruptedException e) {
261                }
262               timer.stop(true);
263           }
264           overallTimer.stop();
265           timer.showTimes(overallTimer.getCurrentTime());
266           overallTimer.showTimes();
267    }
268}
269