What could produce this bizzare behavior with two threads sleeping at the same time?

There are two SDL threads. One is an events thread, and another does
rendering. The rendering thread uses variables from the events thread.
There are mutex locks but they are irrelevant since I noticed the
behavior is same even if I remove them completely (for testing).

If I do a in the rendering thread alone, for 10 milliseconds, the FPS
is normally 100.

If I do no sleep at all in the rendering thread and a SDL_Delay() in
the events thread, the rendering thread does not slow down at all.

But, if I do a sleep of 10 milliseconds in the rendering thread and 10
in the events thread, the FPS is not 100, but lower, about 84! (notice
it’s the same even if mutex locks are removed completely)

(If none of them has sleeps it normally goes high.)

What could produce this behavior?–

The behavior is same both with SDL_Delay() and a direct windows’ Sleep().

Correction. This was "If I do an SDL_Delay() in […]"On Wed, Jan 26, 2011 at 10:45 AM, Michael Menegakis <@Michael_Menegakis> wrote:

If I do a in the rendering thread alone, for 10 milliseconds, the FPS
is normally 100.

Michael Menegakis wrote:

There are two SDL threads. One is an events thread, and another does
rendering. The rendering thread uses variables from the events thread.
There are mutex locks but they are irrelevant since I noticed the
behavior is same even if I remove them completely (for testing).

If I do a in the rendering thread alone, for 10 milliseconds, the FPS
is normally 100.

If I do no sleep at all in the rendering thread and a SDL_Delay() in
the events thread, the rendering thread does not slow down at all.

But, if I do a sleep of 10 milliseconds in the rendering thread and 10
in the events thread, the FPS is not 100, but lower, about 84! (notice
it’s the same even if mutex locks are removed completely)

(If none of them has sleeps it normally goes high.)

What could produce this behavior?

The behavior is same both with SDL_Delay() and a direct windows’ Sleep().


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

It’s not entirely unexpected behavior… When you sleep, you’re telling
the CPU scheduler that you are done with your time for now. Windows is
not a real-time OS, so when you tell it to sleep for 10 ms you are not
guarenteed that it will be 10 when the next time execution will take
place of your thread, only that you have nothing of interest to execute
FOR 10 ms. You still need to wait until the CPU scheduler gets to your
process for the next execution to take place. Very often there can be
100 or so system and user processes/threads running so internally this
could take a while…

But, what do I know. I’m just the Novice. :slight_smile:

In fact, it would behave pretty much like this on an RTOS as well. :slight_smile:

The fundamental problem is that SDL_Delay() is the wrong tool if you want a
fixed period. It will wait for at least the time specified. Any OS
scheduling latency, your code execution time and any system calls that may
block will add to the actual period. If your code is preempted by other tasks,
or interrupted by kernel drivers, that will add to the period as well.

So, what you need to do is check SDL_GetTicks() and adjust your delays in some
way that is appropriate for your application. Frame rate throttling is
probably the most common application of this method in games. (Nice when you
have no retrace sync, and want to avoid running at 1000+ fps at a constant
100% CPU load.)

Alternatively, you can use SDL timers. See SDL_AddTimer(), SDL_RemoveTimer()
etc.On Wednesday 26 January 2011, at 12.41.20, The Novice Coder wrote:

Michael Menegakis wrote:

There are two SDL threads. One is an events thread, and another does
rendering. The rendering thread uses variables from the events thread.
There are mutex locks but they are irrelevant since I noticed the
behavior is same even if I remove them completely (for testing).

If I do a in the rendering thread alone, for 10 milliseconds, the FPS
is normally 100.

If I do no sleep at all in the rendering thread and a SDL_Delay() in
the events thread, the rendering thread does not slow down at all.

But, if I do a sleep of 10 milliseconds in the rendering thread and 10
in the events thread, the FPS is not 100, but lower, about 84! (notice
it’s the same even if mutex locks are removed completely)

(If none of them has sleeps it normally goes high.)

What could produce this behavior?

The behavior is same both with SDL_Delay() and a direct windows’
Sleep(). _______________________________________________
SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

It’s not entirely unexpected behavior… When you sleep, you’re telling
the CPU scheduler that you are done with your time for now. Windows is
not a real-time OS, so when you tell it to sleep for 10 ms you are not
guarenteed that it will be 10 when the next time execution will take
place of your thread, only that you have nothing of interest to execute
FOR 10 ms. You still need to wait until the CPU scheduler gets to your
process for the next execution to take place. Very often there can be
100 or so system and user processes/threads running so internally this
could take a while…

But, what do I know. I’m just the Novice. :slight_smile:


//David Olofson - Consultant, Developer, Artist, Open Source Advocate

