XPCOM timers need to support resolutions smaller than 10ms on Windows

RESOLVED WORKSFORME

Status

()

defect
RESOLVED WORKSFORME
8 years ago
6 years ago

People

(Reporter: bzbarsky, Assigned: johns)

Tracking

(Blocks 1 bug)

Trunk
x86
Windows 7
Points:
---
Dependency tree / graph

Firefox Tracking Flags

(Not tracked)

Details

(Whiteboard: [games:p2])

Attachments

(1 attachment)

XPCOM timers don't do well for resolutions smaller than 10-15ms.  Some relevant discussion is in bug 610077 (which needs this bug fixed to happen).

Assigning per roc's suggestion.

Chrome apparently has some way of doing this where they have a thread polling some high-resolution timer or something...
So the way to set user mode timing granulity on Windows is to call timeBeginPeriod() with the desired granulity in milliseconds. This value determines the length of the time slices that the system scheduler assigns to each thread on the system. Although most hardware probably supports a minimum period of 1ms, timeGetDevCaps() should be used to make sure. As this setting affects all threads on the system, any call to timeBeginPeriod() needs to be undone by a call to timeEndPeriod() (with the same value passed in) when the application no longer requires the increased resolution.

The relevant documentation can be found here:
timeBeginPeriod: http://msdn.microsoft.com/en-us/library/dd757624.aspx
timeGetDevCaps: http://msdn.microsoft.com/en-us/library/dd757627.aspx
timeEndPeriod: http://msdn.microsoft.com/en-us/library/dd757626.aspx

As the first article notes: "Setting a higher resolution can improve the accuracy of time-out intervals in wait functions. However, it can also reduce overall system performance, because the thread scheduler switches tasks more often. High resolutions can also prevent the CPU power management system from entering power-saving modes."

That last part seems like the biggest worry - perhaps the browser could use the increased resolution only when needed (that is, when a foreground tab is actively making use of it), or reset the resolution if the device switches to battery power?

Of course, once you have the 1ms granulity you can just create a worker thread that updates a timestamp every ~1ms with a simple Sleep(1) call.

Finally, if an event needs to trigger with an exact interval, the most precise timestamp on Windows is the high resolution performance counter. You can query the value of this counter with QueryPerformanceCounter(), and find out its frequency with QueryPerformanceFrequency(). Thus (if absolutely necessary) you could wait for the approximate amount of time needed using Sleep(), then tight loop until the desired timestamp (Sleep(0) and SwitchToThread() are less evil than tight looping, but complicate things even more).
QueryPerformanceCounter: http://msdn.microsoft.com/en-us/library/ms644904.aspx
QueryPerformanceFrequency: http://msdn.microsoft.com/en-us/library/ms644905.aspx
I think Chrome and IE9 only use the high-res timer stuff if you're not on battery.

Updated

8 years ago
OS: Mac OS X → Windows 7
> High resolutions can also prevent the CPU power management system

Yes, exactly.

And what happens if we crash before calling timeEndPeriod?

roc, what floor do you see for timeouts in chrome and IE9 on battery?
IE9: 16ms
Chrome: 4ms

I guess I was wrong in comment #2!
Interesting.  16ms seems really high...
Maybe they chose it so you can still get 60fps.
(In reply to comment #3)
> And what happens if we crash before calling timeEndPeriod?
I believe the system is then left in the state that timeBeginPeriod put it in, though I'd have to do a test to be sure. In the nested setTimeout tests I've seen Firefox using 1ms granulity even though no other programs were running at the time, so something must have left the setting in an altered state.

This seems like an oversight in the OS to me - for instance, if a program disables the DWM, it will be automatically re-enabled when the program exits (or crashes). But I guess there's not much that can be done about it now.
I have a prototype implementation that uses QueryPerformanceCounter.

QueryPerformanceCounter is actually faster on my machine than the existing timing code but what I've read on the Internet leads me to believe that the relative performance of the various timing functions varies significantly depending on the operating system and the hardware.

In short, this is going to need a lot of testing.
Posted patch WIPSplinter Review
This patch is the prototype implementation.  It currently fails the CSS Animations mochitest, and moves Talos numbers a lot (some good, a few bad).
Note that this patch in and of itself isn't enough to fix the timers, because the timer thread waits which does silly things on Windows.
There's a lot of work in bug 676349 that seems related.
Some related stuff in bug 731974, specifically around requestAnimationFrame though.
Whiteboard: [games:p?] → [games:p2]
I think this was resolved by bug 590422 and the work in making xpcom timers use the high precision timers on Windows.
Status: NEW → RESOLVED
Last Resolved: 6 years ago
Resolution: --- → WORKSFORME
You need to log in before you can comment on or make changes to this bug.