Inaccuracy of windows thread waits

Started by
19 comments, last by Raghar 15 years, 8 months ago
Is anyone aware of a method to get greater then the 15 millisecond or so accuracy used by the windows thread wait functions( such as Sleep(), WaitForSingleObject()SignalObjectAndWait())? MSDN claims timeBeginPeriod() should increase the accuracy, but even setting it to 1 does not help. I really need far greater accuracy for what I am doing and am rather amazed at how inaccurate these functions are.. Thanks
Advertisement
You can call timeBeginPeriod (and timeEndPeriod) to lower the slicing time to roughly 1ms. Out-of-the-box many PCs are configured to slice at 16ms intervals today (in the past it was 10ms!).

Note that Sleep() does not make any timing guarantees other than your thread will be serviced again sometime 'later'.

To do better than that you would have to hook into a hardware timer and I don't think there's an easy way to do that.
- 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
Why do you need lots of accuracy?

If you only need to wait for a small amount of time, then a spin-lock (possibly with a Sleep(0) call) may be appropriate.
Quote:Original post by AndyPandyV2
I really need far greater accuracy for what I am doing and am rather amazed at how inaccurate these functions are.
The OS is not designed for hard Real-Time computing requirements.

The OS works on scheduled time slices, and yielding the rest of your time slice sticks you at the back of the queue within your priority level. You have no guarantees about when (if ever) the OS will return to you.

What exactly are you trying to do that requires being woken up at more frequent intervals?

There may be other options available, such as Sleep(0) mentioned above so you wait until others in the slice have all yielded their time, using a callback from some other system or driver, operating at the kernel or device driver level, or otherwise digging your application into the OS internals. Deciding the best course of action depends on your eventual goal.
I was hoping to use these wait functions so that the primary threads of the game could surrender any leftover time in the frame to other secondary threads. And while setting timeBeginPeriod seems to slightly increase the accuracy, there are still instances where it takes up to 45+ milliseconds for the Wait to return which is causing very ugly stuttering. I guess I'll just have to waste those extra cycles spinning and doing nothing...
Quote:Original post by AndyPandyV2
I was hoping to use these wait functions so that the primary threads of the game could surrender any leftover time in the frame to other secondary threads. And while setting timeBeginPeriod seems to slightly increase the accuracy, there are still instances where it takes up to 45+ milliseconds for the Wait to return which is causing very ugly stuttering. I guess I'll just have to waste those extra cycles spinning and doing nothing...
If other games can manage without going to this trouble, then your game should be able to as well. If you're getting inconsistencies in your frame rate then you're probably hitting the disk during play, even if it's just paging memory.
Spinning until the desired time elapses probably wont help. Hogging the CPU can make your app less smooth, as the task scheduler compensates somewhat I believe.
Any chance you can profile your code?
"In order to understand recursion, you must first understand recursion."
My website dedicated to sorting algorithms
You may find that instead of sleeping, blocking waiting for a critical section / mutex / event will work better.
I've profiled it, it is the Wait calls, they sometimes take 10x longer then they should. It makes sense now that I know about the OS scheduling rather lengthy time slices for different threads, likely there just aren't any slices available when the wait runs out so it has to wait until the next round of slices. I was assuming the OS would return control when the time was up but it is obviously not consistent so I'll just have to rework it to function differently.
You could try.

SetThreadPriority

http://msdn.microsoft.com/en-us/library/ms686277(VS.85).aspx
Quote:Original post by AndyPandyV2
I was hoping to use these wait functions so that the primary threads of the game could surrender any leftover time in the frame to other secondary threads.


Wrong reason. Concurrency is all about *not* waiting for anything, but simply going on and doing useful work.

If you need to wait in this manner, then cooperative threads or single-threaded approach will be much better.


Multi-threaded programming is annoying because of such details. One solution is to simply not wait:
while (true) {  if (currentTime < nextFrameTime) {    doSomethingUseful();  } else {    renderFrame();  }};
The other, when using worker threads:
while (scheduler->running() {  Task * task = NULL;  if (this->isRenderThread()) {    task = scheduler->getRenderTask();  } else {    task = scheduler->getNextTask();  }  if (task) {    task->run();  } else {    scheduler->waitForTask();  }}
You can then just spawn a number of these workers, and they'll wait for work to come in. Rendering however will always be performed in same, main thread. Obviously, more generic approaches exist for this.

WaitForSingleObject() would be inside waitForTask().

Quote:SetThreadPriority


This is generally wrong solution to the problem. There are uses for priorities, but this isn't one of them.

Quote:I was assuming the OS would return control when the time was up


Unless the OS and hardware you're running on comes with a large fancy certificate saying "Real-Time" and costs a fortune, you will never have such guarantees.

Quote:I really need far greater accuracy for what I am doing and am rather amazed at how inaccurate these functions are


For concurrency, you don't need a timer at all, at least not for this. OS times the slices quite well. Even for cooperative threads.

This topic is closed to new replies.

Advertisement