ACE
6.3.1
|
A high resolution timer class wrapper that encapsulates OS-specific high-resolution timers, such as those found on Solaris, AIX, Win32/Pentium, and VxWorks. More...
#include <High_Res_Timer.h>
Public Types | |
typedef ACE_UINT64 | global_scale_factor_type |
Public Member Functions | |
ACE_High_Res_Timer (void) | |
Initialize the timer. More... | |
~ACE_High_Res_Timer (void) | |
Destructor. More... | |
void | reset (void) |
Reinitialize the timer. More... | |
void | start (const ACE_OS::ACE_HRTimer_Op=ACE_OS::ACE_HRTIMER_GETTIME) |
Start timing. More... | |
void | stop (const ACE_OS::ACE_HRTimer_Op=ACE_OS::ACE_HRTIMER_GETTIME) |
Stop timing. More... | |
void | elapsed_time (ACE_Time_Value &tv) const |
Set tv to the number of microseconds elapsed. More... | |
void | elapsed_time (ACE_hrtime_t &nanoseconds) const |
Set nanoseconds to the number of nanoseconds elapsed. More... | |
void | elapsed_microseconds (ACE_hrtime_t &usecs) const |
Sets usecs to the elapsed (stop - start) time in microseconds. More... | |
void | start_incr (const ACE_OS::ACE_HRTimer_Op=ACE_OS::ACE_HRTIMER_GETTIME) |
Start incremental timing. More... | |
void | stop_incr (const ACE_OS::ACE_HRTimer_Op=ACE_OS::ACE_HRTIMER_GETTIME) |
Stop incremental timing. More... | |
void | elapsed_time_incr (ACE_Time_Value &tv) const |
void | elapsed_time_incr (ACE_hrtime_t &nanoseconds) const |
void | print_total (const ACE_TCHAR *message, const int iterations=1, ACE_HANDLE handle=ACE_STDOUT) const |
void | print_ave (const ACE_TCHAR *message, const int iterations=1, ACE_HANDLE handle=ACE_STDOUT) const |
Print average time. More... | |
void | dump (void) const |
Dump the state of an object. More... | |
Static Public Member Functions | |
static void | global_scale_factor (global_scale_factor_type gsf) |
static global_scale_factor_type | global_scale_factor (void) |
Returns the global_scale_factor. More... | |
static int | get_env_global_scale_factor (const ACE_TCHAR *env=ACE_TEXT("ACE_SCALE_FACTOR")) |
static ACE_UINT32 | calibrate (const ACE_UINT32 usec=500000, const u_int iterations=10) |
static ACE_Time_Value | gettimeofday_hr (void) |
static ACE_Time_Value | gettimeofday (const ACE_OS::ACE_HRTimer_Op=ACE_OS::ACE_HRTIMER_GETTIME) |
static void | hrtime_to_tv (ACE_Time_Value &tv, const ACE_hrtime_t hrt) |
Converts an hrt to tv using global_scale_factor_. More... | |
Public Attributes | |
ACE_ALLOC_HOOK_DECLARE | |
Declare the dynamic allocation hooks. More... | |
Static Private Member Functions | |
static ACE_hrtime_t | gettime (const ACE_OS::ACE_HRTimer_Op=ACE_OS::ACE_HRTIMER_GETTIME) |
static ACE_hrtime_t | elapsed_hrtime (const ACE_hrtime_t end, const ACE_hrtime_t start) |
Private Attributes | |
ACE_hrtime_t | start_ |
Starting time. More... | |
ACE_hrtime_t | end_ |
Ending time. More... | |
ACE_hrtime_t | total_ |
Total elapsed time. More... | |
ACE_hrtime_t | start_incr_ |
Start time of incremental timing. More... | |
Static Private Attributes | |
static global_scale_factor_type | global_scale_factor_ = 1u |
static int | global_scale_factor_status_ = 0 |
A high resolution timer class wrapper that encapsulates OS-specific high-resolution timers, such as those found on Solaris, AIX, Win32/Pentium, and VxWorks.
Most of the member functions don't return values. The only reason that one would fail is if high-resolution time isn't supported on the platform. To avoid impacting performance and complicating the interface, in that case, <ACE_OS::gettimeofday> is used instead. The global scale factor is required for platforms that have high-resolution timers that return units other than microseconds, such as clock ticks. It is represented as a static u_long, can only be accessed through static methods, and is used by all instances of High Res Timer. The member functions that return or print times use the global scale factor. They divide the "time" that they get from <ACE_OS::gethrtime> by global_scale_factor_ to obtain the time in microseconds. Its units are therefore 1/microsecond. On Windows the global_scale_factor_ units are 1/millisecond. There's a macro <ACE_HR_SCALE_CONVERSION> which gives the units/second. Because it's possible that the units/second changes in the future, it's recommended to use it instead of a "hard coded" solution. Dependent on the platform and used class members, there's a maximum elapsed period before overflow (which is not checked). Look at the documentation with some members functions. On some (most?) implementations it's not recommended to measure "long" timeperiods, because the error's can accumulate fast. This is probably not a problem profiling code, but could be on if the high resolution timer class is used to initiate actions after a "long" timeout. On Solaris, a scale factor of 1000 should be used because its high-resolution timer returns nanoseconds. However, on Intel platforms, we use RDTSC which returns the number of clock ticks since system boot. For a 200MHz cpu, each clock tick is 1/200 of a microsecond; the global_scale_factor_ should therefore be 200 or 200000 if it's in unit/millisecond. On Windows ::QueryPerformanceCounter() is used, which can be a different implementation depending on the used windows HAL (Hardware Abstraction Layer). On some it uses the PC "timer chip" while it uses RDTSC on others.
timer.stop()
value might not be the one you queried for timer.start()
. Its not clear how much divergence there would be, if any. This issue is not mentioned in the Solaris 2.5.1 gethrtime man page. A RDTSC NOTE: RDTSC is the Intel Pentium read-time stamp counter and is actualy a 64 bit clock cycle counter, which is increased with every cycle. It has a low overhead and can be read within 16 (pentium) or 32 (pentium II,III,...) cycles, but it doesn't serialize the processor, which could give wrong timings when profiling very short code fragments. Problematic is that some power sensitive devices (laptops for example, but probably also embedded devices), do change the cycle rate while running. Some pentiums can run on (at least) two clock frequency's. Another problem arises with multiprocessor computers, there are reports that the different RDTSC's are not always kept in sync. A windows "timer chip" NOTE: (8254-compatible real-time clock) When ::QueryPerformanceCounter() uses the 8254 it has a frequency off about 1.193 Mhz (or sometimes 3.579 Mhz?) and reading it requires some time (several thousand cycles). ACE_High_Res_Timer::ACE_High_Res_Timer | ( | void | ) |
Initialize the timer.
|
inline |
Destructor.
|
static |
Set (and return, for info) the global scale factor by sleeping for usec and counting the number of intervening clock cycles. Average over iterations of usec each. On some platforms, such as Pentiums, this is called automatically during the first ACE_High_Res_Timer construction with the default parameter values. An application can override that by calling calibrate with any desired parameter values prior to constructing the first ACE_High_Res_Timer instance. Beware for platforms that can change the cycle rate on the fly.
void ACE_High_Res_Timer::dump | ( | void | ) | const |
Dump the state of an object.
|
inlinestaticprivate |
Calculate the difference between two ACE_hrtime_t values. It is assumed that the end time is later than start time, so if end is a smaller value, the time counter has wrapped around.
|
inline |
Sets usecs to the elapsed (stop - start) time in microseconds.
Will overflow on windows when measuring more than appox. 2^^54 ticks. Is still more than 48 days with a 4 Ghz counter.
void ACE_High_Res_Timer::elapsed_time | ( | ACE_Time_Value & | tv | ) | const |
Set tv to the number of microseconds elapsed.
void ACE_High_Res_Timer::elapsed_time | ( | ACE_hrtime_t & | nanoseconds | ) | const |
Set nanoseconds to the number of nanoseconds elapsed.
Will overflow when measuring more than 194 day's.
void ACE_High_Res_Timer::elapsed_time_incr | ( | ACE_Time_Value & | tv | ) | const |
Set tv to the number of microseconds elapsed between all calls to start_incr and stop_incr.
void ACE_High_Res_Timer::elapsed_time_incr | ( | ACE_hrtime_t & | nanoseconds | ) | const |
Set nanoseconds to the number of nanoseconds elapsed between all calls to start_incr and stop_incr.
|
static |
Sets the global_scale_factor to the value in the env environment variable. Returns 0 on success, -1 on failure.
|
inlinestaticprivate |
For internal use: gets the high-resolution time using <ACE_OS::gethrtime>. Except on platforms that require that the <global_scale_factor_> be set, such as ACE_WIN32, uses the low-resolution clock if the <global_scale_factor_> has not been set.
|
inlinestatic |
|
inlinestatic |
Get the current "time" as the high resolution counter at this time. This is intended to be useful for supplying to a ACE_Timer_Queue as the gettimeofday function, thereby basing the timer calculations on the high res timer rather than wall clock time.
Get the current high res timer as the time of day. This is intended to be used for a gettimeofday replacement in ACE_Timer_Queue and derived classes so the timers will be based on high res timers rather than wall clock time. It uses the ACE_High_Res_Timer::gettimeofday function, which is deprecated. If it gets removed, please move the code down here, intact.
|
inlinestatic |
global_scale_factor_ is set to gsf. All High_Res_Timers use global_scale_factor_. This allows applications to set the scale factor just once for all High_Res_Timers. Check High_Res_Timer.cpp for the default global_scale_factors for several platforms. For many platforms (e.g., Solaris), the global_scale_factor_ is set to 1000 so that <scale_factor> need not be set. Careful, a <scale_factor> of 0 will cause division by zero exceptions. Depending on the platform its units are 1/microsecond or 1/millisecond. Use ACE_HR_SCALE_CONVERSION
inside calculations instead a hardcoded value.
|
static |
Returns the global_scale_factor.
|
inlinestatic |
Converts an hrt to tv using global_scale_factor_.
Be very careful before changing the calculations inside ACE_High_Res_Timer. The precision matters and we are using integer calculations not floating point.
void ACE_High_Res_Timer::print_ave | ( | const ACE_TCHAR * | message, |
const int | iterations = 1 , |
||
ACE_HANDLE | handle = ACE_STDOUT |
||
) | const |
Print average time.
void ACE_High_Res_Timer::print_total | ( | const ACE_TCHAR * | message, |
const int | iterations = 1 , |
||
ACE_HANDLE | handle = ACE_STDOUT |
||
) | const |
Print total time.
print_total
if incremental timings had been used! void ACE_High_Res_Timer::reset | ( | void | ) |
Reinitialize the timer.
|
inline |
Start timing.
|
inline |
Start incremental timing.
|
inline |
Stop timing.
|
inline |
Stop incremental timing.
ACE_High_Res_Timer::ACE_ALLOC_HOOK_DECLARE |
Declare the dynamic allocation hooks.
|
private |
Ending time.
|
staticprivate |
Converts ticks to microseconds. That is, ticks / global_scale_factor_ == microseconds.
Initialize the global_scale_factor_ to 1. The first ACE_High_Res_Timer instance construction will override this value.
|
staticprivate |
Indicates the status of the global scale factor, 0 = hasn't been set 1 = been set -1 = HR timer not supported
This is used to tell if the global_scale_factor_ has been set, and if high resolution timers are supported.
|
private |
Starting time.
|
private |
Start time of incremental timing.
|
private |
Total elapsed time.