.— Games, examples, libraries, scripting, sound, music, graphics —.
| http://consulting.olofson.net http://olofsonarcade.com |
’---------------------------------------------------------------------’

OK, but to understand it practically here, what exactly happened with
the 2 sleeps? Did the 1 sleep made the OS be “lazy” about the 2nd
sleep? Because 1 sleep alone (in both threads) does wait 10ms exactly.On Wed, Jan 26, 2011 at 3:00 PM, David Olofson wrote:

It will wait for at least the time specified. Any OS
scheduling latency, your code execution time and any system calls that may
block will add to the actual period. If your code is preempted by other tasks,
or interrupted by kernel drivers, that will add to the period as well.

Yeah, something like that. The OS puts the thread to sleep, using some kind of
timer to wake it up after the specified time - but waking up a thread doesn’t
actually mean that it starts running; just that it’s moved to the “runnable
queue” or similar construct. If other threads have the CPU, they may well get
another few milliseconds to finish what they’re doing, before the OS decides
to preempt.

General purpose operating systems use various forms of dynamic priorities to
govern this, which is why you often get apparently random results. Depending
on what OS you’re on, threads that burn a lot of CPU time, do a lot of system
calls, and various other things, are “punished” by having their priorities
lowered, allowing other threads to get access to the CPU. Other threads may be
"rewarded" for just waking up every now and then, working for a few
microseconds and then go to sleep again. That’s why you can (usually) have an
audio thread processing a few hundred buffers per seconds while other threads
constantly hog the CPU; the audio thread is considered nicer, and will get
higher dynamic priority, thus preemting the CPU hogs with relatively low
latencies. It gets more complicated in scenarios where the threads aren’t as
black and white as this, and that might be what you’re seeing here.On Wednesday 26 January 2011, at 15.39.57, Michael Menegakis wrote:

On Wed, Jan 26, 2011 at 3:00 PM, David Olofson <@David_Olofson> wrote:

It will wait for at least the time specified. Any OS
scheduling latency, your code execution time and any system calls that
may block will add to the actual period. If your code is preempted by
other tasks, or interrupted by kernel drivers, that will add to the
period as well.

OK, but to understand it practically here, what exactly happened with
the 2 sleeps? Did the 1 sleep made the OS be “lazy” about the 2nd
sleep? Because 1 sleep alone (in both threads) does wait 10ms exactly.


//David Olofson - Consultant, Developer, Artist, Open Source Advocate

.— Games, examples, libraries, scripting, sound, music, graphics —.
| http://consulting.olofson.net http://olofsonarcade.com |
’---------------------------------------------------------------------’

Hi,

Another option is to do a busy loop until the correct time is up. This is
often very accurate… but of course you use 100% of a Core/thread to do
this. So it’s a trade off.

cu.

Sleeping isn’t a good way of working with threads. You should only
sleep if you have no legitimate work to do. If you’re hitting your FPS
deadline and you’re happy if the OS won’t run you for a while, you
might sleep in a graphics oriented thread. An input thread can
sometimes be written in such a way that it blocks waiting for pending
input. The SDL_PumpEvents() call can send a signal indicating to the
event thread that there might be work to do.

Of course, if care is not taken (particularly with these mutex locks
you were talking about) then the threads will end up in perfect sync
with each other, which will kill any benefit from threading (as the
processes cannot work in parallel) and the additional overhead of
context switching will likely cost you a small amount of performance.

IMHO, if you’re graphics thread can hit 100FPS it doesn’t need to be
done asynchronously. I seriously doubt your input thread is heavy duty
enough to warrant being a separate thread either. I think your program
would be simpler and likely faster if you wrote it as a normal single
threaded process.

…and, by doing that on a regular basis, you’re also asking the OS to allow
all sorts of background processes and stuff to preempt your thread whenever
they need some CPU time. So, instead of getting timing jitter, you get the
occasional extended stall.

So, while it can be a hack/solution in some special cases, it’s not really
something you should rely on, unless you can expect to be the only application
running, and/or there are enough CPUs/cores that you can have at least one to
abuse as much as you like.On Wednesday 26 January 2011, at 16.19.10, Ren? Dudfield wrote:

Hi,

Another option is to do a busy loop until the correct time is up. This is
often very accurate… but of course you use 100% of a Core/thread to do
this. So it’s a trade off.


//David Olofson - Consultant, Developer, Artist, Open Source Advocate

.— Games, examples, libraries, scripting, sound, music, graphics —.
| http://consulting.olofson.net http://olofsonarcade.com |
’---------------------------------------------------------------------’

Hi,

yeah, on some OS/cpu combinations threads get starved if they are too
busy. This is why you should try and add an SDL_Delay in your main
loop too.

