I needed a portable C++ milliseconds alternative to the Microsoft Windows GetTickCount API, to work on g++ in Linux and OS X, and I also wanted to fix the elapsed time span rollover issue that occurs when you subtract one tick count from another.

Simple C/C++ timing calculation

Use the GetMilliCount and GetMilliSpan functions as follows:

int nTimeStart = GetMilliCount();
// ... processing
int nTimeElapsed = GetMilliSpan( nTimeStart );

This is better than using GetTickCount and subtracting the first tick count from the second since that is subject to the rollover issue described below.

Portable GetTickCount alternative

Here are the functions you can copy and paste into your code (32-bit int is assumed).

#include <sys/timeb.h>

int GetMilliCount()
{
  // Something like GetTickCount but portable
  // It rolls over every ~ 12.1 days (0x100000/24/60/60)
  // Use GetMilliSpan to correct for rollover
  timeb tb;
  ftime( &tb );
  int nCount = tb.millitm + (tb.time & 0xfffff) * 1000;
  return nCount;
}

int GetMilliSpan( int nTimeStart )
{
  int nSpan = GetMilliCount() - nTimeStart;
  if ( nSpan < 0 )
    nSpan += 0x100000 * 1000;
  return nSpan;
}

Note that the maximum millisecond span is about 12.1 days to provide a convenient cutoff in the tb.time seconds to milliseconds calculation.

Elapsed milliseconds rollover issue

GetMilliCount, like GetTickCount, returns a number of milliseconds that starts over (rolls over) when it reaches a maximum. If you subtract an earlier count from a later count, there is a risk of the rollover occuring in the interim, giving an incorrect millisecond span.

GetMilliSpan corrects for the rollover by doing an extra check to see if the rollover occurred in the interim.

The limit

Using the timeb structure and the ftime function, it is possible to obtain millisecond counts beyond the 49.7 day limit of GetTickCount and 32-bit integers.

I considered using a 64-bit integer (VC++ __int64 or g++ int64_t) which can handle 500 billion years of milliseconds. But 64-bit integers introduce additional portability issues.

Generally you want to know how long an action takes from a fraction of a second to a few seconds. In rare cases you might want to measure hours or days with milliseconds in C++. The GetMilliCount limit of 12.1 days is plenty for most purposes.

More accuracy

The solution shown here is okay for easily giving the user feedback on how long something took, such as how long it took to parse or save a document. But system clock milliseconds is not the most accurate way to measure performance.

The time a process takes to perform an activity is affected by other system usage, plus the clock ticks are generally multiple milliseconds and don't give you the granularity to estimate actual CPU usage.

For more accurate timing information, look for code performance profiling solutions or a high resolution performance counter like Windows QueryPerformanceCounter which returns a 64-bit LARGE_INTEGER.

 

comment posted using GetMilliCount

Mark Plunkett 09-Apr-2009

I'm developing some software for a university final year project and I found your GetTickCount alternative very useful, I am just enquiring as to whether it falls under any license, and whether it is ok to include in my project, which I am planning to open source upon completion?

It is public domain, use at will, include in your open source project, etc. Best wishes.