QueryPerformanceCounter: WOW !

Started by
28 comments, last by BSXrider 22 years, 2 months ago
You can increase the resolution of timeGetTime() using timeBeginPeriod()/timeEndPeriod(). I''ve successfully changed timeGetTime()''s resolution to 1ms on my Win2K system. You only need to do this on NT-based systems, since on 9X it has a default resolution of 1ms already. You never really need QPC() unless you''re timing code...

This stuff is in the documentation.


--
Eric
-- Eric
Advertisement
Just a side not on timeBeginPeriod/timeEndPeriod: the MSDN docs state you should call timeBeginPeriod "immediately before using timer services" and class timeEndPeriod "immediately after you are finished using the timer services".

I assume they mean you shouldn''t call timeBeginPeriod/timeEndPeriod at the start and end of your program, respectively, but rather just before starting timeGetTime and after the ending timeGetTime. Keep this in mind if you are reading NVIDIA''s document on function times, because it doesn''t take into consideration the time it takes to call the timeBeginPeriod/timeEndPeriod pair.


- Houdini


- Houdini
quote:Original post by ekenslow
You can increase the resolution of timeGetTime() using timeBeginPeriod()/timeEndPeriod(). I''ve successfully changed timeGetTime()''s resolution to 1ms on my Win2K system. You only need to do this on NT-based systems, since on 9X it has a default resolution of 1ms already. You never really need QPC() unless you''re timing code...

This stuff is in the documentation.


--
Eric


Well my current project pulls 1000+ fps so 1ms accuracy is definately not enough

And given that the timer, whichever one you choose is only called once a loop it seems to me anyone would be silly not to use the best you can get. My computer appeared to take 1.7 us to make a QPC call. At 100 fps that''s 0.017 % of your available processing time.

- seb
quote:Original post by DrPizza
One reason for this is probably that QueryPerformanceFrequency''s result is defined as being constant whilst a system remains booted.

I''m almost certain that changed between NT4 and 2k, and that this is no longer the case with 2k nor XP.

timeBeginPeriod/timeEndPeriod affect context switching time - i.e. if you call timeBeginPeriod(1) you thread-time slices will be 1ms long, not 10ms (or 16ms seems to be the popular default on Compaqs).
- The trade-off between price and quality does not exist in Japan. Rather, the idea that high quality brings on cost reduction is widely accepted.-- Tajima & Matsubara
Trying to maintain 1000 fps is just silly. If your game runs at 1000 fps then- at best- for every 10 frames it draws, 1 is displayed to the user. That''s being generous- below 100Hz refresh rate you''ll draw and discard even more frames for every one actually displayed.

If you want to use QueryPerformanceCounter() because it makes you feel good, then go right ahead- it''s your code. But don''t try to say that timeGetTime() at 1ms resolution is too slow for your framerate, because that''s BS.


--
Eric
-- Eric
quote:I''m almost certain that changed between NT4 and 2k, and that this is no longer the case with 2k nor XP.

I was quoting almost directly the November 2K1 Platform SDK (for QueryPerformanceFrequency), so I don''t think it''s changed.
char a[99999],*p=a;int main(int c,char**V){char*v=c>0?1[V]:(char*)V;if(c>=0)for(;*v&&93!=*v;){62==*v&&++p||60==*v&&--p||43==*v&&++*p||45==*v&&--*p||44==*v&&(*p=getchar())||46==*v&&putchar(*p)||91==*v&&(*p&&main(0,(char**)(--v+2))||(v=(char*)main(-1,(char**)++v)-1));++v;}else for(c=1;c;c+=(91==*v)-(93==*v),++v);return(int)v;}  /*** drpizza@battleaxe.net ***/
NVidia''s code isn''t very good.

rdtsc doesn''t force serialization, but to do the job properly, you generally need to ensure that all pending instructions are flushed before calling it.

This increases the time taken to execute it, but means that you can actually use it to time how long something has taken (rather than timing how long something has taken to partially execute).

Certain instructions force serialization, however, I can''t remember any off the top of my head.
char a[99999],*p=a;int main(int c,char**V){char*v=c>0?1[V]:(char*)V;if(c>=0)for(;*v&&93!=*v;){62==*v&&++p||60==*v&&--p||43==*v&&++*p||45==*v&&--*p||44==*v&&(*p=getchar())||46==*v&&putchar(*p)||91==*v&&(*p&&main(0,(char**)(--v+2))||(v=(char*)main(-1,(char**)++v)-1));++v;}else for(c=1;c;c+=(91==*v)-(93==*v),++v);return(int)v;}  /*** drpizza@battleaxe.net ***/
quote:Original post by DrPizza
I''m almost certain that changed between NT4 and 2k, and that this is no longer the case with 2k nor XP.

I was quoting almost directly the November 2K1 Platform SDK (for QueryPerformanceFrequency), so I don''t think it''s changed.

Maybe it wasn''t QueryPerformanceFrequency… I''ll have to check at work tomorrow. I though it was the disasm of of QPF we were looking at, that did a bunch of stuff to detect if/when the CPU clock changed speed… maybe it was timeGetTime
- The trade-off between price and quality does not exist in Japan. Rather, the idea that high quality brings on cost reduction is widely accepted.-- Tajima & Matsubara
quote:Original post by DrPizza
Certain instructions force serialization, however, I can''t remember any off the top of my head.

CPUID seems to be the one most popular one.
ReactOS - an Open-source operating system compatible with Windows NT apps and drivers
quote:Original post by Martee
CPUID seems to be the one most popular one.


Yup. Anyway, any true measurement using rdtsc needs to do a cpuid to force serialization.

This introduces the problem of having to time the cpuid too, but you can work around that.
char a[99999],*p=a;int main(int c,char**V){char*v=c>0?1[V]:(char*)V;if(c>=0)for(;*v&&93!=*v;){62==*v&&++p||60==*v&&--p||43==*v&&++*p||45==*v&&--*p||44==*v&&(*p=getchar())||46==*v&&putchar(*p)||91==*v&&(*p&&main(0,(char**)(--v+2))||(v=(char*)main(-1,(char**)++v)-1));++v;}else for(c=1;c;c+=(91==*v)-(93==*v),++v);return(int)v;}  /*** drpizza@battleaxe.net ***/

This topic is closed to new replies.

Advertisement