BDE 4.14.0 Production release
Loading...
Searching...
No Matches
bsls_timeutil.h
Go to the documentation of this file.
1/// @file bsls_timeutil.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bsls_timeutil.h -*-C++-*-
8#ifndef INCLUDED_BSLS_TIMEUTIL
9#define INCLUDED_BSLS_TIMEUTIL
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup bsls_timeutil bsls_timeutil
15/// @brief Provide a platform-neutral functional interface to system clocks.
16/// @addtogroup bsl
17/// @{
18/// @addtogroup bsls
19/// @{
20/// @addtogroup bsls_timeutil
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#bsls_timeutil-purpose"> Purpose</a>
25/// * <a href="#bsls_timeutil-classes"> Classes </a>
26/// * <a href="#bsls_timeutil-description"> Description </a>
27/// * <a href="#bsls_timeutil-accuracy-and-precision"> Accuracy and Precision </a>
28/// * <a href="#bsls_timeutil-accuracy-on-windows"> Accuracy on Windows </a>
29/// * <a href="#bsls_timeutil-cpu-scaling"> CPU Scaling </a>
30/// * <a href="#bsls_timeutil-multi-core-issues"> Multi-Core Issues </a>
31/// * <a href="#bsls_timeutil-ensuring-accurate-timers-on-windows"> Ensuring Accurate Timers on Windows </a>
32/// * <a href="#bsls_timeutil-precision-on-windows"> Precision on Windows </a>
33/// * <a href="#bsls_timeutil-usage"> Usage </a>
34///
35/// # Purpose {#bsls_timeutil-purpose}
36/// Provide a platform-neutral functional interface to system clocks.
37///
38/// # Classes {#bsls_timeutil-classes}
39///
40/// - bsls::TimeUtil: namespace for platform-neutral system-time pure procedures
41///
42/// @see bsls_stopwatch
43///
44/// # Description {#bsls_timeutil-description}
45/// This component provides a set of platform-neutral pure
46/// procedures to access real-time system clock functionality. High-resolution
47/// time functions intended for interval-timing return a time interval in
48/// nanoseconds (1 nsec = 1E-9 sec) as a 64-bit integer.
49///
50/// ## Accuracy and Precision {#bsls_timeutil-accuracy-and-precision}
51///
52///
53/// `bsls::TimeUtil` high-resolution functions return time values as absolute
54/// nanoseconds from an arbitrary reference that will *in many cases* remain
55/// fixed within a single process (and among running processes on a single
56/// machine). Absolute monotonic behavior is platform-dependent, however, as
57/// are accuracy and useful precision, despite the nominal nanosecond precision
58/// implied by the return value. The user is advised to determine the actual
59/// performance on each platform of interest.
60///
61/// ### Accuracy on Windows {#bsls_timeutil-accuracy-on-windows}
62///
63///
64/// On certain windows platform configurations, `bsls::TimeUtil::getTimer` and
65/// `bsls::TimeUtil::getRawTimer` can produce unreliable results. On some
66/// machines, these high-resolution functions have been observed to run at
67/// inconsistent speeds, with worst cases as slow as half the speed of actual
68/// wall time. This is known behavior of the underlying high-performance timer
69/// function `QueryPerformanceCounter`, upon which the Windows implementation of
70/// `bsls::TimeUtil` relies.
71///
72/// Reference: https://msdn.microsoft.com/library/windows/desktop/dn553408
73///
74/// #### CPU Scaling {#bsls_timeutil-cpu-scaling}
75///
76///
77/// The behavior of the timer on windows platforms depends on the interaction of
78/// operating system, BIOS, and processor, and certain combinations of the three
79/// (particularly older ones) are vulnerable to timer inaccuracy. For example,
80/// frequently the `QueryPerformanceCounter` function that `TimeUtil` uses on
81/// Windows will utilize the CPU's timestamp counter (TSC), and CPUs with speed
82/// scaling mechanisms such as SpeedStep (frequently used for power management)
83/// will generally see the clock speed vary with the CPU frequency. However,
84/// newer processors often provide an `Invariant TSC` that solves this
85/// problem. Also versions of Windows starting with Vista may internally handle
86/// the inconsistency by automatically using a lower resolution, but accurate,
87/// counter on processors that do not provide an `Invariant TSC`.
88///
89/// #### Multi-Core Issues {#bsls_timeutil-multi-core-issues}
90///
91///
92/// In addition, on multi-core machines, each call to `QueryPerformanceCounter`
93/// may read the TSC from a different CPU. The TSCs of the CPUs may be out of
94/// sync, resulting in slightly inconsistent or even non-monotonic behavior.
95///
96/// Reference: http://support.microsoft.com/kb/895980
97///
98/// ### Ensuring Accurate Timers on Windows {#bsls_timeutil-ensuring-accurate-timers-on-windows}
99///
100///
101/// If a Windows machine appears to have a slow and/or inconsistent
102/// high-resolution timer, it can be reconfigured to avoid using the TSC. On
103/// Windows XP and earlier versions, add the parameter `/usepmtimer` to the
104/// operating system's boot configuration in `boot.ini`. On Windows Vista and
105/// later, run the following command as an administrator:
106/// @code
107/// bcdedit /set useplatformclock true
108/// @endcode
109/// Note that unless the machine has a High Performance Event Timer (HPET) and
110/// it has been enabled in the BIOS, these steps might reduce the resolution of
111/// the `bsls::TimeUtil` high-resolution functions from the nanosecond range to
112/// the microsecond range (or worse).
113///
114/// ### Precision on Windows {#bsls_timeutil-precision-on-windows}
115///
116///
117/// Providing that the underlying timer is capable of supporting the
118/// `QueryPerformanceCounter` interface, `getTimer` and `convertRawTime` will
119/// perform their calculations to nanosecond precision based on the values
120/// reported by `QueryPerformanceCounter`. Because of overflow concerns, these
121/// routines do not simply divide the result of `QueryPerformanceCounter` by the
122/// result of `QueryPerformanceFrequency`. In the course of calculating the
123/// final nanosecond-precision time, there are two places where some precision
124/// might be lost. Therefore, the times reported by `getTimer` and
125/// `convertRawTime` may be as much as two nanoseconds less than the actual time
126/// expressed by the `QueryPerformanceCounter` interface. Note that the times
127/// will still be monotonically non-decreasing.
128///
129/// ## Usage {#bsls_timeutil-usage}
130///
131///
132/// The following snippets of code illustrate how to use `bsls::TimeUtil`
133/// functions to implement a very simple timer. Only the most primitive
134/// functionality is illustrated. See the `bsls::Stopwatch` component for a
135/// better example of a timer interface.
136/// @code
137/// // my_timer.h
138///
139/// #ifndef INCLUDED_BSLS_TYPES
140/// #include <bsls_types.h> // bsls::Types::Int64
141/// #endif
142///
143/// #ifndef INCLUDED_BSLS_TIMEUTIL
144/// #include <bsls_timeutil.h>
145/// #endif
146///
147/// class my_Timer {
148/// // This class implements a simple interval timer that is created in
149/// // the "running" state, and may be queried for its cumulative
150/// // interval (as a 'double', in seconds) but never stopped or reset.
151///
152/// bsls::Types::Int64 d_startWallTime; // time at creation (nsec)
153/// bsls::Types::Int64 d_startUserTime; // time at creation (nsec)
154/// bsls::Types::Int64 d_startSystemTime; // time at creation (nsec)
155///
156/// public:
157/// // CREATORS
158/// my_Timer() {
159/// d_startWallTime = bsls::TimeUtil::getTimer();
160/// d_startUserTime = bsls::TimeUtil::getProcessUserTimer();
161/// d_startSystemTime = bsls::TimeUtil::getProcessSystemTimer();
162/// }
163/// // Create a timer object initialized with the times at creation.
164/// // All values returned by subsequent calls to 'elapsed<...>Time()'
165/// // are with respect to this creation time.
166///
167/// ~my_Timer() {}
168///
169/// // ACCESSORS
170/// double elapsedWallTime();
171/// // Return the total elapsed time in seconds since the creation of
172/// // this timer object.
173/// double elapsedUserTime();
174/// // Return the elapsed user time in seconds since the creation of
175/// // this timer object.
176/// double elapsedSystemTime();
177/// // Return the elapsed system time in seconds since the creation of
178/// // this timer object.
179/// };
180///
181/// inline
182/// double my_Timer::elapsedWallTime()
183/// {
184/// return (double) (bsls::TimeUtil::getTimer() - d_startWallTime) * 1.0E-9;
185/// }
186///
187/// inline
188/// double my_Timer::elapsedUserTime()
189/// {
190/// return (double) (bsls::TimeUtil::getProcessUserTimer()
191/// - d_startUserTime) * 1.0E-9;
192/// }
193///
194/// inline
195/// double my_Timer::elapsedSystemTime()
196/// {
197/// return (double) (bsls::TimeUtil::getProcessSystemTimer()
198/// - d_startSystemTime) * 1.0E-9;
199/// }
200/// // ...
201/// @endcode
202/// The `my_Timer` object may be used to time some section of code at runtime as
203/// follows:
204/// @code
205/// // ...
206/// {
207/// my_Timer tw;
208/// for (int i = 0; i < 1000000; ++i) {
209/// // ...
210/// }
211/// double dTw = tw.elapsedWallTime();
212/// my_Timer tu;
213/// for (int i = 0; i < 1000000; ++i) {
214/// // ...
215/// }
216/// double dTu = tu.elapsedUserTime();
217/// my_Timer ts;
218/// for (int i = 0; i < 1000000; ++i) {
219/// // ...
220/// }
221/// double dTs = ts.elapsedSystemTime();
222/// std::cout << "elapsed wall time: " << dTw << std::endl
223/// << "elapsed user time: " << dTu << std::endl
224/// << "elapsed system time: " << dTs << std::endl;
225/// }
226/// @endcode
227/// @}
228/** @} */
229/** @} */
230
231/** @addtogroup bsl
232 * @{
233 */
234/** @addtogroup bsls
235 * @{
236 */
237/** @addtogroup bsls_timeutil
238 * @{
239 */
240
241#include <bsls_platform.h>
242#include <bsls_types.h>
243
244#ifdef BSLS_PLATFORM_OS_UNIX
245 #include <time.h>
246#endif
247
248#if defined(BSLS_PLATFORM_OS_AIX) || defined(BSLS_PLATFORM_OS_FREEBSD) || defined(BSLS_PLATFORM_OS_DARWIN)
249 #include <sys/time.h>
250#endif
251
252
253
254namespace bsls {
255
256 // ===============
257 // struct TimeUtil
258 // ===============
259
260/// This `struct` provides a namespace for a set of platform-neutral pure
261/// procedures to access real-time system clock functionality.
262/// High-resolution time functions intended for interval-timing return an
263/// interval in nanoseconds (1 nsec = 1E-9 sec) as a platform-independent
264/// 64-bit integer.
265///
266/// For maximum performance on some platforms where fetching the native
267/// clock is significantly faster than converting the fetched value to
268/// nanoseconds, this class also provides a "raw" method returning an opaque
269/// native time value and a conversion method returning a value in
270/// nanoseconds.
271struct TimeUtil {
272
273 // TYPES
274#if defined BSLS_PLATFORM_OS_SOLARIS
275 typedef struct { Types::Int64 d_opaque; } OpaqueNativeTime;
276#elif defined BSLS_PLATFORM_OS_AIX
277 typedef timebasestruct_t OpaqueNativeTime;
278#elif defined(BSLS_PLATFORM_OS_LINUX) || defined(BSLS_PLATFORM_OS_CYGWIN)
279 typedef timespec OpaqueNativeTime;
280#elif defined BSLS_PLATFORM_OS_DARWIN
281 typedef struct { Types::Uint64 d_opaque; } OpaqueNativeTime;
282#elif defined BSLS_PLATFORM_OS_UNIX
283 typedef timeval OpaqueNativeTime;
284#elif defined BSLS_PLATFORM_OS_WINDOWS
285 typedef struct { Types::Int64 d_opaque; } OpaqueNativeTime;
286#endif
287
288 // CLASS METHODS
289
290 // Initializers
291
292 /// Do a platform-dependent initialization for the utilities. Note that
293 /// the other methods in this component are guaranteed to be thread-safe
294 /// only after calling this method.
295 static void initialize();
296
297 // Operations
298
299 /// Convert the specified `rawTime` to a value in nanoseconds,
300 /// referenced to an arbitrary but fixed origin, and return the result
301 /// of the conversion. Note that this method is thread-safe only if
302 /// `initialize` has been called before.
303 static Types::Int64 convertRawTime(OpaqueNativeTime rawTime);
304
305 /// Return the instantaneous values of a platform-dependent timer for
306 /// the current process system time in absolute nanoseconds referenced
307 /// to an arbitrary but fixed origin. Note that this method is thread-
308 /// safe only if `initialize` has been called before.
310
311 /// Load into the specified `systemTimer` and `userTimer` the
312 /// instantaneous values of platform-dependent system timer and user
313 /// timer in absolute nanoseconds referenced to an arbitrary but fixed
314 /// origin. Note that this method is thread-safe only if `initialize`
315 /// has been called before.
316 static void getProcessTimers(Types::Int64 *systemTimer,
317 Types::Int64 *userTimer);
318
319 /// Return the instantaneous values of a platform-dependent timer for
320 /// the current process user time in absolute nanoseconds referenced to
321 /// an arbitrary but fixed origin. Note that this method is thread-safe
322 /// only if `initialize` has been called before.
324
325 /// Return the instantaneous value of a platform-dependent system timer
326 /// in absolute nanoseconds referenced to an arbitrary but fixed origin.
327 /// Note that this method is thread-safe only if `initialize` has been
328 /// called before.
330
331 /// Load into the specified `timeValue` the value of an opaque,
332 /// platform-dependent type representing the current time. `timeValue`
333 /// must be converted by the `convertRawTime` method to conventional
334 /// units (nanoseconds). This method is intended to facilitate accurate
335 /// timing of small segments of code, and care must be used in
336 /// interpreting the results. Note that this method is thread-safe only
337 /// if `initialize` has been called before.
338 static void getTimerRaw(OpaqueNativeTime *timeValue);
339
340};
341
342} // close package namespace
343
344#ifndef BDE_OPENSOURCE_PUBLICATION // BACKWARD_COMPATIBILITY
345// ============================================================================
346// BACKWARD COMPATIBILITY
347// ============================================================================
348
349/// This alias is defined for backward compatibility.
351#endif // BDE_OPENSOURCE_PUBLICATION -- BACKWARD_COMPATIBILITY
352
353
354
355#endif
356
357// ----------------------------------------------------------------------------
358// Copyright 2013 Bloomberg Finance L.P.
359//
360// Licensed under the Apache License, Version 2.0 (the "License");
361// you may not use this file except in compliance with the License.
362// You may obtain a copy of the License at
363//
364// http://www.apache.org/licenses/LICENSE-2.0
365//
366// Unless required by applicable law or agreed to in writing, software
367// distributed under the License is distributed on an "AS IS" BASIS,
368// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
369// See the License for the specific language governing permissions and
370// limitations under the License.
371// ----------------------------- END-OF-FILE ----------------------------------
372
373/** @} */
374/** @} */
375/** @} */
#define BSLS_IDENT(str)
Definition bsls_ident.h:195
bsls::TimeUtil bsls_TimeUtil
This alias is defined for backward compatibility.
Definition bsls_timeutil.h:350
Definition bdlt_iso8601util.h:691
Definition bsls_timeutil.h:271
static Types::Int64 convertRawTime(OpaqueNativeTime rawTime)
static void initialize()
static Types::Int64 getTimer()
static Types::Int64 getProcessUserTimer()
static void getTimerRaw(OpaqueNativeTime *timeValue)
static void getProcessTimers(Types::Int64 *systemTimer, Types::Int64 *userTimer)
static Types::Int64 getProcessSystemTimer()
unsigned long long Uint64
Definition bsls_types.h:137
long long Int64
Definition bsls_types.h:132