The Code Project View our advertisersSupport Code Project and purchase Visual Studio .NET from $899Advertise on the CodeProject
All Topics, MFC / C++ >> C++ / MFC >> Algorithms

A C++ class for more precise time interval measurement
By George Anescu

A C++ class capable to measure time intervals in microseconds under Windows OS 
 C++ (VC6)
Windows (Win95, Win98, NT4, Win2K)
Win32, VS
Dev
 Posted 12 Oct 2001
 Updated 18 Oct 2001
Articles by this author
51,316 views
Search:
Toolbox
Broken Article?
VS.NET 2003 from $899
MSDN Univ. from $2499
Print version
Bookmark this
Send to a friend
My Profile
My Settings
My Articles
My Bookmarks
Sign out
 


23 members have rated this article. Result:
Popularity: 5.39. Rating: 3.96 out of 5.

Introduction

This timer class is capable to measure time intervals in microseconds under Windows OS. It is using the less known Windows API functions QueryPerformanceFrequency() and QueryPerformanceCounter() for getting the frequency and respectively the counts of the high-resolution performance counter. For systems where such a high-resolution performance counter is not available, the more known API function GetTickCounts() is used instead, but with a performance penalty on the timer's precision. The reliability of the timer is depending anyway on the system's hardware performance, i.e. the accuracy is increased for systems with higher processor frequency. The class is also demonstrating some useful tips about using the __int64 integers in VC++.

Implementation

Here I present only the public user interface of the CPreciseTimer class, the implementation details being in the demo project source files:

class CPreciseTimer
{
public:
    CPreciseTimer();
    bool SupportsHighResCounter();
    void StartTimer();
    void StopTimer();
    __int64 GetTime();
};
  • The constructor CPreciseTimer() at the first class's instance construction is also determining if the high-resolution performance counter is available, and in the favorable case is initializing the frequency member variable. Subsequent constructions are not repeating this computation block.

  • The function SupportsHighResCounter() is returning true only if the high-resolution performance counter is available. It is giving to the user a clue about the accuracy of the timer.

  • The function StartTimer(), as the name says, is starting the timer.

  • The function StopTimer() is stopping the timer, also keeping the elapsed time since the timer was started.

  • The function GetTime() in case the timer is in the running state is returning the time interval since the timer was started. If the timer is in the stopped state then it is returning the time difference between the last stop call and the last start call. The returned value is in microseconds, but it cannot be trusted if the high-resolution performance counter is not available, case for which the accuracy cannot be in fact higher than the order of milliseconds.

How to use it

The following code snippet is showing a simple use example:

CPreciseTimer oPreciseTimer;
cout << "Starting!" << endl;
oPreciseTimer.StartTimer();
::Sleep(5000);
cout << "Ending!" << endl;
oPreciseTimer.StopTimer();
__int64 i64Diff = oPreciseTimer.GetTime();
cout << "Diff=" << Int64ToString(i64Diff) << endl;
return 0;

I am using my own function Int64ToString() for displaying __int64 numbers. I also give this function for free use below:

string Int64ToString(__int64 const& ri64, int iRadix=10)
{
    bool bNeg = (ri64 < 0);
    __int64 i64 = ri64;
    string ostrRes;
    bool bSpecial = false;
    if(true == bNeg)
    {
        i64 = -i64;
        if(i64 < 0)
        // Special case number -9223372036854775808 or 
        // 0x8000000000000000
        bSpecial = true;
        ostrRes.append(1, '-');
    }
    int iR;
    do
    {
        iR = i64 % iRadix;
        if(true == bSpecial)
            iR = -iR;
        if(iR < 10)
            ostrRes.append(1, '0' + iR);
        else
            ostrRes.append(1, 'A' + iR - 10);
        i64 /= iRadix;
    }
    while(i64 != 0);
    //Reverse the string
    string::iterator it = ostrRes.begin();
    if(bNeg)
        it++;
    reverse(it, ostrRes.end());
    return ostrRes;
}

It is capable to display __int64 values in any radix base (the default radix base being 10). __int64 values can also be displayed using the printf() function as in the following code snippet:

__int64 i64 = 0x7fffffffffffffff;
printf("Decimal Value = %I64d\n", i64);
printf("Hexa Value = %I64x\n", i64);

You can also use in MFC applications the Format() function of CString:

CString str;
str.Format("%I64d", 4294967307);

or a stdlib function _i64toa() which is similar to itoa():

__int64 i64 = 4294967307;
char szBuff[20];
_i64toa(i64, szBuff, 10);

Conclusion

The project attached to this article contains the source code of the presented CPreciseTimer class and test code. I am interested in any opinions and new ideas about this implementation.

George Anescu


Click here to view George Anescu's online profile.


Other popular articles:

[Top] Rate this Article for us!     PoorExcellent  
MSDN Magazine - Your guide to Microsoft tools, development environments, and technologies for Windows and the Web.
Premium Sponsor

The power of a complete PDF toolkit combined in one handy component
FAQ Noise level    Search comments  
 View   Per page  
New threadMsgs 1 to 9 of 9 (Total: 9) (Refresh)First Prev Next     
Subject 
Author 
Date 
  C++ MFC timer help...
 yihaa 22:21 27 Aug '04 
  Ask about Tree
 MinhHai 3:13 2 Jul '03 
  Check out CPerfTimer
 Dean Wyant 11:05 22 Oct '01 
  Re: Check out CPerfTimer
Unconfirmed/Anonymous posting Kimon Hoffmann 18:22 12 Aug '02 
Help!
Articles
Message Boards
StoreFront
Lounge
What is 'The Code Project'?
General FAQ
Post a Question
Site Directory
About Us
Latest
Most Popular
Search
Site Directory
Submit an Article
Update an Article
Article Competition
Visual C++
ATL / WTL / STL
COM
Managed C++
C#
ASP.NET
VB.NET
Web Development
.NET Framework
SQL / ADO / ADO.NET
XML / XSL
OS / SysAdmin
Work Issues
Article Requests
Collaboration
General Discussions
Suggestions
The Soapbox