High resolution counter

Started by
11 comments, last by GameDev.net 18 years, 11 months ago
Hello, In my multiplayer game, i may need that things move at the same speed on each client. So, i'd like to use a seperate thread for moving my objects and displaying. Moving and displaying in the same thread may force my objects to move at the monitor frequency, because directx' Device::Present() waits for vertical retrace before copying backbuffer. Moving things in my game will have a speed expressed in "unit of measure per unit of time" where unit of measure is defined and unit of time may be µs or ms. I'm using C# and hoped to use Environment.TickCount that should return the number of elapsed milliseconds since the beginning of the program. But i've made some tests and its accuracy seem to be computer specific. On my computer, it provides a new value only each 16ms (62,5Hz, quite my monitor frequency). It's the same for TimeDate.Now.Ticks. I've found this win32 function that i could import in my c# code : QueryPerformanceCounter() But i've read this is not available on every systems. Do you know on which kind of systems this is unavailable? or do you know another method to fetch a better counter?
Advertisement
Here's some information on timers. From that page:
Quote:
The Pentium processor and most PC compatible processors such as AMD support a high-resolution Performance Counter, which can provide a resolution of less than one microsecond.

The QueryPerformanceFrequency function is used to determine the actual frequency of the counter. This is the numeric value that the Performance Counter will increase by in 1 second.

The QueryPerformanceCounter function is used to read the Performance Counter, which may be divided by the counter frequency to determine the time in seconds.

Both of these functions take a pointer to a LARGE_INTEGER union, which will be filled with the requested value if the function is successful.

The function will return 0 on failure, or non-zero on success.


Ideally what you should do is something like this. Have support for two timers in case the QueryPerformanceCounter does not exist. Other than that, that timer is the best you can have. I don't know how much of help that code is begin in C++ format, but hopefully you can get the idea of what to do. Good luck! [smile]
Oh, i see
You use another counter method if QueryPerformanceCounter is not available

Thanks
timeGetTime with a call to timeBeginPeriod(1) in the beginning and timeEndPeriod(1) in the end isn't as accurate as QueryPerformanceCounter which uses the TSC, but is more accurate than the ones you describe, so it could be a good second choice for a timer.

You should be aware of mobile processors that can change their clock frequency, because then your timing won't work if you're using the ones that totally rely on the frequency, like QueryPerformanceCounter. timeGetTime will do the job in those cases, so that should be a good second choice for a timing system.
Killers don't end up in jailThey end up on a high-score!
Cool, yes timeGetTime() seems to be more suitable for me
i decided to learn and test timeGetTime throughoutly before turning to QuerryPerformacneCounter but after running some tests on differen machines I noticed the in a longer loop the times vary. i don't really understand why but on one pc it takes the loop 10 sec to execute while on other machines it takes 7 or 15 seconds. the time factor is set to 0.01 second as with lower values differences between times to execute the loop vary much more.

can anyone explain to me this weir behaviour?

reagrds
Quote:Original post by ursus
i decided to learn and test timeGetTime throughoutly before turning to QuerryPerformacneCounter but after running some tests on differen machines I noticed the in a longer loop the times vary. i don't really understand why but on one pc it takes the loop 10 sec to execute while on other machines it takes 7 or 15 seconds. the time factor is set to 0.01 second as with lower values differences between times to execute the loop vary much more.

can anyone explain to me this weir behaviour?

reagrds


If the OS is multithreaded anything could happen in between your loop start and end. If you haven't, you should set the priority of your thread to real-time to get the best/most accurate results. I'm assuming that you did shut down all other programs that could be shut down without trouble (anti-virus, firewall, messenger etc.) while you were testing it?

I haven't tested timeGetTime on my computers yet, but I would certainly make sure that my above terms are reached before testing - otherwise it could just as easily be another program(s) that were causing the slowdown.
Killers don't end up in jailThey end up on a high-score!
most likely you're right, but if so, can someone explain to me how it's done with pro games? even those short and simple ones appear to run at constant speed (despite changing frame rates) on most pcs?
Two things: Don't use QueryPerformance*, because it doesn't work properly on computers that vary their cpu speed. Almost all laptops do this, and most modern pentium 4 processors do as well (and in the future, AMDs will likely do the same).

Next, leave your game's process priority set to normal. To do otherwise will interfere with the operating system in a negative way, and can cause the whole system to become so unresponsibe that the only option for the user is to do a manual reboot (on modern machines that means either holding the power button for a while or pulling the plug).

Finally, it shouldn't matter how long the frame takes as long as you base movement on time. If you're doing straight line movement, then each frame you just do position += velocity * time. For more complicated systems (with things like gravity, acceleration and that kind of thing), you need more advanced systems (called numerical integrators). A popular and rather accurate one is calld RK4
"Walk not the trodden path, for it has borne it's burden." -John, Flying Monk
Extrarius,

i caould put some example source here, but i'll just resort to famous NEHE 21 tutorial. when i ran it on different pcs it works with differen speed. so it's the question of the code i suppose.

i heard about accumulators. have you got any experience using them? are they worth learning and implementing?

take care

This topic is closed to new replies.

Advertisement