BDE 4.14.0 Production release
Loading...
Searching...
No Matches
bsls_stopwatch.h
Go to the documentation of this file.
1/// @file bsls_stopwatch.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bsls_stopwatch.h -*-C++-*-
8#ifndef INCLUDED_BSLS_STOPWATCH
9#define INCLUDED_BSLS_STOPWATCH
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup bsls_stopwatch bsls_stopwatch
15/// @brief Provide access to user, system, and wall times of current process.
16/// @addtogroup bsl
17/// @{
18/// @addtogroup bsls
19/// @{
20/// @addtogroup bsls_stopwatch
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#bsls_stopwatch-purpose"> Purpose</a>
25/// * <a href="#bsls_stopwatch-classes"> Classes </a>
26/// * <a href="#bsls_stopwatch-description"> Description </a>
27/// * <a href="#bsls_stopwatch-accuracy-and-precision"> Accuracy and Precision </a>
28/// * <a href="#bsls_stopwatch-accuracy-on-windows"> Accuracy on Windows </a>
29/// * <a href="#bsls_stopwatch-usage-examples"> Usage Examples </a>
30///
31/// # Purpose {#bsls_stopwatch-purpose}
32/// Provide access to user, system, and wall times of current process.
33///
34/// # Classes {#bsls_stopwatch-classes}
35///
36/// - bsls::Stopwatch: accumulates user, system, wall times of current process
37///
38/// # Description {#bsls_stopwatch-description}
39/// This component provides a class, `bsls::Stopwatch`, that
40/// implements real-time (system clock) interval timers for the system, user,
41/// and wall times of the current process. A `bsls::Stopwatch` object can
42/// accumulate the above values from multiple runs and always presents only the
43/// final total (zero if never started or reset to the initial state).
44///
45/// ## Accuracy and Precision {#bsls_stopwatch-accuracy-and-precision}
46///
47///
48/// A `bsls::Stopwatch` object returns its elapsed time intervals in seconds as
49/// `double` values. The precision is given by that of the `bsls::TimeUtil`
50/// component, and, as such, strives to be as high as possible. Monotonic
51/// behavior is platform-dependent, however, as are accuracy and useful
52/// precision. The user is advised to determine the actual performance on each
53/// platform of interest. In general, it is better to avoid stopping and
54/// restarting the stopwatch too often (e.g., inside a loop). It is better to
55/// measure the overhead of the loop separately and subtract that time from the
56/// over-all time interval.
57///
58/// ### Accuracy on Windows {#bsls_stopwatch-accuracy-on-windows}
59///
60///
61/// `bsls::Stopwatch` may be slow or inconsistent on some Windows machines. See
62/// the `Accuracy and Precision` section of `bsls_timeutil.h`.
63///
64/// ## Usage Examples {#bsls_stopwatch-usage-examples}
65///
66///
67/// The following snippets of code illustrate basic use of a `bsls::Stopwatch`
68/// object. First we create a stopwatch and note that the accumulated times are
69/// all initially 0.0:
70/// @code
71/// bsls::Stopwatch s;
72/// const double t0s = s.accumulatedSystemTime(); assert(0.0 == t0s);
73/// const double t0u = s.accumulatedUserTime(); assert(0.0 == t0u);
74/// const double t0w = s.accumulatedWallTime(); assert(0.0 == t0w);
75/// @endcode
76/// Next we start the stopwatch such that it does not accumulate system or user
77/// times. Note that a stopwatch always accumulates wall time (i.e., as long as
78/// it is in the RUNNING state):
79/// @code
80/// s.start();
81/// const double t1s = s.accumulatedSystemTime(); assert(0.0 == t1s);
82/// const double t1u = s.accumulatedUserTime(); assert(0.0 == t1u);
83/// const double t1w = s.accumulatedWallTime(); assert(0.0 <= t1w);
84/// @endcode
85/// Now stop the stopwatch and restart it so as to accumulate system and user
86/// times (i.e., by passing `true` to the `start` method):
87/// @code
88/// s.stop();
89/// const double t2s = s.accumulatedSystemTime(); assert(t1s == t2s);
90/// const double t2u = s.accumulatedUserTime(); assert(t1u == t2u);
91/// const double t2w = s.accumulatedWallTime(); assert(t1w <= t2w);
92///
93/// s.start(bsls::Stopwatch::k_COLLECT_ALSO_CPU_TIMES);
94/// const double t3s = s.accumulatedSystemTime(); assert(t2s <= t3s);
95/// const double t3u = s.accumulatedUserTime(); assert(t2u <= t3u);
96/// const double t3w = s.accumulatedWallTime(); assert(t2w <= t3w);
97/// @endcode
98/// Finally, we reset the stopwatch, which both puts it into the STOPPED state
99/// and resets all accumulated times back to their initial state (i.e., 0.0):
100/// @code
101/// s.reset();
102/// const double t4s = s.accumulatedSystemTime(); assert(0.0 == t4s);
103/// const double t4u = s.accumulatedUserTime(); assert(0.0 == t4u);
104/// const double t4w = s.accumulatedWallTime(); assert(0.0 == t4w);
105/// const double t5s = s.accumulatedSystemTime(); assert(0.0 == t5s);
106/// const double t5u = s.accumulatedUserTime(); assert(0.0 == t5u);
107/// const double t5w = s.accumulatedWallTime(); assert(0.0 == t5w);
108/// @endcode
109/// @}
110/** @} */
111/** @} */
112
113/** @addtogroup bsl
114 * @{
115 */
116/** @addtogroup bsls
117 * @{
118 */
119/** @addtogroup bsls_stopwatch
120 * @{
121 */
122
123#include <bsls_keyword.h>
124#include <bsls_timeutil.h>
125#include <bsls_types.h>
126
127#include <string.h>
128
129
130namespace bsls {
131
132 // ===============
133 // class Stopwatch
134 // ===============
135
136/// The `class` provides an accumulator for the system, user, and wall times
137/// of the current process. A stopwatch can be in either the STOPPED
138/// (initial) state or the RUNNING state. It potentially tracks three
139/// values: the accumulated system time, the accumulated user time, and the
140/// accumulated wall time (all in seconds and all initially set to zero).
141/// Whether or not system and user times are accumulated is conditional on
142/// how the stopwatch is started (see the `start` method). While in the
143/// RUNNING state, a stopwatch accumulates the above values and it retains
144/// the values if put into the STOPPED state (unless `reset` is called).
145/// The accumulated times can be accessed at any time and in either state
146/// (RUNNING or STOPPED).
147///
148/// See @ref bsls_stopwatch
150
151 // DATA
152 Types::Int64 d_startSystemTime; // system time when started
153 // (nanoseconds)
154
155 Types::Int64 d_startUserTime; // user time when started
156 // (nanoseconds)
157
158 TimeUtil::OpaqueNativeTime d_startWallTime;
159 // wall time when started
160 // (nanoseconds)
161
162 Types::Int64 d_accumulatedSystemTime; // accumulated system time
163 // (nanoseconds)
164
165 Types::Int64 d_accumulatedUserTime; // accumulated user time
166 // (nanoseconds)
167
168 Types::Int64 d_accumulatedWallTime; // accumulated wall time
169 // (nanoseconds)
170
171 bool d_isRunning; // state flag ('true' if RUNNING,
172 // 'false' if STOPPED)
173
174 bool d_collectCpuTimesFlag; // 'true' if cpu times are being
175 // collected
176
177 // CLASS DATA
178 static const double s_nanosecondsPerSecond; // conversion factor
179 // (for nanoseconds to
180 // seconds)
181
182 private:
183 // NOT IMPLEMENTED
184 Stopwatch& operator=(const Stopwatch&) BSLS_KEYWORD_DELETED;
185
186 private:
187 // PRIVATE MANIPULATORS
188
189 /// Update the CPU times accumulated but this stopwatch.
190 void updateTimes();
191
192 // PRIVATE ACCESSORS
193
194 /// Load into the specified `systemTime`, `userTime`, and `wallTime` the
195 /// values of the system time, user time, and wall time (in
196 /// nanoseconds), respectively, as provided by `TimeUtil`.
197 void accumulatedTimesRaw(Types::Int64 *systemTime,
198 Types::Int64 *userTime,
199 TimeUtil::OpaqueNativeTime *wallTime) const;
200
201 /// Return the elapsed time, in nanoseconds, between the current
202 /// `d_startWallTime` and the specified `rawWallTime`.
203 Types::Int64 elapsedWallTime(TimeUtil::OpaqueNativeTime rawWallTime) const;
204
205 public:
206 // PUBLIC CONSTANTS
207 static const bool k_COLLECT_WALL_TIME_ONLY = false;
208
209 /// For readability/ease of understanding of code that calls the
210 /// `start(bool)` method use these constants as arguments.
211 static const bool k_COLLECT_WALL_AND_CPU_TIMES = true;
212
213 // CREATORS
214
215 /// Create a stopwatch in the STOPPED state having total accumulated
216 /// system, user, and wall times all equal to 0.0.
217 Stopwatch();
218
219#ifdef BSLS_COMPILERFEATURES_SUPPORT_DEFAULTED_FUNCTIONS
220 // To avoid warnings about future incompatibility due to the deleted copy
221 // assignment operator we declare the copy constructor as implicitly
222 // generated. For consistency the destructor was also placed here and
223 // declared to be explicitly generated.
224
225 /// Create a stopwatch having the state and total accumulated system,
226 /// user, and wall time of the specified `other` object. Note that this
227 /// method's definition is compiler generated.
228 Stopwatch(const Stopwatch& other) = default;
229
230 /// Destroy this stopwatch. Note that this method's definition is
231 /// compiler generated.
232 ~Stopwatch() = default;
233#endif
234
235 // MANIPULATORS
236
237 /// Place this stopwatch in the STOPPED state, unconditionally stopping
238 /// the accumulation of elapsed times, and set the quiescent elapsed
239 /// times to 0.0.
240 void reset();
241
242 /// Place this stopwatch in the RUNNING state and begin accumulating
243 /// elapsed times if this object was in the STOPPED state. Optionally
244 /// specify a `collectCpuTimes` flag indicating whether CPU times should
245 /// be collected. If `collectCpuTimes` is not specified, then CPU times
246 /// are *not* collected. Note that the instantaneous total elapsed
247 /// times are available from the RUNNING state. Also note that
248 /// disabling collection of CPU times will result in fewer systems calls
249 /// and therefore faster measurements. Also note that `collectCpuTimes`
250 /// may be expressed using the one of the class level constants
251 /// `k_COLLECT_WALL_TIME_ONLY`, and `k_COLLECT_WALL_AND_CPU_TIMES` for
252 /// easier immediate understanding of the meaning of the client code.
253 void start(bool collectCpuTimes = false);
254
255 /// Place this stopwatch in the STOPPED state, unconditionally stopping
256 /// the accumulation of elapsed times. Note that the quiescent
257 /// accumulated elapsed times are available while in the STOPPED state.
258 void stop();
259
260 // ACCESSORS
261
262 /// Return the total (instantaneous and quiescent) elapsed system time
263 /// (in seconds) accumulated by this stopwatch, or 0 if the collection
264 /// of CPU times is disabled.
265 double accumulatedSystemTime() const;
266
267 /// Load into the specified `systemTime`, `userTime` and `wallTime` the
268 /// total (instantaneous and quiescent) elapsed system, user, and wall
269 /// times (all in seconds) accumulated by this stopwatch. Note that
270 /// this method attempts to retrieve all of the values at the same time
271 /// (atomically), if the underlying platform supports it.
272 void accumulatedTimes(double *systemTime,
273 double *userTime,
274 double *wallTime) const;
275
276 /// Return the total (instantaneous and quiescent) elapsed user time (in
277 /// seconds) accumulated by this stopwatch, or 0 if the collection of
278 /// CPU times is disabled.
279 double accumulatedUserTime() const;
280
281 /// Return the total (instantaneous and quiescent) elapsed wall time (in
282 /// seconds) accumulated by this stopwatch.
283 double accumulatedWallTime() const;
284
285 /// Return the total (instantaneous and quiescent) elapsed wall time (in
286 /// seconds) accumulated by this stopwatch. Note that this method is
287 /// equivalent to `accumulatedWallTime`.
288 double elapsedTime() const;
289
290 /// Return `true` if this stopwatch is in the RUNNING state, and `false`
291 /// otherwise.
292 bool isRunning() const;
293};
294
295// ============================================================================
296// INLINE DEFINITIONS
297// ============================================================================
298
299 // ---------------
300 // class Stopwatch
301 // ---------------
302
303// PRIVATE ACCESSORS
304inline
305void Stopwatch::accumulatedTimesRaw(Types::Int64 *systemTime,
306 Types::Int64 *userTime,
307 TimeUtil::OpaqueNativeTime *wallTime) const
308{
309 TimeUtil::getProcessTimers(systemTime, userTime);
310 TimeUtil::getTimerRaw(wallTime);
311}
312
313inline
314Types::Int64 Stopwatch::elapsedWallTime(
315 TimeUtil::OpaqueNativeTime rawWallTime) const
316{
317 return TimeUtil::convertRawTime(rawWallTime)
318 - TimeUtil::convertRawTime(d_startWallTime);
319}
320
321// CREATORS
322inline
324: d_startSystemTime(0)
325, d_startUserTime(0)
326// , d_startWallTime(0) // opaque type, no default ctor from 0.
327, d_accumulatedSystemTime(0)
328, d_accumulatedUserTime(0)
329, d_accumulatedWallTime(0)
330, d_isRunning(false)
331, d_collectCpuTimesFlag(false)
332{
334 memset(&d_startWallTime, 0, sizeof(d_startWallTime));
335}
336
337// MANIPULATORS
338inline
340{
341 d_isRunning = false;
342 d_accumulatedSystemTime = 0;
343 d_accumulatedUserTime = 0;
344 d_accumulatedWallTime = 0;
345}
346
347inline
348void Stopwatch::start(bool collectCpuTimes)
349{
350 if (!d_isRunning) {
351 d_collectCpuTimesFlag = collectCpuTimes;
352 if (d_collectCpuTimesFlag) {
353 accumulatedTimesRaw(&d_startSystemTime,
354 &d_startUserTime,
355 &d_startWallTime);
356 }
357 else {
358 TimeUtil::getTimerRaw(&d_startWallTime);
359 }
360 d_isRunning = true;
361 }
362}
363
364inline
366{
367 if (d_isRunning) {
368 if (d_collectCpuTimesFlag) {
369 updateTimes();
370 }
371 else {
372 TimeUtil::OpaqueNativeTime now;
374 d_accumulatedWallTime += elapsedWallTime(now);
375 }
376 d_isRunning = false;
377 }
378}
379
380// ACCESSORS
381inline
383{
384 if (!d_collectCpuTimesFlag) {
385 return 0.0; // RETURN
386 }
387
388 if (d_isRunning) {
389 return (double)(d_accumulatedSystemTime
390 + TimeUtil::getProcessSystemTimer() - d_startSystemTime)
391 / s_nanosecondsPerSecond;
392 // RETURN
393 }
394 return (double)d_accumulatedSystemTime / s_nanosecondsPerSecond;
395}
396
397inline
399{
400 if (!d_collectCpuTimesFlag) {
401 return 0.0; // RETURN
402 }
403
404 if (d_isRunning) {
405 return (double)(d_accumulatedUserTime
406 + TimeUtil::getProcessUserTimer() - d_startUserTime)
407 / s_nanosecondsPerSecond;
408 // RETURN
409 }
410 return (double)d_accumulatedUserTime / s_nanosecondsPerSecond;
411}
412
413inline
415{
416 if (d_isRunning) {
417 TimeUtil::OpaqueNativeTime now;
419 return (double)(d_accumulatedWallTime + elapsedWallTime(now))
420 / s_nanosecondsPerSecond;
421 // RETURN
422 }
423 return (double)d_accumulatedWallTime / s_nanosecondsPerSecond;
424}
425
426inline
428{
429 return accumulatedWallTime();
430}
431
432inline
434{
435 return d_isRunning;
436}
437
438} // close package namespace
439
440#ifndef BDE_OPENSOURCE_PUBLICATION // BACKWARD_COMPATIBILITY
441// ============================================================================
442// BACKWARD COMPATIBILITY
443// ============================================================================
444
445/// This alias is defined for backward compatibility.
447#endif // BDE_OPENSOURCE_PUBLICATION -- BACKWARD_COMPATIBILITY
448
449
450
451#endif
452
453// ----------------------------------------------------------------------------
454// Copyright 2016 Bloomberg Finance L.P.
455//
456// Licensed under the Apache License, Version 2.0 (the "License");
457// you may not use this file except in compliance with the License.
458// You may obtain a copy of the License at
459//
460// http://www.apache.org/licenses/LICENSE-2.0
461//
462// Unless required by applicable law or agreed to in writing, software
463// distributed under the License is distributed on an "AS IS" BASIS,
464// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
465// See the License for the specific language governing permissions and
466// limitations under the License.
467// ----------------------------- END-OF-FILE ----------------------------------
468
469/** @} */
470/** @} */
471/** @} */
Definition bsls_stopwatch.h:149
double accumulatedWallTime() const
Definition bsls_stopwatch.h:414
static const bool k_COLLECT_WALL_TIME_ONLY
Definition bsls_stopwatch.h:207
void stop()
Definition bsls_stopwatch.h:365
void start(bool collectCpuTimes=false)
Definition bsls_stopwatch.h:348
double accumulatedUserTime() const
Definition bsls_stopwatch.h:398
double accumulatedSystemTime() const
Definition bsls_stopwatch.h:382
void accumulatedTimes(double *systemTime, double *userTime, double *wallTime) const
Stopwatch()
Definition bsls_stopwatch.h:323
void reset()
Definition bsls_stopwatch.h:339
double elapsedTime() const
Definition bsls_stopwatch.h:427
static const bool k_COLLECT_WALL_AND_CPU_TIMES
Definition bsls_stopwatch.h:211
bool isRunning() const
Definition bsls_stopwatch.h:433
#define BSLS_IDENT(str)
Definition bsls_ident.h:195
#define BSLS_KEYWORD_DELETED
Definition bsls_keyword.h:609
bsls::Stopwatch bsls_Stopwatch
This alias is defined for backward compatibility.
Definition bsls_stopwatch.h:446
Definition bdlt_iso8601util.h:691
static Types::Int64 convertRawTime(OpaqueNativeTime rawTime)
static void initialize()
static Types::Int64 getProcessUserTimer()
static void getTimerRaw(OpaqueNativeTime *timeValue)
static void getProcessTimers(Types::Int64 *systemTimer, Types::Int64 *userTimer)
static Types::Int64 getProcessSystemTimer()
long long Int64
Definition bsls_types.h:132