Welcome to CCPUTicker, An ultra high precision MFC timing class for Pentium or greater CPU's. resolution timing.
Features |
Copyright |
History |
API Reference |
Usage |
Contacting the Author |
This class implements an MFC wrapper class for the Pentium-specific (or better) time stamp counter which can be accessed using the "RDTSC" assembly language instruction. This counter has a resolution in terms of PCLKS (processor clocks) so if you have a 2000 MHz CPU then this class will give a frequency of 2000 MHz. The value returned is an 64 bit integer so assuming your CPU runs at 2000 MHz, the value will take roughly 300 years to roll over. As the value also starts counting from 0, the value returned is the number of CPU ticks since the computer was turned on.
Because the timer is part of the CPU hardware, it is unaffected by processor activity and workload.
The class itself was developed originally by J.M.McGuiness and continues to be co-developed by both authors.
V1.0 (26 March 1996)
V1.1 (16 July 1997)
V1.2 (14 January 1999)
V1.21 (18 January 1999)
21 January 1999
27 January 1999
v1.22 (3 December 1999)
v1.23 (17 May 2000)
30 July 2000
v1.24 (30 January 2001)
v1.25 (23 February 2004)
v1.26 (24 December 2006)
The API is made of the following public methods of the CCPUTicker class
Measure()
GetTickCountAsSeconds()
GetCPUFrequency()
unsigned __int64 Measure();
Return value
The current RDTSC counter value in seconds.
Remarks
Calling this function retrieves the current value of the RDTSC counter into this CCPUTicker instance.
CCPUTicker::GetTickCountAsSeconds
double GetTickCountAsSeconds(unsigned __int64 nValue) const;
Parameters
nValue The counter value to convert to seconds.
Return value
The current RDTSC counter value expressed in seconds.
Remarks
Calling this function retrieves the stored value of the RDTSC counter from this instance as seconds. The number of seconds is the "Up" time of the computer. Because the counter is stored in clock ticks, the first time this function is called by any of your code, the processor clock frequency will be estimated using an internal timing routine. Please note that this can appear to hang the current process for up to 20 seconds when this is being performed. Please see the Usage section below for important development notes regarding this function.
static BOOL GetCPUFrequency(double& CPUFrequency, double& TargetAverageDeviation, DWORD dwInterval = 100, DWORD dwMaxLoops = 20) const;
Parameters
CPUFequency Upon successful return, this will contain the processor clock frequency in Hertz.
TargetAverageDeviation Upon successful return, this will contain the estimated average deviation of the processor clock frequency in Hertz.
dwInterval Interval in milliseconds for each timing loop.
dwMaxLoops The maximum number of timing loops to use to estimate the processor clock frequency with.
Return value
TRUE if the CPU frequency was returned successfully, otherwise FALSE. Use GetLastError to determine the cause if this happens.
Remarks
This function will work out the processor clock frequency to a specified accuracy determined by the target average deviation required. The average deviation is a better and more robust measure than it's cousin the standard deviation of a quantity. The item determined by each is essentially similar. See "Numerical Recipies", W.Press et al for more details. This function will run for a maximum of 2 seconds by default before giving up on trying to improve the average deviation, with the average deviation actually achieved replacing the supplied target value. Use "dwMaxLoops" to change this. To improve the value the function converges to increase "dwInterval" (which is in units of ms, default value=100ms). Please see the Usage section below for important development notes regarding this function.
The sample app is a simple MFC message box based demonstration which will time the accuracy of a call to the SDK call "Sleep(1000)", also reports how long your machine has been "Up" in addition to the processor speed of your machine.
To use CCPUTicker in your project simply include CCPUTicker.cpp from the test application in your application and #include "CCPUTicker.h" in whichever files you want to use the class in.
The following points should be born in mind when developing code with CCPUTicker
Usage on SMP(Symmetric Multiprocessing Machines)/Multi-Core Machines
Consider the following scenario: we intend to get an idea of how long (real time) something takes by taking two readings of RDTSC, and using the difference/frequency to give us a time reading. Suppose the first reading is taken from CPU0, and the second reading is taken from CPU1 (the process is not necessarily always run on the same CPU). Since the CPU's RDTSC instructions are separate, the RDTSC on one CPU is not related at all to the RDTSC on the other CPU - so the readings would have no relation at all!. You should work around this problem at your application level. Detecting a SMP machine can be done by calling the GetSystemInfo SDK function and examining the dwNumberOfProcessors in the structure returned. You should also have a look at the SetProcessAffinityMask function to ensure that your code will always run on only a single CPU. AMD has a download to specifically address this problem at http://www.amd.com/us-en/Processors/TechnicalResources/0,,30_182_871_9706,00.html for their multi-core CPU's.
Re: APM, ACPI, CPU overheating
On many machines, the clock speed of the CPU can be slowed (and later increased) by these. Thus calculating real time from clock cycles may not be valid. (Suppose the clock was changed between the first and second reading, or suppose that the clock frequency was calculated at one speed, and later it was changed....). Please bear in mind that calls to GetCPUFrequency and GetTickCountAsSeconds are dependent on the CPU frequency being invariant over time. If the CPU frequency does change over time then anything reported as seconds may not be accurate. If you just want to retrieve the up time of the computer, you should use the GetTickCount(64) SDK functions.
For further information about the issues surrounding using RDTSC, please see the MSDN article http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/Game_Timing_and_Multicore_Processors.asp
PJ Naughter
Email: pjna@naughter.com
Web: http://www.naughter.com
4 September 2007