132
|
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 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 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 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 }
|