001 // Copyright (c) 2001 Hursh Jain (http://www.mollypages.org)
002 // The Molly framework is freely distributable under the terms of an
003 // MIT-style license. For details, see the molly pages web site at:
004 // http://www.mollypages.org/. Use, modify, have fun !
005
006 package fc.util;
007
008 /**
009 Allows measuring the start and stop time and (hence the elapsed time) of
010 some event. ("event" meaning something of interest, for example, a method
011 call). Can be started/stopped repeatedly. (cumulative time across all such
012 start/stops are available via the {@link #cumulativeTime} method).
013 <p>
014 All times are in <i>nano-seconds</i>.
015 <p>
016 Thread Safety: This class is <b>not</b> threadsafe and it's method
017 do <b>not</b> acquire any locks to reduce any time skew due to
018 lock acquisition. Multiple threads should use separate NanoWatch
019 objects or alternatively, higher level synchronization.
020
021 @author hursh jain
022 @see Watch A lower precision (milliseconds) watch.
023 */
024 public final class NanoWatch extends Watch
025 {
026 public NanoWatch(String name) {
027 super(name);
028 }
029
030 public NanoWatch() {
031 super("DefaultNanoWatch/" + Thread.currentThread().getName());
032 }
033
034 /**
035 Start measuring time. Call this method just before calling the
036 method/code to be instrumented. This method does <b>not</b> reset the
037 Watch, so the reset method should be called before calling this method
038 <b>again</b>.
039 */
040 public NanoWatch start() {
041 startTime = System.nanoTime();
042 running = true;
043 return this;
044 }
045
046 /** Stop measuring the time */
047 public void stop() {
048 stopTime = System.nanoTime();
049 cumulativeTime += (stopTime - startTime);
050 running = false;
051 }
052
053
054 /**
055 Returns the time elapsed since the Watch was started. If the watch was
056 started and stopped, returns the time between the start/stop interval.
057
058 @throws RuntimeException if the watch was never started before calling
059 this method.
060 */
061 public long time()
062 {
063 if (startTime == -1)
064 throw new RuntimeException("You need to start the watch at least once before calling this method");
065
066 if (running)
067 return System.nanoTime() - startTime;
068
069 return stopTime - startTime;
070 }
071
072 /**
073 Returns the time elapsed since the Watch was started. (this method is
074 an alias for {@link #time} method).
075 */
076 public long getTime()
077 {
078 return time();
079 }
080
081 private static final double ms_factor = 1.0 / 1000000.00D;
082
083 /**
084 Returns the elapsed time in milliseconds. Useful when nanosecond values are
085 too hard to read.
086 */
087 public double getTimeInMillis()
088 {
089 long t = time();
090 return t * ms_factor;
091 }
092
093
094 /**
095 Returns the total time recorded by this Watch (across several starts/stops)
096 */
097 public long cumulativeTime()
098 {
099 if (! running)
100 return cumulativeTime;
101
102 return cumulativeTime + (System.nanoTime() - startTime);
103 }
104
105 /**
106 Reset all values to zero. This method should be called
107 before this object is used <b>again</b>.
108 */
109 public void reset()
110 {
111 startTime = stopTime = 0;
112 }
113
114 /** Is the Watch currently running ? */
115 public boolean isRunning() {
116 return running;
117 }
118
119 /**
120 Get the start time (in nanoseconds), the start time is arbitrary (see
121 {@link System#nanoTime}).
122 */
123 protected long getStart() {
124 return startTime;
125 }
126
127 /**
128 Get the stop time (in nanoseconds). Useful only as a difference from
129 the start time
130 */
131 protected long getStop() {
132 return stopTime;
133 }
134
135 public String toString()
136 {
137 java.text.NumberFormat nf = java.text.NumberFormat.getNumberInstance();
138 nf.setGroupingUsed(true);
139
140 String str = myname;
141
142 str += ": Cum.Time=[" + nf.format(cumulativeTime()) + " nanoseconds]";
143
144 if (running)
145 str += "; Elapsed=[" + nf.format(time()) + " nanoseconds]";
146
147 return str;
148 }
149
150 public static void main(String[] args)
151 {
152 fc.util.Watch t1 = new fc.util.NanoWatch("NanoWatch 1");
153 t1.start();
154
155 new Thread(new Runnable() {
156 public void run() {
157 try {
158 Watch t2 = new NanoWatch();
159 t2.start(); Thread.currentThread().sleep(20); t2.stop();
160 System.out.println("t2.toString():" + t2);
161 }
162 catch (Exception e) { e.printStackTrace(); }
163 }
164 }).start();
165
166 //following should return -1
167 System.out.println("NanoWatch 1, total time taken:" + t1.time());
168
169 System.out.println("NanoWatch 1, time=" + t1.time());
170 System.out.println("NanoWatch 1, before-being-stopped, toString():" + t1);
171 t1.stop();
172 System.out.println("NanoWatch 1, is running ? " + t1.isRunning() );
173 System.out.println("NanoWatch 1, after-being-stopped, toString():" + t1);
174 System.out.println("NanoWatch 1, elapsed time:" + t1.time());
175 System.out.println("NanoWatch 1, cumulative time taken:" + t1.cumulativeTime());
176 System.out.println("NanoWatch 1, elapsed time:" + t1.time());
177 }
178
179 } //~class NanoWatch