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