From David Fries, changed the Win32 Timer init code across to using

QueryPerformanceCounter to avoid inaccurate and slow original Sleep based code.
This commit is contained in:
Robert Osfield
2004-03-02 21:37:44 +00:00
parent 05969004c6
commit f10a47ed75

View File

@@ -47,20 +47,75 @@ const Timer* Timer::instance()
}
else
{
// use a static here to ensure that the Sleep(..) for 1 sec
// is not incurred more than once per app execution.
// use a static here to ensure that the time to determine
// the cpu frequency is not incurred more than once
// per app execution.
static double _tempSecsPerClick=0.0;
if (_tempSecsPerClick==0.0)
{
Timer_t start_time = tick();
Sleep (1000);
Timer_t end_time = tick();
// QueryPerformanceCounter under Windows 2000 Service Pack 3
// two 2.4 GHz cpus was timed to take about 70 times longer
// than the RDTSC assembly instruction sequence, but if
// that counter is available we use it to quickly determine
// the Time Stamp Counter rate, quickly as in 240 microseconds
LARGE_INTEGER frequency;
if(QueryPerformanceFrequency(&frequency))
{
//#define DEBUG_TIME_OUTPUT 1
LARGE_INTEGER QPCstart, QPCstop,
QPCstartAfter, QPCstopAfter;
Timer_t TSCstart, TSCstop;
double QPCSecsPerClock = 1.0/frequency.QuadPart;
double elapsed, last, current, bound;
_tempSecsPerClick = 1.0/(double)(end_time-start_time);
QueryPerformanceCounter(&QPCstart);
TSCstart=tick();
QueryPerformanceCounter(&QPCstartAfter);
current = 0;
do
{
// store the seconds per clock
last = current;
// read the clocks
QueryPerformanceCounter(&QPCstop);
TSCstop=tick();
QueryPerformanceCounter(&QPCstopAfter);
// average before and after to approximate reading
// both clocks at the same time
elapsed = ((QPCstop.QuadPart+QPCstopAfter.QuadPart)
-(QPCstart.QuadPart+QPCstartAfter.QuadPart))/2.0
*QPCSecsPerClock;
// TSC seconds per clock
current = elapsed / (TSCstop-TSCstart);
// calculate a bound to check against
bound = current/1000000;
// break if current-bound<last && current+bound>last
}while(current-bound>last || current+bound<last);
_tempSecsPerClick = current;
#ifdef DEBUG_TIME_OUTPUT
fprintf(stderr, "current %e, last %e\n",
1.0/current, 1.0/last);
fprintf(stderr, "Total Time %e\n",
(QPCstop.QuadPart-QPCstart.QuadPart)*QPCSecsPerClock);
#endif
}
#ifndef DEBUG_TIME_OUTPUT
else
#endif
{
Timer_t start_time = tick();
Sleep (1000);
Timer_t end_time = tick();
_tempSecsPerClick = 1.0/(double)(end_time-start_time);
#ifdef DEBUG_TIME_OUTPUT
fprintf(stderr, "Sec delay rate %e\n",
1.0/_tempSecsPerClick);
#endif
}
}
_secsPerTick = _tempSecsPerClick;
}
}