1 /******************************************************************************* 2 3 copyright: Copyright (c) 2007 Kris Bell. All rights reserved 4 5 license: BSD style: $(LICENSE) 6 7 version: Feb 2007: Initial release 8 9 author: Kris 10 11 *******************************************************************************/ 12 13 module tango.time.StopWatch; 14 15 private import tango.core.Exception; 16 17 /******************************************************************************* 18 19 *******************************************************************************/ 20 21 version (Win32) 22 { 23 private extern (Windows) 24 { 25 int QueryPerformanceCounter (ulong *count); 26 int QueryPerformanceFrequency (ulong *frequency); 27 } 28 } 29 30 version (Posix) 31 { 32 private import tango.stdc.posix.sys.time; 33 } 34 35 /******************************************************************************* 36 37 Timer for measuring small intervals, such as the duration of a 38 subroutine or other reasonably small period. 39 --- 40 StopWatch elapsed; 41 42 elapsed.start; 43 44 // do something 45 // ... 46 47 double i = elapsed.stop; 48 --- 49 50 The measured interval is in units of seconds, using floating- 51 point to represent fractions. This approach is more flexible 52 than integer arithmetic since it migrates trivially to more 53 capable timer hardware (there no implicit granularity to the 54 measurable intervals, except the limits of fp representation) 55 56 StopWatch is accurate to the extent of what the underlying OS 57 supports. On linux systems, this accuracy is typically 1 us at 58 best. Win32 is generally more precise. 59 60 There is some minor overhead in using StopWatch, so take that into 61 account 62 63 *******************************************************************************/ 64 65 public struct StopWatch 66 { 67 private ulong started; 68 private static double multiplier = 1.0 / 1_000_000.0; 69 70 version (Win32) 71 private static double microsecond; 72 73 /*********************************************************************** 74 75 Start the timer 76 77 ***********************************************************************/ 78 79 void start () 80 { 81 started = timer; 82 } 83 84 /*********************************************************************** 85 86 Stop the timer and return elapsed duration since start() 87 88 ***********************************************************************/ 89 90 double stop () 91 { 92 return multiplier * (timer - started); 93 } 94 95 /*********************************************************************** 96 97 Return elapsed time since the last start() as microseconds 98 99 ***********************************************************************/ 100 101 @property ulong microsec () 102 { 103 version (Posix) 104 return (timer - started); 105 106 version (Win32) 107 return cast(ulong) ((timer - started) * microsecond); 108 } 109 110 /*********************************************************************** 111 112 Setup timing information for later use 113 114 ***********************************************************************/ 115 116 shared static this() 117 { 118 version (Win32) 119 { 120 ulong freq; 121 122 QueryPerformanceFrequency (&freq); 123 microsecond = 1_000_000.0 / freq; 124 multiplier = 1.0 / freq; 125 } 126 } 127 128 /*********************************************************************** 129 130 Return the current time as an Interval 131 132 ***********************************************************************/ 133 134 @property private static ulong timer () 135 { 136 version (Posix) 137 { 138 timeval tv; 139 if (gettimeofday (&tv, null)) 140 throw new PlatformException ("Timer :: linux timer is not available"); 141 142 return (cast(ulong) tv.tv_sec * 1_000_000) + tv.tv_usec; 143 } 144 145 version (Win32) 146 { 147 ulong now; 148 149 if (! QueryPerformanceCounter (&now)) 150 throw new PlatformException ("high-resolution timer is not available"); 151 152 return now; 153 } 154 } 155 } 156 157 158 /******************************************************************************* 159 160 *******************************************************************************/ 161 162 debug (StopWatch) 163 { 164 import tango.io.Stdout; 165 166 void main() 167 { 168 StopWatch t; 169 t.start; 170 171 for (int i=0; i < 100_000_000; ++i) 172 {} 173 Stdout.format ("{:f9}", t.stop).newline; 174 } 175 }