Simple PC Timer using QueryPerformanceCounter

Microsoft recommend that we use QueryPerformanceCounter() for high-performance, high-accuracy timers on Windows. If you're on modern hardware, this generally works well (except current bugs on some Athlon X2 systems). There are three sources of timing information for QPC:

  • New north-bridge hardware performance timers
  • Time stamp counter (RDTSC) on P4 level hardware
  • PCI bridge timers
QPC uses whichever it finds, in the order given. If you have a modern motherboard with new performance timers, everything is cool. If you have a CPU which does not do SpeedStep, and Windows uses RDTSC on your system, you also have a good timer. Last, if you're using the PCI bridge timers, you may suffer from a bug where time jumps ahead by one to four seconds every once in a while, but otherwise it's OK.

So, assuming you can live with these restrictions, you might want to use the following timer class (which works around some bugs found in other timer classes I've seen on the net, while also being simpler):

#include <windows.h>

/// Create a Timer, which will immediately begin counting
/// up from 0.0 seconds.
/// You can call reset() to make it start over.
class Timer {
  public:
    Timer() {
      reset();
    }
    /// reset() makes the timer start over counting from 0.0 seconds.
    void reset() {
      unsigned __int64 pf;
      QueryPerformanceFrequency( (LARGE_INTEGER *)&pf );
      freq_ = 1.0 / (double)pf;
      QueryPerformanceCounter( (LARGE_INTEGER *)&baseTime_ );
    }
    /// seconds() returns the number of seconds (to very high resolution)
    /// elapsed since the timer was last created or reset().
    double seconds() {
      unsigned __int64 val;
      QueryPerformanceCounter( (LARGE_INTEGER *)&val );
      return (val - baseTime_) * freq_;
    }
    /// seconds() returns the number of milliseconds (to very high resolution)
    /// elapsed since the timer was last created or reset().
    double milliseconds() {
      return seconds() * 1000.0;
    }
  private:
    double freq_;
    unsigned __int64 baseTime_;
};



#include <stdio.h>

/* a simple test function */
int main() {
  Timer t;
  double a = t.seconds();
  Sleep( 1 );
  double b = t.seconds();
  t.reset();
  double c = t.seconds();
  printf( "%g %g\n", b-a, c );
  return 0;
}

That's it! Have fun!

If you're more interested in hardware compatibility, check my other article on PC timers which talks a bit about the various problems with various timers on the PC hardware platform.