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.
|