BDE 4.14.0 Production release
Loading...
Searching...
No Matches
bsls_timeutil

Typedefs

typedef bsls::TimeUtil bsls_TimeUtil
 This alias is defined for backward compatibility.
 

Detailed Description

Outline

Purpose

Provide a platform-neutral functional interface to system clocks.

Classes

See also
bsls_stopwatch

Description

This component provides a set of platform-neutral pure procedures to access real-time system clock functionality. High-resolution time functions intended for interval-timing return a time interval in nanoseconds (1 nsec = 1E-9 sec) as a 64-bit integer.

Accuracy and Precision

bsls::TimeUtil high-resolution functions return time values as absolute nanoseconds from an arbitrary reference that will in many cases remain fixed within a single process (and among running processes on a single machine). Absolute monotonic behavior is platform-dependent, however, as are accuracy and useful precision, despite the nominal nanosecond precision implied by the return value. The user is advised to determine the actual performance on each platform of interest.

Accuracy on Windows

On certain windows platform configurations, bsls::TimeUtil::getTimer and bsls::TimeUtil::getRawTimer can produce unreliable results. On some machines, these high-resolution functions have been observed to run at inconsistent speeds, with worst cases as slow as half the speed of actual wall time. This is known behavior of the underlying high-performance timer function QueryPerformanceCounter, upon which the Windows implementation of bsls::TimeUtil relies.

Reference: https://msdn.microsoft.com/library/windows/desktop/dn553408

CPU Scaling

The behavior of the timer on windows platforms depends on the interaction of operating system, BIOS, and processor, and certain combinations of the three (particularly older ones) are vulnerable to timer inaccuracy. For example, frequently the QueryPerformanceCounter function that TimeUtil uses on Windows will utilize the CPU's timestamp counter (TSC), and CPUs with speed scaling mechanisms such as SpeedStep (frequently used for power management) will generally see the clock speed vary with the CPU frequency. However, newer processors often provide an Invariant TSC that solves this problem. Also versions of Windows starting with Vista may internally handle the inconsistency by automatically using a lower resolution, but accurate, counter on processors that do not provide an Invariant TSC.

Multi-Core Issues

In addition, on multi-core machines, each call to QueryPerformanceCounter may read the TSC from a different CPU. The TSCs of the CPUs may be out of sync, resulting in slightly inconsistent or even non-monotonic behavior.

Reference: http://support.microsoft.com/kb/895980

Ensuring Accurate Timers on Windows

If a Windows machine appears to have a slow and/or inconsistent high-resolution timer, it can be reconfigured to avoid using the TSC. On Windows XP and earlier versions, add the parameter /usepmtimer to the operating system's boot configuration in boot.ini. On Windows Vista and later, run the following command as an administrator:

bcdedit /set useplatformclock true

Note that unless the machine has a High Performance Event Timer (HPET) and it has been enabled in the BIOS, these steps might reduce the resolution of the bsls::TimeUtil high-resolution functions from the nanosecond range to the microsecond range (or worse).

Precision on Windows

Providing that the underlying timer is capable of supporting the QueryPerformanceCounter interface, getTimer and convertRawTime will perform their calculations to nanosecond precision based on the values reported by QueryPerformanceCounter. Because of overflow concerns, these routines do not simply divide the result of QueryPerformanceCounter by the result of QueryPerformanceFrequency. In the course of calculating the final nanosecond-precision time, there are two places where some precision might be lost. Therefore, the times reported by getTimer and convertRawTime may be as much as two nanoseconds less than the actual time expressed by the QueryPerformanceCounter interface. Note that the times will still be monotonically non-decreasing.

Usage

The following snippets of code illustrate how to use bsls::TimeUtil functions to implement a very simple timer. Only the most primitive functionality is illustrated. See the bsls::Stopwatch component for a better example of a timer interface.

// my_timer.h
#ifndef INCLUDED_BSLS_TYPES
#include <bsls_types.h> // bsls::Types::Int64
#endif
#ifndef INCLUDED_BSLS_TIMEUTIL
#include <bsls_timeutil.h>
#endif
class my_Timer {
// This class implements a simple interval timer that is created in
// the "running" state, and may be queried for its cumulative
// interval (as a 'double', in seconds) but never stopped or reset.
bsls::Types::Int64 d_startWallTime; // time at creation (nsec)
bsls::Types::Int64 d_startUserTime; // time at creation (nsec)
bsls::Types::Int64 d_startSystemTime; // time at creation (nsec)
public:
// CREATORS
my_Timer() {
d_startWallTime = bsls::TimeUtil::getTimer();
}
// Create a timer object initialized with the times at creation.
// All values returned by subsequent calls to 'elapsed<...>Time()'
// are with respect to this creation time.
~my_Timer() {}
// ACCESSORS
double elapsedWallTime();
// Return the total elapsed time in seconds since the creation of
// this timer object.
double elapsedUserTime();
// Return the elapsed user time in seconds since the creation of
// this timer object.
double elapsedSystemTime();
// Return the elapsed system time in seconds since the creation of
// this timer object.
};
inline
double my_Timer::elapsedWallTime()
{
return (double) (bsls::TimeUtil::getTimer() - d_startWallTime) * 1.0E-9;
}
inline
double my_Timer::elapsedUserTime()
{
- d_startUserTime) * 1.0E-9;
}
inline
double my_Timer::elapsedSystemTime()
{
- d_startSystemTime) * 1.0E-9;
}
// ...
static Types::Int64 getTimer()
static Types::Int64 getProcessUserTimer()
static Types::Int64 getProcessSystemTimer()
long long Int64
Definition bsls_types.h:132

The my_Timer object may be used to time some section of code at runtime as follows:

// ...
{
my_Timer tw;
for (int i = 0; i < 1000000; ++i) {
// ...
}
double dTw = tw.elapsedWallTime();
my_Timer tu;
for (int i = 0; i < 1000000; ++i) {
// ...
}
double dTu = tu.elapsedUserTime();
my_Timer ts;
for (int i = 0; i < 1000000; ++i) {
// ...
}
double dTs = ts.elapsedSystemTime();
std::cout << "elapsed wall time: " << dTw << std::endl
<< "elapsed user time: " << dTu << std::endl
<< "elapsed system time: " << dTs << std::endl;
}

Typedef Documentation

◆ bsls_TimeUtil