source: trunk/demos/spectrum/3rdparty/fftreal/stopwatch/ClockCycleCounter.cpp

Last change on this file was 769, checked in by Dmitry A. Kuminov, 15 years ago

trunk: Merged in qt 4.6.3 sources from branches/vendor/nokia/qt.

File size: 6.9 KB
Line 
1/*****************************************************************************
2
3 ClockCycleCounter.cpp
4 Copyright (c) 2003 Laurent de Soras
5
6--- Legal stuff ---
7
8This library is free software; you can redistribute it and/or
9modify it under the terms of the GNU Lesser General Public
10License as published by the Free Software Foundation; either
11version 2.1 of the License, or (at your option) any later version.
12
13This library is distributed in the hope that it will be useful,
14but WITHOUT ANY WARRANTY; without even the implied warranty of
15MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16Lesser General Public License for more details.
17
18You should have received a copy of the GNU Lesser General Public
19License along with this library; if not, write to the Free Software
20Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21
22*Tab=3***********************************************************************/
23
24
25
26#if defined (_MSC_VER)
27 #pragma warning (1 : 4130) // "'operator' : logical operation on address of string constant"
28 #pragma warning (1 : 4223) // "nonstandard extension used : non-lvalue array converted to pointer"
29 #pragma warning (1 : 4705) // "statement has no effect"
30 #pragma warning (1 : 4706) // "assignment within conditional expression"
31 #pragma warning (4 : 4786) // "identifier was truncated to '255' characters in the debug information"
32 #pragma warning (4 : 4800) // "forcing value to bool 'true' or 'false' (performance warning)"
33 #pragma warning (4 : 4355) // "'this' : used in base member initializer list"
34#endif
35
36
37
38/*\\\ INCLUDE FILES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/
39
40#include "ClockCycleCounter.h"
41
42#include <cassert>
43
44
45
46namespace stopwatch
47{
48
49
50
51/*\\\ PUBLIC \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/
52
53
54
55/*
56==============================================================================
57Name: ctor
58Description:
59 The first object constructed initialise global data. This first
60 construction may be a bit slow.
61Throws: Nothing
62==============================================================================
63*/
64
65ClockCycleCounter::ClockCycleCounter ()
66: _start_time (0)
67, _state (0)
68, _best_score (-1)
69{
70 if (! _init_flag)
71 {
72 // Should be executed in this order
73 compute_clk_mul ();
74 compute_measure_time_total ();
75 compute_measure_time_lap ();
76
77 // Restores object state
78 _start_time = 0;
79 _state = 0;
80 _best_score = -1;
81
82 _init_flag = true;
83 }
84}
85
86
87
88/*
89==============================================================================
90Name: get_time_total
91Description:
92 Gives the time elapsed between the latest stop_lap() and start() calls.
93Returns:
94 The duration, in clock cycles.
95Throws: Nothing
96==============================================================================
97*/
98
99Int64 ClockCycleCounter::get_time_total () const
100{
101 const Int64 duration = _state - _start_time;
102 assert (duration >= 0);
103
104 const Int64 t = max (
105 duration - _measure_time_total,
106 static_cast <Int64> (0)
107 );
108
109 return (t * _clk_mul);
110}
111
112
113
114/*
115==============================================================================
116Name: get_time_best_lap
117Description:
118 Gives the smallest time between two consecutive stop_lap() or between
119 the stop_lap() and start(). The value is reset by a call to start().
120 Call this function only after a stop_lap().
121 The time is amputed from the duration of the stop_lap() call itself.
122Returns:
123 The smallest duration, in clock cycles.
124Throws: Nothing
125==============================================================================
126*/
127
128Int64 ClockCycleCounter::get_time_best_lap () const
129{
130 assert (_best_score >= 0);
131
132 const Int64 t1 = max (
133 _best_score - _measure_time_lap,
134 static_cast <Int64> (0)
135 );
136 const Int64 t = min (t1, get_time_total ());
137
138 return (t * _clk_mul);
139}
140
141
142
143/*\\\ PROTECTED \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/
144
145
146
147/*\\\ PRIVATE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/
148
149
150
151#if defined (__MACOS__)
152
153static inline double stopwatch_ClockCycleCounter_get_time_s ()
154{
155 const Nanoseconds ns = AbsoluteToNanoseconds (UpTime ());
156
157 return (ns.hi * 4294967296e-9 + ns.lo * 1e-9);
158}
159
160#endif // __MACOS__
161
162
163
164/*
165==============================================================================
166Name: compute_clk_mul
167Description:
168 This function, only for PowerPC/MacOS computers, computes the multiplier
169 required to deduce clock cycles from the internal counter.
170Throws: Nothing
171==============================================================================
172*/
173
174void ClockCycleCounter::compute_clk_mul ()
175{
176 assert (! _init_flag);
177
178#if defined (__MACOS__)
179
180 long clk_speed_mhz = CurrentProcessorSpeed ();
181 const Int64 clk_speed =
182 static_cast <Int64> (clk_speed_mhz) * (1000L*1000L);
183
184 const double start_time_s = stopwatch_ClockCycleCounter_get_time_s ();
185 start ();
186
187 const double duration = 0.01; // Seconds
188 while (stopwatch_ClockCycleCounter_get_time_s () - start_time_s < duration)
189 {
190 continue;
191 }
192
193 const double stop_time_s = stopwatch_ClockCycleCounter_get_time_s ();
194 stop ();
195
196 const double diff_time_s = stop_time_s - start_time_s;
197 const double nbr_cycles = diff_time_s * static_cast <double> (clk_speed);
198
199 const Int64 diff_time_c = _state - _start_time;
200 const double clk_mul = nbr_cycles / static_cast <double> (diff_time_c);
201
202 _clk_mul = round_int (clk_mul);
203
204#endif // __MACOS__
205}
206
207
208
209void ClockCycleCounter::compute_measure_time_total ()
210{
211 start ();
212 spend_time ();
213
214 Int64 best_result = 0x7FFFFFFFL; // Should be enough
215 long nbr_tests = 100;
216 for (long cnt = 0; cnt < nbr_tests; ++cnt)
217 {
218 start ();
219 stop_lap ();
220 const Int64 duration = _state - _start_time;
221 best_result = min (best_result, duration);
222 }
223
224 _measure_time_total = best_result;
225}
226
227
228
229/*
230==============================================================================
231Name: compute_measure_time_lap
232Description:
233 Computes the duration of one stop_lap() call and store it. It will be used
234 later to get the real duration of the measured operation (by substracting
235 the measurement duration).
236Throws: Nothing
237==============================================================================
238*/
239
240void ClockCycleCounter::compute_measure_time_lap ()
241{
242 start ();
243 spend_time ();
244
245 long nbr_tests = 10;
246 for (long cnt = 0; cnt < nbr_tests; ++cnt)
247 {
248 stop_lap ();
249 stop_lap ();
250 stop_lap ();
251 stop_lap ();
252 }
253
254 _measure_time_lap = _best_score;
255}
256
257
258
259void ClockCycleCounter::spend_time ()
260{
261 const Int64 nbr_clocks = 500; // Number of clock cycles to spend
262
263 const Int64 start = read_clock_counter ();
264 Int64 current;
265
266 do
267 {
268 current = read_clock_counter ();
269 }
270 while ((current - start) * _clk_mul < nbr_clocks);
271}
272
273
274
275Int64 ClockCycleCounter::_measure_time_total = 0;
276Int64 ClockCycleCounter::_measure_time_lap = 0;
277int ClockCycleCounter::_clk_mul = 1;
278bool ClockCycleCounter::_init_flag = false;
279
280
281} // namespace stopwatch
282
283
284
285/*\\\ EOF \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/
Note: See TracBrowser for help on using the repository browser.