Does Sleep tend to overwait?
#1 Crossbones+ - Reputation: 521
Posted 29 April 2012 - 08:46 AM
#3 Members - Reputation: 3678
Posted 29 April 2012 - 11:02 AM
The voices in my head may not be real, but they have some good ideas!
#4 Crossbones+ - Reputation: 521
Posted 29 April 2012 - 02:09 PM
If you sleep 500 and then take something like 1ms to generate the frame, you just spent 501 ms for a frame, and you'll measure about 1.9961 fps. This sounds like expected behavior to me.
Does a simple std::cout really require 1ms to output something? I simply thought that it would take faster. Thanks for the input.
#5 Members - Reputation: 5801
Posted 29 April 2012 - 05:57 PM
If you sleep 500 and then take something like 1ms to generate the frame, you just spent 501 ms for a frame, and you'll measure about 1.9961 fps. This sounds like expected behavior to me.
Does a simple std::cout really require 1ms to output something? I simply thought that it would take faster. Thanks for the input.
Oh, I probably misunderstood what you tested. Sorry about that. If all you were doing was printing out a number, it shouldn't take anywhere near 1ms, so the explanation of Sleep waiting for too long seems sound.
#6 Crossbones+ - Reputation: 521
Posted 29 April 2012 - 06:28 PM
int main(){
timer_init();
while(true){
timer_begin_frame();
cout << get_fps() << endl;
Sleep(500);
timer_end_frame();
timer_calculate();
}
return 0;
}
begin_frame() and end_frame() grab high resolution tick counts while timer_calculate() subtracts a number and adds.
I'm not too sure how fast timer_calculate() can run, but I don't think this will take anywhere near 1ms.
void __stdcall timer_calculate(){
float fps = static_cast<float>(timer_info.freq.QuadPart) / static_cast<float>(timer_info.time_end.QuadPart - timer_info.time_start.QuadPart);
//Increment current sample and mod if necessary
fps_info.current_sample++;
fps_info.current_sample %= FPS_SAMPLES;
//First run
if(fps_info.first){
for(size_t i = 0; i < FPS_SAMPLES; i++){
fps_info.fps_samples[i] = fps;
}
fps_info.fps = fps;
fps_info.frame_time = 1/fps;
fps_info.fps_sum = static_cast<float>(FPS_SAMPLES) * fps;
fps_info.first = false;
return;
}
//Subtract the previous recorded fps from the sum
fps_info.fps_sum -= fps_info.fps_samples[fps_info.current_sample];
//Add the current sample information to the sample info
fps_info.fps_samples[fps_info.current_sample] = fps;
//Add our data to the sum
fps_info.fps_sum += fps_info.fps_samples[fps_info.current_sample];
//FPS is sum / samples while frame_time = 1/fps
fps_info.fps = fps_info.fps_sum / static_cast<float>(FPS_SAMPLES);
fps_info.frame_time = 1/fps_info.fps;
}
#8 Members - Reputation: 1298
Posted 30 April 2012 - 12:15 AM
Always keep in mind that your program isn't the only thing going on and that with all the background processes, services and what-not there are way more things wanting to run every once in a while than you got cores in your CPU.
#9 Members - Reputation: 127
Posted 30 April 2012 - 05:35 PM
Just put all your events into a std::priority_queue and sleep only if there is more than one timeslice between now and the next event. Otherwise just keep spinning until the time the event occurs.
Edited by Mihai Moldovan, 30 April 2012 - 05:35 PM.
#10 Crossbones+ - Reputation: 521
Posted 30 April 2012 - 05:58 PM
#11 Members - Reputation: 127
Posted 30 April 2012 - 06:03 PM
I'm afraid you don't understand the point of my test. I was simply using a set of functions I wrote and a simple Sleep(500) test to see if I would get reasonably near 2fps. The fact that I was actually waiting 1ms too long made me question whether Sleep tends to over wait or if I have code that is not functioning at top performance.
I was trying to explain the more general application of event queues aka reactor pattern.
#12 Members - Reputation: 2369
Posted 01 May 2012 - 07:51 AM
I'm afraid you don't understand the point of my test. I was simply using a set of functions I wrote and a simple Sleep(500) test to see if I would get reasonably near 2fps. The fact that I was actually waiting 1ms too long made me question whether Sleep tends to over wait or if I have code that is not functioning at top performance.
FPS = 1000 / (sleep_time_in_ms + x).
x = time needed to update fps, to render frame, anything really
sleep_time_in_ms is guaranteed to be 500ms or more.
As such, using method above, it's impossible to get 2.000000 fps, unless x is exactly 0 (cycles, nanoseconds, ...).
Any routine which switches threads, such as sleep, will be accurate up to 20 ms, or whatever the time slice quantum is. Expected times for such approach are 1.92 - 1.99fps.
The lower the sleep time, the larger the range. For sleep time, such as 30ms, fps will vary between 33 and 20.
If you run multiple applications that put more load on CPU, you'll notice the time starts varying, since scheduler cannot find a time slice for your app quickly enough.
Edited by Antheus, 01 May 2012 - 07:53 AM.
#13 Crossbones+ - Reputation: 5152
Posted 01 May 2012 - 09:18 AM
It basically boils down to this.
Sleep() waits for no less than the given time. In other words, it always sleeps more than you want. That is why I am such an antagonist against using it for game loops or anything that relies on timing.
You may as well assume it is possible for Sleep() to wait 5 seconds longer than you specify, because at least then you will follow safe coding practices.
Between the hardware and the operating system, Sleep() gives you 1 and only 1 guarantee: Nothing will happen for at least the time you specify.
The hardware schedules triggers on a regularly scheduled basis. A basis that does not give a damn about the number of milliseconds you sent to your last Sleep() call. If it wants to wait 5 more milliseconds, it will.
Then the operating system, which has the task of scheduling threads, needs to decide which threads are the most starved for attention. Some threads have been put on hold so, well, it’s super-nifty that your little timer went off, but this thread has been waiting for a long time and needs to run for a while.
Timers basically give you 1 and only 1 guarantee: Whatever delay you specify, it will always be longer than that before the timer triggers.
Never use timers for time-sensitive execution.
Does Sleep() sometimes overwait? No. It always overwaits. No exceptions.
L. Spiro
I spent most of my life learning the courage it takes to go out and get what I want. Now that I have it, I am not sure exactly what it is that I want. - L. Spiro 2013
L. Spiro Engine: http://lspiroengine.com
L. Spiro Engine Forums: http://lspiroengine.com/forums







