Hi,
I’m wondering why the SDL library doesn’t use POSIX conformant nanosleep()
function in its SDL_Delay() routine. Currently select() used for this purpose,
which IMHO looks like hammering nails using computer keyboard…
I have patches at hand, so it someone will want to commit them please let me
know.
-Maxim
Hi!On Mon, 3 Apr 2000, Maxim Sobolev wrote:
I’m wondering why the SDL library doesn’t use POSIX conformant nanosleep()
function in its SDL_Delay() routine. Currently select() used for this purpose,
I also wondered a while ago and tried to replace the select() with
nanosleep() and usleep(). The result: under Linux 2.2.x, the select()
timeout seems to have a far higher accuracy and resolution than *sleep(),
e.g. nanosleep(3ms) on my machine usually waits for about 20-30ms,
sometimes 14-16ms, while select() is relatively constant at ~3ms.
Bye,
Christian
–
/ Coding on PowerPC and proud of it
/ http://www.uni-mainz.de/~bauec002/
Christian Bauer wrote:
Hi!
I’m wondering why the SDL library doesn’t use POSIX conformant nanosleep()
function in its SDL_Delay() routine. Currently select() used for this purpose,
I also wondered a while ago and tried to replace the select() with
nanosleep() and usleep(). The result: under Linux 2.2.x, the select()
timeout seems to have a far higher accuracy and resolution than *sleep(),
e.g. nanosleep(3ms) on my machine usually waits for about 20-30ms,
sometimes 14-16ms, while select() is relatively constant at ~3ms.
BUGS
The current implementation of nanosleep is based on the
normal kernel timer mechanism, which has a resolution of
1/HZ s (i.e, 10 ms on Linux/i386 and 1 ms on Linux/Alpha).
Therefore, nanosleep pauses always for at least the speci?
fied time, however it can take up to 10 ms longer than
specified until the process becomes runnable again. For
the same reason, the value returned in case of a delivered
signal in *rem is usually rounded to the next larger mul?
tiple of 1/HZ s.
As some applications require much more precise pauses
(e.g., in order to control some time-critical hardware),
nanosleep is also capable of short high-precision pauses.
If the process is scheduled under a real-time policy like
SCHED_FIFO or SCHED_RR, then pauses of up to 2 ms will be
performed as busy waits with microsecond precision.> On Mon, 3 Apr 2000, Maxim Sobolev wrote:
–
Daniel Vogel My opinions may have changed,
666 @ http://grafzahl.de but not the fact that I am right
Christian Bauer wrote:
Hi!
I’m wondering why the SDL library doesn’t use POSIX conformant nanosleep()
function in its SDL_Delay() routine. Currently select() used for this purpose,
I also wondered a while ago and tried to replace the select() with
nanosleep() and usleep(). The result: under Linux 2.2.x, the select()
timeout seems to have a far higher accuracy and resolution than *sleep(),
e.g. nanosleep(3ms) on my machine usually waits for about 20-30ms,
sometimes 14-16ms, while select() is relatively constant at ~3ms.
I did a 1000 x 1 ms sleep with ‘sleep’ == usleep it took 20 secs and
with select only 10. Then I did try a 100x 10 ms sleep and it took 2
seconds with select. Looks as if select takes about 10ms more than I
want
Well, at least it performs better than usleep.> On Mon, 3 Apr 2000, Maxim Sobolev wrote:
–
Daniel Vogel My opinions may have changed,
666 @ http://grafzahl.de but not the fact that I am right
Daniel Vogel wrote:
I did a 1000 x 1 ms sleep with ‘sleep’ == usleep it took 20 secs and
with select only 10. Then I did try a 100x 10 ms sleep and it took 2
seconds with select. Looks as if select takes about 10ms more than I
want
Well, at least it performs better than usleep.
Ups, timed the wrong one… usleep was the one that took 2 seconds and
select was taking about 1 sec. Well, the 1000x1ms still takes 10 secs
with select here but at least it works perfectly with a resolution of
more than 10ms whereof usleep even fails on such a high granularity.–
Daniel Vogel My opinions may have changed,
666 @ http://grafzahl.de but not the fact that I am right
Daniel Vogel wrote:
Christian Bauer wrote:
Hi!
I’m wondering why the SDL library doesn’t use POSIX conformant nanosleep()
function in its SDL_Delay() routine. Currently select() used for this purpose,
I also wondered a while ago and tried to replace the select() with
nanosleep() and usleep(). The result: under Linux 2.2.x, the select()
timeout seems to have a far higher accuracy and resolution than *sleep(),
e.g. nanosleep(3ms) on my machine usually waits for about 20-30ms,
sometimes 14-16ms, while select() is relatively constant at ~3ms.
I did a 1000 x 1 ms sleep with ‘sleep’ == usleep it took 20 secs and
with select only 10. Then I did try a 100x 10 ms sleep and it took 2
seconds with select. Looks as if select takes about 10ms more than I
want
Well, at least it performs better than usleep.
Hm,
FreeBSD seems much more consistent in this area. My small testcase gave me (in ms of
course):
Requiested: 1, Nanosleep: 20, Select: 20
Requiested: 2, Nanosleep: 20, Select: 20
Requiested: 4, Nanosleep: 20, Select: 20
Requiested: 8, Nanosleep: 20, Select: 20
Requiested: 16, Nanosleep: 30, Select: 30
Requiested: 32, Nanosleep: 50, Select: 50
Requiested: 64, Nanosleep: 80, Select: 80
Requiested: 128, Nanosleep: 140, Select: 140
Requiested: 256, Nanosleep: 270, Select: 270
Requiested: 512, Nanosleep: 529, Select: 530
Well, while it is not very accurate, at least it is the same across different
interfaces.
-Maxim> > On Mon, 3 Apr 2000, Maxim Sobolev wrote:
Ups, timed the wrong one… usleep was the one that took 2 seconds and
select was taking about 1 sec. Well, the 1000x1ms still takes 10 secs
with select here but at least it works perfectly with a resolution of
more than 10ms whereof usleep even fails on such a high granularity.
On Linux, select() and usleep() have a 10ms granularity, but usleep
often overshoots by up to 10ms since it has to sleep at least the
asked amount, not less. If you usleep() near the end of a tick, the delay
will be closer to what you asked for, but I presume your test program
did it just after the beginning of a tick.
(Except on Alpha, where a tick = 1/1024 s.)
I don’t think SDL_Delay should busy-wait (often you delay to let other
threads run), so nanosleep() is out. We could provide a SDL_BusyWait(),
but the implementation is so trivial there’s little point.
Mattias Engdeg?rd wrote:
On Linux, select() and usleep() have a 10ms granularity, but usleep
often overshoots by up to 10ms since it has to sleep at least the
asked amount, not less. If you usleep() near the end of a tick, the delay
will be closer to what you asked for, but I presume your test program
did it just after the beginning of a tick.
(Except on Alpha, where a tick = 1/1024 s.)
Thanks for the info. I knew that nanosleep had this granularity but
didn’t know about usleep. Why isn’t that in the man pages??? Well,
browsing the glibc source usleep calls nanosleep so that explains the
10ms granularity for usleep.
I don’t think SDL_Delay should busy-wait (often you delay to let other
threads run), so nanosleep() is out. We could provide a SDL_BusyWait(),
but the implementation is so trivial there’s little point.
Yes, most of the time you call delay to give other tasks like input/
event handling some time to gather/ process them. I don’t see why
anybody would want a busy wait with ms granularity except for driver
programming.–
Daniel Vogel My opinions may have changed,
666 @ http://grafzahl.de but not the fact that I am right
Maxim Sobolev wrote:
Hi,
I’m wondering why the SDL library doesn’t use POSIX conformant nanosleep()
function in its SDL_Delay() routine. Currently select() used for this purpose,
which IMHO looks like hammering nails using computer keyboard…
I have patches at hand, so it someone will want to commit them please let me
know.
nanosleep(2) is a POSIX.1b feature. Linux doesn’t completely support
POSIX.1b, and neither does any version of Windows I have used (know
nothing about W2K, though). If it doesn’t exist on all platforms, then
it’s trouble for portability.–
| Rafael R. Sevilla @Rafael_R_Sevilla |
| Instrumentation, Robotics, and Control Laboratory |
College of Engineering, University of the Philippines, Diliman |
Linux has an internel timer resolution of 10Hz. The most accurate you can set
a timer for in linux is 1/100th of a second. nanosecond is pointless since you
will never get nanosecond accuracy. Im not sure about other OS’s but I would
guess that you wouldn’t get nanosecond accuracy on them either. Also select is
the most portable timer. I think even windows supports it.On Mon, 03 Apr 2000, you wrote:
Maxim Sobolev wrote:
Hi,
I’m wondering why the SDL library doesn’t use POSIX conformant nanosleep()
function in its SDL_Delay() routine. Currently select() used for this purpose,
which IMHO looks like hammering nails using computer keyboard…
I have patches at hand, so it someone will want to commit them please let me
know.
nanosleep(2) is a POSIX.1b feature. Linux doesn’t completely support
POSIX.1b, and neither does any version of Windows I have used (know
nothing about W2K, though). If it doesn’t exist on all platforms, then
it’s trouble for portability.
–
| Rafael R. Sevilla dido at pacific.net.ph |
| Instrumentation, Robotics, and Control Laboratory |
College of Engineering, University of the Philippines, Diliman |
–
-Garrett, WPI student majoring in Computer Science
“The fastest way to succeed is to look as if you’re playing by somebody
else’s rules, while quietly playing by your own.” -Michael Konda
Nicholas Vining wrote:
Huh. What’s the resolution of the internal Pentium timers? It’s gotta be
better than SDL’s current resolution, and if that’s really important, we
could go that route and start doing things that way. I have improved
resolution timer code for both x86 Pentium machines and Mac PPCs, if anybody
wants.
That would result in a ‘busy wait’… The trick is you want the system
to suspend your task for the time you sleep so we can’t change code in
SDL to achieve this
One thing that could be done is that when the
argument to sleep is less than 10ms (on i386) it could do a busy wait,
but I don’t think this would be a good idea…–
Daniel Vogel My opinions may have changed,
666 @ http://grafzahl.de but not the fact that I am right
Daniel Vogel wrote:
Huh. What’s the resolution of the internal Pentium timers? It’s gotta be
better than SDL’s current resolution, and if that’s really important, we
could go that route and start doing things that way. I have improved
resolution timer code for both x86 Pentium machines and Mac PPCs, if
anybody wants.
That would result in a ‘busy wait’… The trick is you want the system
to suspend your task for the time you sleep so we can’t change code in
SDL to achieve this
One thing that could be done is that when the
argument to sleep is less than 10ms (on i386) it could do a busy wait,
but I don’t think this would be a good idea…
Hmm, BTW, while I agree that using the internal Pentium timer for a
timer would result in a busy-wait (bad), it would be very interesting to
have a portable SDL_GetTime() function (if there isn’t already one) that
uses a bit of assembler to grab the internal Pentium timer (or the
equivalent on other platforms), with a fallback on gettimeofday(). The
advantage would be in avoiding a system call. With the typical use of
“gettime()”-type functions, this would be a very useful saving I think.–
Pierre Phaneuf
Systems Exorcist
Huh. What’s the resolution of the internal Pentium timers? It’s gotta be
better than SDL’s current resolution, and if that’s really important, we
could go that route and start doing things that way. I have improved
resolution timer code for both x86 Pentium machines and Mac PPCs, if anybody
wants.
The gettimeofday() syscall in Linux (and doubtless other OSes) uses the cycle
counter where available (which is in most modern processors). But having
a high-resolution clock is not the same thing as a high-res timer that
can wakeup and reschedule processes at higher rates. Some effort has been
made, anyway; see http://www.ittc.ukans.edu/utime/ .
It could be useful for giving some cycles to other threads or cooperating
processes though. Has anyone found themselves in a need for this?
The
advantage would be in avoiding a system call. With the typical use of
“gettime()”-type functions, this would be a very useful saving I think.
I tend to do a lot of gettimeofday()s in my code, so I was worried about
their cost and profiled. It turned out to be quite insignificant.
Not to say that it always is, though — it can still be useful for
measuring performance of very short code snippets which are hard to
get accurate readings for otherwise.
Nicholas Vining wrote:
Huh. What’s the resolution of the internal Pentium timers? It’s gotta be
better than SDL’s current resolution, and if that’s really important, we
could go that route and start doing things that way. I have improved
resolution timer code for both x86 Pentium machines and Mac PPCs, if anybody
wants.
That would result in a ‘busy wait’… The trick is you want the system
to suspend your task for the time you sleep so we can’t change code in
SDL to achieve this
One thing that could be done is that when the
argument to sleep is less than 10ms (on i386) it could do a busy wait,
but I don’t think this would be a good idea…
–
Daniel Vogel My opinions may have changed,
666 @ http://grafzahl.de but not the fact that I am right
Something that I have seen done, with varying amounts of sucess is something
like: (Please excuse my pseudo-code)
starttime = gettimeofday()
if ( x < 10ms ) /* Give other processes a change */
sleep(0)
} else {
usleep((x/(10ms))*10000us)
}
endtime = gettimeofday()
while ( starttime + x > endtime ) { /* while time left */
sleep(0)
endtime = gettimeofday()
}
The problem is that sleep(0) isn’t as predictable/portable as we might
hope… If I remember correctly from FileNET, something like this works
reasonably well on WinNT, but I wouldn’t trust it on Linux.
Regards,
-Loren
Loren Osborn wrote:
The problem is that sleep(0) isn’t as predictable/portable as we might
hope… If I remember correctly from FileNET, something like this works
reasonably well on WinNT, but I wouldn’t trust it on Linux.
The sleep(0) works okay on Linux (we use it in Quadra). In Windows, it
is Sleep(0) you have to use (damn Win32, why the useless
difference???)…–
Pierre Phaneuf
Systems Exorcist
Loren Osborn wrote:
The problem is that sleep(0) isn’t as predictable/portable as we might
hope… If I remember correctly from FileNET, something like this works
reasonably well on WinNT, but I wouldn’t trust it on Linux.
The sleep(0) works okay on Linux (we use it in Quadra). In Windows, it
is Sleep(0) you have to use (damn Win32, why the useless
difference???)…
sleep() sleeps seconds
Sleep() sleeps milliseconds
-Sam Lantinga, Lead Programmer, Loki Entertainment Software
Loren Osborn wrote:
The problem is that sleep(0) isn’t as predictable/portable as we might
hope… If I remember correctly from FileNET, something like this works
reasonably well on WinNT, but I wouldn’t trust it on Linux.
The sleep(0) works okay on Linux (we use it in Quadra). In Windows, it
is Sleep(0) you have to use (damn Win32, why the useless
difference???)…
sleep() sleeps seconds
Sleep() sleeps milliseconds
-Sam Lantinga, Lead Programmer, Loki Entertainment Software
Just to clarify: Yes, 0 seconds == 0 milliseconds == 0 microseconds!
On WinNT Sleep(0) acts as a sort of “process yeild” letting other processes
use CPU time if they need it, but returning control to the calling process
at earliest convienience. What sleep(0) or usleep(0) do in Unix/Linux I’m
not so sure of… (May yeild… may act as NOP… haven’t tried it…)
Regards,
-Loren