The Code Project View our sponsorsClick here for Dundas Software's TCP/IP Development KitAdvertise on the CodeProject
Home >> Date / Time handling >> General

CCPUTicker v1.22 - Precision Timing
By PJ Naughter

An ultra high precision MFC timing class for Pentium or greater CPUs. 
 VC6, Win9x, NT4, MFC
 Posted 4 Mar 2000
Articles by this author
Send to a friend
Printer friendly version
Lounge New Articles Sign in Forums Contribute
Broken links? Email us!
3 users have rated this article. result:
5 out of 5.

  • Download source files - 16 Kb
  • Introduction

    Welcome to CCPUTicker, An ultra high precision MFC timing class for Pentium or greater CPU's resolution timing.


    Features
    History
    API Reference
    Usage
    Contacting the Author


    Features

    This class implements an MFC wrapper class for the Pentium-specific 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 200 MHz CPU then this class will give a frequency of 200 MHz. The value returned is a 64 bit integer so assuming your CPU runs at 200 MHZ, the value will take roughly 3000 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 i.e. the "UP" time.

    Because the timer is part of the CPU hardware, it is unaffected by processor activity and workload. The class has only been tested on Intel CPU's. Feedback about its behavior on other CPU types would be appreciated. The class can also be used on Windows NT without any problems.

    The class itself was developed originally by J.M.McGuiness and continues to be co-developed by both authors.

    The source zip file contains the CCPUTicker source code and also includes a simple MFC message box based demonstration application which will time the accuracy of a call to the SDK call Sleep(1000) and also report how long your machine has been "Up".


    History

    V1.0 (26 March 1996)

    V1.1 (16 July 1997)

    V1.2 (14 January 1999)

    V1.21 (14 January 1999)

    21 January 1999

    27 January 1999

    v1.22 (3 December 1999)


    API Reference

    The API is made of the following public methods of the CCPUTicker class:

    CCPUTicker()
    operator=()
    Measure()
    GetTickCountAsSeconds()
    GetTickCount()
    GetCPUFrequency()
    IsAvailable()
    AssertValid()
    Dump()


    CCPUTicker::CCPUTicker

    CCPUTicker();
    CCPUTicker(const CCPUTicker &ticker;);

    Parameters:

    Remarks:
    Standard constructor and copy constructor for the class which just initialize some internal variables.


    CCPUTicker::operator=

    CCPUTicker& operator=(const CCPUTicker &ticker;);

    Parameters:

    Return Value:
    Usual reference to this from a C++ operator= function.

    Remarks:
    Standard operator= for the class.


    CCPUTicker::Measure

    void CCPUTicker::Measure();

    Remarks:
    Calling this function retrieves the current value of the RDTSC counter into this CCPUTicker instance.


    CCPUTicker::GetTickCountAsSeconds

    double GetTickCountAsSeconds() const;

    Return Value:
    The current RDTSC counter value 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.


    CCPUTicker::GetTickCount

    __int64 CCPUTicker::GetTickCount() const;

    Return Value:
    The current RDTSC counter value in clock ticks.

    Remarks:
    Calling this function retrieves the stored value of the RDTSC counter from this instance as clock ticks. This function is a simple accessor on the value which the class will have obtained on the last call to its Measure method.


    CCPUTicker::GetCPUFrequency

    static BOOL GetCPUFrequency(double& frequency, double& target_ave_dev, unsigned long interval = 1000, unsigned int max_loops = 20) const;

    Parameters:

    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. Note that the worst average deviation of the result is less than 5MHz for a mean frequency of 90MHz. So basically the target average deviation is supplied only if you want a more accurate result, it won't let you get a worse one. (Units are Hz.). 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 20 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 "max_loops" to change this. To improve the value the function converges to increase "interval" (which is in units of ms, default value=1000ms). Please see the Usage section below for important development notes regarding this function.


    CCPUTicker::IsAvailable

    BOOL IsAvailable() const;

    Return value:
    TRUE if this machine has the "RDTSC" instruction available for timing otherwise FALSE.


    CCPUTicker::AssertValid

    virtual void AssertValid() const;

    Remarks:
    Standard MFC diagnostic function.


    CCPUTicker::Dump

    virtual void Dump(CDumpContext& dc) const;

    Remarks:
    Standard MFC diagnostic function.



    Usage

    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) and also report how long your machine has been "Up".

    To use CCPUTicker in your project simply include cputicker.cpp from the test application in your application and #include "cputicker.h" in which ever files you want to use the class.

    The following points should be born in mind when developing code with CCPUTicker:

    Usage on SMP Machines (Symmetric Multiprocessing Machines) i.e. NT with 2 or more CPU's
    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 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.

    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 timer. 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 SDK function.


    Contacting the Author

    PJ Naughter
    Email: pjn@indigo..ie
    Web:
    [Top] Sign in to vote for this article:     PoorExcellent  
    Hint: For improved responsiveness, use Internet Explorer 4 (or above) with Javascript enabled, choose 'Use DHTML' from the View dropdown and hit 'Set Options'.
     Keyword Filter
     View   Per page   Messages since
    New threadMessages 1 to 10 of 10 (Total: 10)First Prev Next Last
    Subject 
    Author 
    Date 
      how to delay 0.00002 second
    Julia 11:37 26 Apr 01 
      Re: how to delay 0.00002 second
    Anonymous 5:10 8 May 01 
      how to delay 0.00002 second
    Anonymous 11:37 26 Apr 01 
      Hard drive performance monitoring
    Steve Portly 11:40 20 Sep 00 
      Hard drive performance monitoring
    Steve Portly 11:39 20 Sep 00 
      return type of CCPUTicker::Measure()
    Rufus V. Smith 12:23 17 May 00 
      Re: return type of CCPUTicker::Measure()
    PJ Naughter 16:59 17 May 00 
      What about Win32 HighResolutionTimer
    Christian Rodemeyer 6:44 15 Mar 00 
      Re: What about Win32 HighResolutionTimer
    PJ Naughter 19:45 16 May 00 
      Re: What about Win32 HighResolutionTimer
    Rufus V. Smith 12:34 17 May 00 
    Last Visit: 12:00 Friday 1st January, 1999First Prev Next Last

    Home >> Date / Time handling >> General
    last updated 4 Mar 2000
    Article content copyright PJ Naughter, 2000
    everything else © CodeProject, 1999-2001.
    The Code Project View our sponsorsClick here for Whole Tomato Software - Home of Visual AssistAdvertise on the CodeProject