BDE 4.39.x 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, user, and wall time of the specified `other` object.
226 ///
227 /// \note Note that this
228 /// method's definition is compiler generated.
229 Stopwatch(const Stopwatch& other) = default;
230
231 /// Destroy this stopwatch.
232 /// \note Note that this method's definition is
233 /// compiler generated.
234 ~Stopwatch() = default;
235#endif
236
237 // MANIPULATORS
238
239 /// Place this stopwatch in the STOPPED state, unconditionally stopping
240 /// the accumulation of elapsed times, and set the quiescent elapsed
241 /// times to 0.0.
242 void reset();
243
244 /// Place this stopwatch in the RUNNING state and begin accumulating
245 /// elapsed times if this object was in the STOPPED state. Optionally
246 /// specify a `collectCpuTimes` flag indicating whether CPU times should
247 /// be collected. If `collectCpuTimes` is not specified, then CPU times are *not* collected.
248 ///
249 /// \note Note that the instantaneous total elapsed
250 /// times are available from the RUNNING state. Also note that
251 /// disabling collection of CPU times will result in fewer systems calls
252 /// and therefore faster measurements. Also note that `collectCpuTimes`
253 /// may be expressed using the one of the class level constants
254 /// `k_COLLECT_WALL_TIME_ONLY`, and `k_COLLECT_WALL_AND_CPU_TIMES` for
255 /// easier immediate understanding of the meaning of the client code.
256 void start(bool collectCpuTimes = false);
257
258 /// Place this stopwatch in the STOPPED state, unconditionally stopping the accumulation of elapsed times.
259 ///
260 /// \note Note that the quiescent
261 /// accumulated elapsed times are available while in the STOPPED state.
262 void stop();
263
264 // ACCESSORS
265
266 /// Return the total (instantaneous and quiescent) elapsed system time
267 /// (in seconds) accumulated by this stopwatch, or 0 if the collection
268 /// of CPU times is disabled.
269 double accumulatedSystemTime() const;
270
271 /// Load into the specified `systemTime`, `userTime` and `wallTime` the
272 /// total (instantaneous and quiescent) elapsed system, user, and wall
273 /// times (all in seconds) accumulated by this stopwatch.
274 ///
275 /// \note Note that this method attempts to retrieve all of the values at the same time
276 /// (atomically), if the underlying platform supports it.
277 void accumulatedTimes(double *systemTime,
278 double *userTime,
279 double *wallTime) const;
280
281 /// Return the total (instantaneous and quiescent) elapsed user time (in
282 /// seconds) accumulated by this stopwatch, or 0 if the collection of
283 /// CPU times is disabled.
284 double accumulatedUserTime() const;
285
286 /// Return the total (instantaneous and quiescent) elapsed wall time (in
287 /// seconds) accumulated by this stopwatch.
288 double accumulatedWallTime() const;
289
290 /// Return the total (instantaneous and quiescent) elapsed wall time (in seconds) accumulated by this stopwatch.
291 ///
292 /// \note Note that this method is
293 /// equivalent to `accumulatedWallTime`.
294 double elapsedTime() const;
295
296 /// Return `true` if this stopwatch is in the RUNNING state, and `false`
297 /// otherwise.
298 bool isRunning() const;
299};
300
301// ============================================================================
302// INLINE DEFINITIONS
303// ============================================================================
304
305 // ---------------
306 // class Stopwatch
307 // ---------------
308
309// PRIVATE ACCESSORS
310inline
311void Stopwatch::accumulatedTimesRaw(Types::Int64 *systemTime,
312 Types::Int64 *userTime,
313 TimeUtil::OpaqueNativeTime *wallTime) const
314{
315 TimeUtil::getProcessTimers(systemTime, userTime);
316 TimeUtil::getTimerRaw(wallTime);
317}
318
319inline
320Types::Int64 Stopwatch::elapsedWallTime(
321 TimeUtil::OpaqueNativeTime rawWallTime) const
322{
323 return TimeUtil::convertRawTime(rawWallTime)
324 - TimeUtil::convertRawTime(d_startWallTime);
325}
326
327// CREATORS
328inline
330: d_startSystemTime(0)
331, d_startUserTime(0)
332// , d_startWallTime(0) // opaque type, no default ctor from 0.
333, d_accumulatedSystemTime(0)
334, d_accumulatedUserTime(0)
335, d_accumulatedWallTime(0)
336, d_isRunning(false)
337, d_collectCpuTimesFlag(false)
338{
340 memset(&d_startWallTime, 0, sizeof(d_startWallTime));
341}
342
343// MANIPULATORS
344inline
346{
347 d_isRunning = false;
348 d_accumulatedSystemTime = 0;
349 d_accumulatedUserTime = 0;
350 d_accumulatedWallTime = 0;
351}
352
353inline
354void Stopwatch::start(bool collectCpuTimes)
355{
356 if (!d_isRunning) {
357 d_collectCpuTimesFlag = collectCpuTimes;
358 if (d_collectCpuTimesFlag) {
359 accumulatedTimesRaw(&d_startSystemTime,
360 &d_startUserTime,
361 &d_startWallTime);
362 }
363 else {
364 TimeUtil::getTimerRaw(&d_startWallTime);
365 }
366 d_isRunning = true;
367 }
368}
369
370inline
372{
373 if (d_isRunning) {
374 if (d_collectCpuTimesFlag) {
375 updateTimes();
376 }
377 else {
378 TimeUtil::OpaqueNativeTime now;
380 d_accumulatedWallTime += elapsedWallTime(now);
381 }
382 d_isRunning = false;
383 }
384}
385
386// ACCESSORS
387inline
389{
390 if (!d_collectCpuTimesFlag) {
391 return 0.0; // RETURN
392 }
393
394 if (d_isRunning) {
395 return (double)(d_accumulatedSystemTime
396 + TimeUtil::getProcessSystemTimer() - d_startSystemTime)
397 / s_nanosecondsPerSecond;
398 // RETURN
399 }
400 return (double)d_accumulatedSystemTime / s_nanosecondsPerSecond;
401}
402
403inline
405{
406 if (!d_collectCpuTimesFlag) {
407 return 0.0; // RETURN
408 }
409
410 if (d_isRunning) {
411 return (double)(d_accumulatedUserTime
412 + TimeUtil::getProcessUserTimer() - d_startUserTime)
413 / s_nanosecondsPerSecond;
414 // RETURN
415 }
416 return (double)d_accumulatedUserTime / s_nanosecondsPerSecond;
417}
418
419inline
421{
422 if (d_isRunning) {
423 TimeUtil::OpaqueNativeTime now;
425 return (double)(d_accumulatedWallTime + elapsedWallTime(now))
426 / s_nanosecondsPerSecond;
427 // RETURN
428 }
429 return (double)d_accumulatedWallTime / s_nanosecondsPerSecond;
430}
431
432inline
434{
435 return accumulatedWallTime();
436}
437
438inline
440{
441 return d_isRunning;
442}
443
444} // close package namespace
445
446#ifndef BDE_OPENSOURCE_PUBLICATION // BACKWARD_COMPATIBILITY
447// ============================================================================
448// BACKWARD COMPATIBILITY
449// ============================================================================
450
451/// This alias is defined for backward compatibility.
453#endif // BDE_OPENSOURCE_PUBLICATION -- BACKWARD_COMPATIBILITY
454
455
456
457#endif
458
459// ----------------------------------------------------------------------------
460// Copyright 2016 Bloomberg Finance L.P.
461//
462// Licensed under the Apache License, Version 2.0 (the "License");
463// you may not use this file except in compliance with the License.
464// You may obtain a copy of the License at
465//
466// http://www.apache.org/licenses/LICENSE-2.0
467//
468// Unless required by applicable law or agreed to in writing, software
469// distributed under the License is distributed on an "AS IS" BASIS,
470// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
471// See the License for the specific language governing permissions and
472// limitations under the License.
473// ----------------------------- END-OF-FILE ----------------------------------
474
475/** @} */
476/** @} */
477/** @} */
Definition bsls_stopwatch.h:149
double accumulatedWallTime() const
Definition bsls_stopwatch.h:420
static const bool k_COLLECT_WALL_TIME_ONLY
Definition bsls_stopwatch.h:207
void stop()
Definition bsls_stopwatch.h:371
void start(bool collectCpuTimes=false)
Definition bsls_stopwatch.h:354
double accumulatedUserTime() const
Definition bsls_stopwatch.h:404
double accumulatedSystemTime() const
Definition bsls_stopwatch.h:388
void accumulatedTimes(double *systemTime, double *userTime, double *wallTime) const
Stopwatch()
Definition bsls_stopwatch.h:329
void reset()
Definition bsls_stopwatch.h:345
double elapsedTime() const
Definition bsls_stopwatch.h:433
static const bool k_COLLECT_WALL_AND_CPU_TIMES
Definition bsls_stopwatch.h:211
bool isRunning() const
Definition bsls_stopwatch.h:439
#define BSLS_IDENT(str)
BSLS_IDENT() - insert string into .comment binary segment (if supported)
Definition bsls_ident.h:238
#define BSLS_KEYWORD_DELETED
Definition bsls_keyword.h:651
bsls::Stopwatch bsls_Stopwatch
This alias is defined for backward compatibility.
Definition bsls_stopwatch.h:452
Definition bdlt_iso8601util.h:707
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:134