Page 1 of 1
QueryPerformanceCounter() not returning millisecs ?!?!
Posted: Tue Apr 04, 2006 8:34 am
by nco2k
Code: Select all
QueryFreq.q
QueryCount1.q
QueryCount2.q
tgtCount1.l
tgtCount2.l
DisableDebugger
timeBeginPeriod_(1)
If QueryPerformanceFrequency_(@QueryFreq)
QueryPerformanceCounter_(@QueryCount1)
Delay(500)
QueryPerformanceCounter_(@QueryCount2)
EndIf
tgtCount1 = timeGetTime_()
Delay(500)
tgtCount2 = timeGetTime_()
timeEndPeriod_(1)
EnableDebugger
Debug "Hardware Timer: "+Str(QueryCount2 - QueryCount1)
Debug "Software Timer: "+Str(tgtCount2 - tgtCount1)
the software timer returns here correctly the 500ms, but the hardware timer returns ~1457359560 here. whats that value?! this cant be millisecs, shouldnt QueryPerformanceCounter() return millisecs or have i missed something??
c ya,
nco2k
Posted: Tue Apr 04, 2006 9:06 am
by maw
You have missed something

Always read MSDN first
http://msdn.microsoft.com/library/defau ... ounter.asp
The high resolution PerformanceCounter gives you "counts per second" which with todays CPUs is several million counts per second. QueryPerformanceFrequency_() returns the number of "counts per second" the hardware you are running on is capable of.
Together with QueryPerformanceCounter_() you have a timer resolution that on the fastest CPUs will be in the nanoseconds range. Very nice for benchmarking single instructions

Posted: Tue Apr 04, 2006 9:21 am
by netmaestro
QueryPerformanceFrequency returns the maximum number of slices you can cut one second into. It's usually a very high number, around four million on my machine. To get an accurate timeslice equal to one millisecond, you divide that number by 1000 and that is what you will test using QueryPerformanceCounter to see if a millisecond has gone by yet.
Here's a procedure that accurately returns ticks at a resolution of one ms: (by rescator)
Code: Select all
Procedure.l TicksHQ()
Static maxfreq.q
Protected t.q
If maxfreq=0
QueryPerformanceFrequency_(@maxfreq)
maxfreq=maxfreq/1000
EndIf
QueryPerformanceCounter_(@t.q)
ProcedureReturn t/maxfreq
EndProcedure
Divide maxfreq by 10000 instead of 1000 if you want tenths of a millisecond.
Usage:
Code: Select all
t=TicksHQ()
Repeat
t2=TicksHQ
If t2-t
; a millisecond has passed
; do some stuff
t=t2
EndIf
Until PureBasic 4.0 is released
Posted: Tue Apr 04, 2006 9:31 am
by dagcrack
Well, by not discounting the function overhead you're trashing the accuracy if you were using a higher res.
You're also dividing.. got an if statement in there...etc. big overhead if you ask.
Posted: Tue Apr 04, 2006 9:35 am
by netmaestro
Theoretically, yes. But from a practical standpoint, at res's of up to 1/10 ms the function overhead is not significant enough to impact accuracy. Res's much higher than that are not practical for much, afaik. You can't get FPS anywhere near that, for example. My testing shows no degradation of accuracy that would impact a practical application of the counter. But - you're more than welcome to improve on it!
Posted: Tue Apr 04, 2006 9:38 am
by nco2k
thanks guys for clearing this up and thanks netmaestro for the example code, this will become pretty handy. now i have a better idea of how to use this great highres counter.
c ya,
nco2k
Posted: Tue Apr 04, 2006 10:03 am
by dagcrack
Of course at that res theres no problem, I just pointed out that there is an overhead .. For benchmarking purposes it would be cool if you took the overhead into account and reduced it from the result value.
I just like to see things well done even if sometimes theres not a big difference

Re: QueryPerformanceCounter() not returning millisecs ?!?!
Posted: Wed Jun 13, 2012 2:33 pm
by chris319
Code: Select all
maxfreq.q: a.q: b.q: t_total.d = 0: t_average.d
QueryPerformanceFrequency_(@maxfreq)
maxfreq / 1000
For ct = 1 To 100
QueryPerformanceCounter_(@a.q)
Delay(20)
QueryPerformanceCounter_(@b.q)
t_total + (b - a) / maxfreq
t_average = t_total / ct
Debug "Average: " + StrD(t_average, 3) + " milliseconds"
Next