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 006package fc.util; 007 008/** 009Allows measuring the start and stop time and (hence the elapsed time) of 010some event. ("event" meaning something of interest, for example, a method 011call). Can be started/stopped repeatedly. (cumulative time across all such 012start/stops are available via the {@link #cumulativeTime} method). 013<p> 014All times are in <i>nano-seconds</i>. 015<p> 016Thread Safety: This class is <b>not</b> threadsafe and it's method 017do <b>not</b> acquire any locks to reduce any time skew due to 018lock acquisition. Multiple threads should use separate NanoWatch 019objects or alternatively, higher level synchronization. 020 021@author hursh jain 022@see Watch A lower precision (milliseconds) watch. 023*/ 024public final class NanoWatch extends Watch 025{ 026public NanoWatch(String name) { 027 super(name); 028 } 029 030public NanoWatch() { 031 super("DefaultNanoWatch/" + Thread.currentThread().getName()); 032 } 033 034/** 035Start measuring time. Call this method just before calling the 036method/code to be instrumented. This method does <b>not</b> reset the 037Watch, so the reset method should be called before calling this method 038<b>again</b>. 039*/ 040public NanoWatch start() { 041 startTime = System.nanoTime(); 042 running = true; 043 return this; 044 } 045 046/** Stop measuring the time */ 047public void stop() { 048 stopTime = System.nanoTime(); 049 cumulativeTime += (stopTime - startTime); 050 running = false; 051 } 052 053 054/** 055Returns the time elapsed since the Watch was started. If the watch was 056started 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*/ 061public 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/** 073Returns the time elapsed since the Watch was started. (this method is 074an alias for {@link #time} method). 075*/ 076public long getTime() 077 { 078 return time(); 079 } 080 081private static final double ms_factor = 1.0 / 1000000.00D; 082 083/** 084Returns the elapsed time in milliseconds. Useful when nanosecond values are 085too hard to read. 086*/ 087public double getTimeInMillis() 088 { 089 long t = time(); 090 return t * ms_factor; 091 } 092 093 094/** 095Returns the total time recorded by this Watch (across several starts/stops) 096*/ 097public long cumulativeTime() 098 { 099 if (! running) 100 return cumulativeTime; 101 102 return cumulativeTime + (System.nanoTime() - startTime); 103 } 104 105/** 106Reset all values to zero. This method should be called 107before this object is used <b>again</b>. 108*/ 109public void reset() 110 { 111 startTime = stopTime = 0; 112 } 113 114/** Is the Watch currently running ? */ 115public boolean isRunning() { 116 return running; 117 } 118 119/** 120Get the start time (in nanoseconds), the start time is arbitrary (see 121{@link System#nanoTime}). 122*/ 123protected long getStart() { 124 return startTime; 125 } 126 127/** 128Get the stop time (in nanoseconds). Useful only as a difference from 129the start time 130*/ 131protected long getStop() { 132 return stopTime; 133 } 134 135public 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 150public 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