Below is an “accurate_delay()” function that is used in
pygame.time.Clock.tick_busy_loop(). Why the OS does not stall the
thread is that it uses a combination of a real OS sleep, and a busy
loop at the end to get the accurate sleeping. It uses knowledge of
how bad the clock sleep accuracy on each OS is at sleeping to figure
out how long to sleep for.

So for the right amount of delay time this get’s the benefit of a pure
busy loop on an OS, and does not use 100% cpu. It seems to work ok in
many places… except on some linux 2.4 kernels it used 100% cpu
unfortunately.

#define WORST_CLOCK_ACCURACY 12

static int
accurate_delay (int ticks)
{
int funcstart, delay;
if (ticks <= 0)
return 0;

if (!SDL_WasInit (SDL_INIT_TIMER))
{
    if (SDL_InitSubSystem (SDL_INIT_TIMER))
    {
        RAISE (PyExc_SDLError, SDL_GetError ());
        return -1;
    }
}

funcstart = SDL_GetTicks ();
if (ticks >= WORST_CLOCK_ACCURACY)
{
    delay = (ticks - 2) - (ticks % WORST_CLOCK_ACCURACY);
    if (delay >= WORST_CLOCK_ACCURACY)
    {
        Py_BEGIN_ALLOW_THREADS;
        SDL_Delay (delay);
        Py_END_ALLOW_THREADS;
    }
}
do
{
    delay = ticks - (SDL_GetTicks () - funcstart);	
}
while (delay > 0);

return SDL_GetTicks () - funcstart;	

}On Wed, Jan 26, 2011 at 3:57 PM, David Olofson wrote:

On Wednesday 26 January 2011, at 16.19.10, Ren? Dudfield <@Rene_Dudfield> wrote:

Hi,

Another option is to do a busy loop until the correct time is up. ?This is
often very accurate… but of course you use 100% of a Core/thread to do
this. ?So it’s a trade off.

…and, by doing that on a regular basis, you’re also asking the OS to allow
all sorts of background processes and stuff to preempt your thread whenever
they need some CPU time. So, instead of getting timing jitter, you get the
occasional extended stall.

So, while it can be a hack/solution in some special cases, it’s not really
something you should rely on, unless you can expect to be the only application
running, and/or there are enough CPUs/cores that you can have at least one to
abuse as much as you like.


//David Olofson - Consultant, Developer, Artist, Open Source Advocate

.— Games, examples, libraries, scripting, sound, music, graphics —.
| ? http://consulting.olofson.net ? ? ? ? ?http://olofsonarcade.com ? |
’---------------------------------------------------------------------’


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

Hello !

A question about SDL_Delay :

When i use SDL_Delay (12) in my code on a system that has for example a schedule size of 10ms.
What is the biggest delay that could happen on an idle system ? SDL_Delay has to wait at least for 12 ms,
so the worst thing that could happen, would be that it waits two complete time slices, so here 20ms.

Is that correct ?

CU

Actually, it could be any amount of time >= 12 ms., depending upon the
scheduler.On Wed, Jan 26, 2011 at 11:48, Torsten Giebl wrote:

Hello !

A question about SDL_Delay :

When i use SDL_Delay (12) in my code on a system that has for example a
schedule size of 10ms.
What is the biggest delay that could happen on an idle system ? SDL_Delay
has to wait at least for 12 ms,
so the worst thing that could happen, would be that it waits two complete
time slices, so here 20ms.

Is that correct ?

CU


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org


Do what you can, where you are, with what you have. - T. Roosevelt

Actually, it could be any amount of time >= 12 ms., depending upon the
scheduler.

Yes; there are all sorts of different ways of implementing that - and there’s
another variable: the point in time the delay syscall is made. If it happens
to be 2 ms before a kernel 100 Hz “jiffy” interrupt, you may well get your 12
ms - but for all practical matters, count on anything between 12 and 20 ms,
with occasional peaks way above that.On Wednesday 26 January 2011, at 19.07.35, Greg Jandl <greg.jandl at gmail.com> wrote:

On Wed, Jan 26, 2011 at 11:48, Torsten Giebl wrote:

Hello !

A question about SDL_Delay :

When i use SDL_Delay (12) in my code on a system that has for example a
schedule size of 10ms.
What is the biggest delay that could happen on an idle system ? SDL_Delay
has to wait at least for 12 ms,
so the worst thing that could happen, would be that it waits two complete
time slices, so here 20ms.

Is that correct ?

CU


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org


//David Olofson - Consultant, Developer, Artist, Open Source Advocate

.— Games, examples, libraries, scripting, sound, music, graphics —.
| http://consulting.olofson.net http://olofsonarcade.com |
’---------------------------------------------------------------------’