script: Use a timer when rAF is used for non-animation purposes

After this patch, when the page calls `requestAnimationFrame()` too many
times in the row without actually mutating the DOM, further calls to
`rAF` will actually perform the moral equivalent of `setTimeout(16)`.
This saves a lot of CPU time compared to actually waiting for the
vertical blanking interval, because waiting for that requires us to draw
the page.

Reduces CPU usage drastically on nytimes.com, which has a perpetual
`requestAnimationFrame()` loop that checks whether ads are in view.
This commit is contained in:
Patrick Walton 2016-12-02 11:54:07 -08:00 committed by Anthony Ramine
parent 198662f8cb
commit 4e7ac19380
2 changed files with 85 additions and 14 deletions

View file

@ -7,6 +7,7 @@ use dom::bindings::cell::DOMRefCell;
use dom::bindings::codegen::Bindings::FunctionBinding::Function;
use dom::bindings::reflector::DomObject;
use dom::bindings::str::DOMString;
use dom::document::FakeRequestAnimationFrameCallback;
use dom::eventsource::EventSourceTimeoutCallback;
use dom::globalscope::GlobalScope;
use dom::testbinding::TestBindingCallback;
@ -69,6 +70,7 @@ pub enum OneshotTimerCallback {
EventSourceTimeout(EventSourceTimeoutCallback),
JsTimer(JsTimerTask),
TestBindingCallback(TestBindingCallback),
FakeRequestAnimationFrame(FakeRequestAnimationFrameCallback),
}
impl OneshotTimerCallback {
@ -78,6 +80,7 @@ impl OneshotTimerCallback {
OneshotTimerCallback::EventSourceTimeout(callback) => callback.invoke(),
OneshotTimerCallback::JsTimer(task) => task.invoke(this, js_timers),
OneshotTimerCallback::TestBindingCallback(callback) => callback.invoke(),
OneshotTimerCallback::FakeRequestAnimationFrame(callback) => callback.invoke(),
}
}
}