Does Sleep tend to overwait?

Started by
11 comments, last by L. Spiro 11 years, 11 months ago
I've been the high performance timers (QueryPerformaceCounter) to time program fps. I've let the program take the average of 256 fps samples to produce the final fps. So I test it with Sleep(500), expecting the fps to be around 2, but I've found that the fps steadily decreases until it stabilizes around 1.9961 - 1.9962. Frame time, on the other hand, seems to be increasing by 0.00006 per query. Is this normal and should be disregarded as float inaccuracies?
what
Advertisement
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.
sleep (on Windows) will sleep for atleast the specified amount of time so in general it will sleep for slightly longer than specified. (Exactly how long it sleeps depend on alot of factors such as other running processes, available cpu cores, scheduler timeslice size, etc), It is a bad idea to use sleep to control the speed an application runs at, only use sleep to reduce cpu usage for mobile devices(when running on battery) or for enviromental reasons.
[size="1"]I don't suffer from insanity, I'm enjoying every minute of it.
The voices in my head may not be real, but they have some good ideas!

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.
what

[quote name='alvaro' timestamp='1335711300' post='4935838']
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.
[/quote]

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.
Yeah lol, this was my test program:


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 = 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;
}
what
Sleep() in the windows library will quite frequently sleep for longer than you specify. IIRC it yields the remaining time slice which can defaults to 15ms in length.
To make it short: there simply is no way to wait for any exact amount of time. There are a ton of processes running and a scheduler juggling them all. When you suspend your process with sleep all you can do is "nicely ask" to be resumed in at least x ms. Even if you waste resources by busy waiting the scheduler can suspend you at any time and you won't get to run again in time.

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.
f@dzhttp://festini.device-zero.de
This is so obvious, yet I see so many threads about this subject with no clear answers.

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.
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.
what

This topic is closed to new replies.

Advertisement