Timer frequency fun

So I was on IRC and got this interesting link

In a nutshell it warns the developers that setting windows system timer to
a low resolution and then leave it like that even when the application
doesn’t need it harms performance and battery life. Apparently, osx and
linux are not affected by this problem.

So I took a glance at the windows timers in SDL just for fun and noticed a
few things:

  • it’s possible to use GetTickCount by setting USE_GETTICKCOUNT, but as its
    resolution is too low (10-16ms) it is disabled
  • by default, the high resolution timer is in use
  • only when the high resolution timer is not available (when? it’s not
    clear to me) then the the timeBeginPeriod() is set.

However this affects the Sleep behaviour (in SDL_Delay) as
http://msdn.microsoft.com/en-us/library/windows/desktop/ms686298(v=vs.85).aspxreport:
when timeBeginPeriod is not set Sleep may last 15.6 ms more or less.
So I prepped this patch that uses WaitForObject() on the current thread,
which according to the docs
http://msdn.microsoft.com/en-us/library/ms687036(v=vs.85).aspx should
not suffer from precision skew.

I’m not sure how this affects existing behaviour of games and tests out
there so testing and review would be welcome.

Vittorio
-------------- next part --------------
A non-text attachment was scrubbed…
Name: sdldelay.patch
Type: application/octet-stream
Size: 656 bytes
Desc: not available
URL: http://lists.libsdl.org/pipermail/sdl-libsdl.org/attachments/20130710/06ac103c/attachment.obj

From Bruce Dawson:

WaitForSingleObjectEx is affected by the timer precision so switching from
Sleep(n) to WaitForSingleObjectEx(n) will not help things. At the default
timer precision of 15.6 ms the scheduler only runs every 15.6 ms, so no
timeouts can be serviced at higher than that resolution.****


When a process readies another process (SetEvent, ReleaseSemaphore, etc.)
then the scheduler is invoked for that, but timeouts are not processed
until the timer interrupt.****


As I recommend in my blog post, be sure to put in a paired call to
timeEndPeriod() when you don?t need the higher resolution.—

What I’ll probably do is put the timeBeginPeriod() back in, with a hint so
applications that don’t need that resolution can specify a lower resolution
to save power.

Thanks!

On Wed, Jul 10, 2013 at 4:00 AM, Vittorio Giovara < vittorio.giovara at gmail.com> wrote:

So I was on IRC and got this interesting link

https://randomascii.wordpress.com/2013/07/08/windows-timer-resolution-megawatts-wasted/

In a nutshell it warns the developers that setting windows system timer to
a low resolution and then leave it like that even when the application
doesn’t need it harms performance and battery life. Apparently, osx and
linux are not affected by this problem.

So I took a glance at the windows timers in SDL just for fun and noticed a
few things:

  • it’s possible to use GetTickCount by setting USE_GETTICKCOUNT, but as
    its resolution is too low (10-16ms) it is disabled
  • by default, the high resolution timer is in use
  • only when the high resolution timer is not available (when? it’s not
    clear to me) then the the timeBeginPeriod() is set.

However this affects the Sleep behaviour (in SDL_Delay) as
http://msdn.microsoft.com/en-us/library/windows/desktop/ms686298(v=vs.85).aspxreport: when timeBeginPeriod is not set Sleep may last 15.6 ms more or less.
So I prepped this patch that uses WaitForObject() on the current thread,
which according to the docs
http://msdn.microsoft.com/en-us/library/ms687036(v=vs.85).aspx should
not suffer from precision skew.

I’m not sure how this affects existing behaviour of games and tests out
there so testing and review would be welcome.

Vittorio


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

Sleep is not very predictable anyway, it really wasn’t meant to be
used for small amounts of time. The only reason it specifies time in
milliseconds is probably to provide an easy way to specify non-integer
amounts of seconds (e.g. pass 500 to delay half a second).

One thing to take into account is that if I understand correctly the
QueryPerformance timers should not be affected by this, since they
work in a completely different way (they’re counter based rather than
interrupt driven). When you just want to query the elapsed time, this
should be probably the best option in this sense (and as a bonus you
get extra accuracy!). The big downside is that they can’t be used for
idle delays (e.g. what SDL_Delay would do), since you have to poll
constantly and thereby it ends up being a busy loop.

Correct me if I’m wrong, but only the standard timer (i.e. the one
used in window messages and GetTickCount) should be affected.

From Bruce Dawson:

WaitForSingleObjectEx is affected by the timer precision so switching from
Sleep(n) to WaitForSingleObjectEx(n) will not help things. At the default
timer precision of 15.6 ms the scheduler only runs every 15.6 ms, so no
timeouts can be serviced at higher than that resolution.

Ack, sorry for the wrong patch, re-reading documentation for
WaitForSingleObjectEx mentions that too.


What I’ll probably do is put the timeBeginPeriod() back in, with a hint so
applications that don’t need that resolution can specify a lower resolution
to save power.

That’s great, but do you think there could be some hooks to reset the
timer too? For example when the game is paused there is no need to leave
the high precision on.

Thanks!

Thank you for doublecheking ^^
VittorioOn Wed, Jul 10, 2013 at 7:56 PM, Sam Lantinga wrote:

Also would it make sense to have something like

timeBeginPeriod(1);
Sleep(ms);
timeEndPeriod(1);

In this way the high precision timer would be on only for the duration of
the Sleep.
I tried to see if this made sense but I found no useful info…

VittorioOn Wed, Jul 10, 2013 at 7:56 PM, Sam Lantinga wrote:

From Bruce Dawson:

WaitForSingleObjectEx is affected by the timer precision so switching from
Sleep(n) to WaitForSingleObjectEx(n) will not help things. At the default
timer precision of 15.6 ms the scheduler only runs every 15.6 ms, so no
timeouts can be serviced at higher than that resolution.****


When a process readies another process (SetEvent, ReleaseSemaphore, etc.)
then the scheduler is invoked for that, but timeouts are not processed
until the timer interrupt.****


As I recommend in my blog post, be sure to put in a paired call to
timeEndPeriod() when you don?t need the higher resolution.


What I’ll probably do is put the timeBeginPeriod() back in, with a hint so
applications that don’t need that resolution can specify a lower resolution
to save power.

Thanks!

On Wed, Jul 10, 2013 at 4:00 AM, Vittorio Giovara < @Vittorio_Giovara> wrote:

So I was on IRC and got this interesting link

https://randomascii.wordpress.com/2013/07/08/windows-timer-resolution-megawatts-wasted/

In a nutshell it warns the developers that setting windows system timer
to a low resolution and then leave it like that even when the application
doesn’t need it harms performance and battery life. Apparently, osx and
linux are not affected by this problem.

So I took a glance at the windows timers in SDL just for fun and noticed
a few things:

  • it’s possible to use GetTickCount by setting USE_GETTICKCOUNT, but as
    its resolution is too low (10-16ms) it is disabled
  • by default, the high resolution timer is in use
  • only when the high resolution timer is not available (when? it’s not
    clear to me) then the the timeBeginPeriod() is set.

However this affects the Sleep behaviour (in SDL_Delay) as
http://msdn.microsoft.com/en-us/library/windows/desktop/ms686298(v=vs.85).aspxreport: when timeBeginPeriod is not set Sleep may last 15.6 ms more or less.
So I prepped this patch that uses WaitForObject() on the current thread,
which according to the docs
http://msdn.microsoft.com/en-us/library/ms687036(v=vs.85).aspxshould not suffer from precision skew.

I’m not sure how this affects existing behaviour of games and tests out
there so testing and review would be welcome.

Vittorio


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


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