Click here to Skip to main content
Email Password   helpLost your password?
  • 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:
    You must Sign In to use this message board.
     
     
    Per page   
     FirstPrevNext
    GeneralLaptops and Processor load speed adjustment
    ndl
    8:15 9 Jun '09  
    There is a problem in using this class with laptops and some desktops that have their power management scheme configured to adjust processor speed based on load. If the clock speed is reduced or increased by the power management system, the class methods return incorrect time values. I believe disabling processor speed changes before using this class would solve the problem. Anyone know the "correct" way to do this, and how to set it back?

    Neil
    GeneralCWinthread Problems?
    AAntix
    18:38 4 Mar '03  
    I have a pointer to a CPUTicker object in a derived CWinThread class. The object is allocated in InitInstance, and is deallocated in ExitInstance.

    All of my calls work correctly, but when the thread goes to shutdown, I am receiving memory check errors everywhere when I issue a "delete m_pCPUTicker;"

    Should I be able to run this class in a thread, or does it have to be called in the main process? I am using it primarily to get the CPU frequency.

    Jim
    QTExtender - The OFFICIAL addon for QuoteTracker.
    GeneralRe: CWinthread Problems?
    pjnaughter
    8:04 5 Mar '03  
    Ya, I would not expect there to be any problems there. 2 suggestions:

    1. Make sure you have the latest version from my web site www.naughter.com.
    2. Get the debugger out, and take it from there
    GeneralRe: CWinthread Problems?
    AAntix
    23:48 6 Mar '03  
    Smile I did find an apparent workaround for the version found here on CodeProject; I allocated the CCPUTicker object on the heap within the main process, and then passed a pointer of the CCPUTicker object to my CWinThread.

    It appears to be working fine.

    Thanks again for great work.

    Jim
    QTExtender - The OFFICIAL addon for QuoteTracker.
    GeneralSystem time manipulation
    Anonymous
    6:46 13 Feb '02  
    How do I change the system time so that "time" passes on the computer at a different rate than real time.   In other words, how do I slow down or speed up the date/time system clock rate?   Thanks.
    GeneralRe: System time manipulation
    Richard Lee
    18:15 5 Jul '02  
    System time on the computer is produced by divided the PC counter by two number, so you can change the two number in order to change the system time!The placement of the two number is in the port 0x43 and 0x45(maybe, I forget it)!
    If you speed up the system time you will feel cool when you play some game in the internet for you are very fast!!!
    Generalgenerate calender
    Rizwan Ali
    18:58 21 Jun '01  
    hi,
    i am very new in c++ programming. can i use any functions which returns me the system date & for using that date can i generate the calender for the current month & also for the following ones.. if yes can u send me the code for that .. please
    my email is
    khali_pk@yahoo.com
    thank U. Cry Cry
    Generalhow to delay 0.00002 second
    Julia
    6:37 26 Apr '01  
    I just want to make a time delay for about 0.00002 second. I tried to use your tick.Measure() and tick.GetTickCountAsSeconds(), but failed.
    How can I do? I appreciate any suggestion.

    Confused

    Julia
    GeneralRe: how to delay 0.00002 second
    Anonymous
    0:10 8 May '01  
    Simple. In Windoze you can't. It is not a real-time OS. In fact, it's not even remotely close to a real-time OS.;) Wink
    Generalhow to delay 0.00002 second
    Anonymous
    6:37 26 Apr '01  
    I just want to make a time delay for about 0.00002 second. I tried to use your tick.Measure() and tick.GetTickCountAsSeconds(), but failed.
    How can I do? I appreciate any suggestion.

    Confused

    Julia
    GeneralRe: how to delay 0.00002 second
    Anonymous
    2:52 11 Jun '01  
    I find that setting priority to time critical, then using "GetPerformanceFrequency" / "GetPerformanceCounter" standard MSVC++ 6 functions does this for me - my freq. is ~ 1mHZ for this counter, so you should find this resolution easy in your application.

    Of course, busy waiting on a counter is not "polite" - but sometimes it just needs to be done.

    GeneralHard drive performance monitoring
    Steve Portly
    6:40 20 Sep '00  
    Has anybody seen any good routines that measure seek time, and track switching times on hard drives? There are so many disk caches and buffers in Windows that you can't get an accurate read. I have TASM and thought there must be some simple ASM instructions to bypass the cache?
    GeneralHard drive performance monitoring
    Steve Portly
    6:39 20 Sep '00  
    Has anybody seen any good routines that measure seek time, and track switching times on hard drives? There are so many disk caches and buffers in Windows that you can't get an accurate read. I have TASM and thought there must be some simple ASM instructions to bypass the cache?
    Generalreturn type of CCPUTicker::Measure()
    Rufus V. Smith
    7:23 17 May '00  
    Often while getting the time I'd like to get the current time without making it a two-step operation.

    One simple alternative is adding another method (any name'll do):

    __int64 GetImmediateTickCount();

    Which simply calls the two (measure + get) methods.

    Or Measure could have return type of __int64 instead of void:

    __int64 Measure();

    Or it could have a return type of const CCPUTicker & so it
    could be chained:

    const CCPUTicker & Measure();

    Then example calls could look like:

    __int64 UpTicks = MyTicker.Measure().GetTickCount();

    or

    double UpSeconds = MyTicker.Measure().GetTickCountAsSeconds();

    Or is the overhead of a non-void return type unacceptable?

    Rufus
    GeneralRe: return type of CCPUTicker::Measure()
    PJ Naughter
    11:59 17 May '00  
    I've posted an update on my web site (www.naughter.com) which uses:

    __int64 Measure();

    GeneralWhat about Win32 HighResolutionTimer
    Christian Rodemeyer
    1:44 15 Mar '00  
    The concept of the class is good, but I thought that
    QueryPerformanceCounter is an safe way to do an RDTSC if the right processor is installed. Why not use this functions in your class. You use QueryPerformanceCounter/QueryPerformanceFrequency already when you calculate the processor frequency
    GeneralRe: What about Win32 HighResolutionTimer
    PJ Naughter
    14:45 16 May '00  
    Only the Multiprocessor HAL of NT and Windows 2000 uses the RDTSC instruction. On all other versions of NT/2000, you just get a multiple of the standard PC Timer c. 1.x Mhz.

    My code will work on any Win32 platform and will give you a resolution of the processor clock speed
    GeneralRe: What about Win32 HighResolutionTimer
    Rufus V. Smith
    7:34 17 May '00  
    I, too, had assumed that QueryPerformanceCounter always used RTDSC on a Pentium processor. Now I have to find out what our Windows CE does. Anyone know?


    Last Updated 4 Mar 2000 | Advertise | Privacy | Terms of Use | Copyright © CodeProject, 1999-2010