Jump to content

  • Log In with Google      Sign In   
  • Create Account

Awesome job so far everyone! Please give us your feedback on how our article efforts are going. We still need more finished articles for our May contest theme: Remake the Classics

Does Sleep tend to overwait?


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
12 replies to this topic

#1 incertia   Crossbones+   -  Reputation: 521

Like
0Likes
Like

Posted 29 April 2012 - 08:46 AM

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?
Current project here

Ad:

#2 Álvaro   Members   -  Reputation: 5801

Like
0Likes
Like

Posted 29 April 2012 - 08:55 AM

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.

#3 SimonForsman   Members   -  Reputation: 3678

Like
1Likes
Like

Posted 29 April 2012 - 11:02 AM

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

#4 incertia   Crossbones+   -  Reputation: 521

Like
0Likes
Like

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.
Current project here

#5 Álvaro   Members   -  Reputation: 5801

Like
0Likes
Like

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 incertia   Crossbones+   -  Reputation: 521

Like
0Likes
Like

Posted 29 April 2012 - 06:28 PM

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[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;
}

Current project here

#7 Digitalfragment   Members   -  Reputation: 398

Like
0Likes
Like

Posted 29 April 2012 - 10:44 PM

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.
-Shaun Stamper, Graphics Programmer / Tools Ninja @ Big Ant Studios

#8 Trienco   Members   -  Reputation: 1298

Like
0Likes
Like

Posted 30 April 2012 - 12:15 AM

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

#9 Mihai Moldovan   Members   -  Reputation: 127

Like
0Likes
Like

Posted 30 April 2012 - 05:35 PM

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.

Edited by Mihai Moldovan, 30 April 2012 - 05:35 PM.


#10 incertia   Crossbones+   -  Reputation: 521

Like
0Likes
Like

Posted 30 April 2012 - 05:58 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.
Current project here

#11 Mihai Moldovan   Members   -  Reputation: 127

Like
0Likes
Like

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 Antheus   Members   -  Reputation: 2369

Like
0Likes
Like

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 L. Spiro   Crossbones+   -  Reputation: 5152

Like
0Likes
Like

Posted 01 May 2012 - 09:18 AM

Antheus explained it, but I wanted to try to explain it with a different approach.

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
It is amazing how often people try to be unique, and yet they are always trying to make others be like them. - L. Spiro 2011
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




Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS