Background tab timers

2,281 views
Skip to first unread message

Oliver Mattos

unread,
Apr 29, 2011, 8:48:25 AM4/29/11
to Chromium-dev
On the Chromium blog, Google said:


>In the forthcoming Chrome 11 release, we plan to reduce CPU
consumption even for pages that are using setTimeout and setInterval.
For background tabs, we intend to run each independent timer no more
than once per second. This change has already been implemented in the
Chrome dev channel and canary builds.


Unfortunately, this has broken my application (it uses timers do test
network latency). Can anyone point me to a spec or the commit where
this change was made so I can see the exact limits and modify my code
to work with it? Is there any way to detect if my page is in a
foreground or background tab?

Dominic Hamon

unread,
Apr 29, 2011, 10:15:15 AM4/29/11
to oma...@gmail.com, Chromium-dev
There's an interesting discussion here (http://lists.whatwg.org/pipermail/whatwg-whatwg.org/2010-December/029382.html) regarding a visibility API that would enable your application to know what state it is in. However this is not currently available, I'm afraid.

Also see this discussion which has some other techniques for handling this: http://stackoverflow.com/questions/831686/how-can-i-detect-whether-a-browser-window-is-focused-or-not

- dominic



--
Chromium Developers mailing list: chromi...@chromium.org
View archives, change email options, or unsubscribe:
   http://groups.google.com/a/chromium.org/group/chromium-dev

PhistucK

unread,
Apr 29, 2011, 10:19:29 AM4/29/11
to oma...@gmail.com, Chromium-dev
The limits were stated (no more than once per second for every independent timer).
I think you might be able to track being background or foreground with the "focus" and "blur" event.

Note that if your page is created as a background tab, I guess "focus" should never be fired until it becomes a foreground tab. But I never actually tested this and I imagine it could be buggy, but maybe Chrome gets this right.
On the other hand, if it does fire an initial "focus" when it is a foreground tab from the start, then when will it be fired, after "load"?
I have not read the specifications regarding this.

PhistucK



Ojan Vafai

unread,
Apr 29, 2011, 12:12:56 PM4/29/11
to oma...@gmail.com, Chromium-dev
On Fri, Apr 29, 2011 at 5:48 AM, Oliver Mattos <oma...@gmail.com> wrote:
Unfortunately, this has broken my application (it uses timers do test
network latency).  Can anyone point me to a spec or the commit where
this change was made so I can see the exact limits and modify my code
to work with it?  Is there any way to detect if my page is in a
foreground or background tab?

As it is, timers won't give you terribly accurate times since they are already somewhat throttled. What sort of network latency are you measuring? Can you give an example?

Maybe it's possible to do without setTimeout/setInterval.

Ojan 

Oliver Mattos

unread,
Apr 29, 2011, 12:38:28 PM4/29/11
to Ojan Vafai, Chromium-dev
> Can you give an example?
> Maybe it's possible to do without setTimeout/setInterval.

I'm trying to write a web app so the server can very rapidly determine
when a client goes offline. To do this, I hold a Websocket (falling
back to flash XMLSocket) connection open and send a byte every 250ms.
When the server doesn't get a byte after say 500ms, it assumes the
client is dead, and informs all it's other users that a client has
gone down.

For everyone else solving similar problems, here is a workaround:

Old code:

function process() {
// Do stuff...

setTimeout(process, 250);
}


New code:

function process() {
if (Now() - lastRunTime >= 250) {
lastRunTime = Now();
// Do stuff...

for (i=0; i<10; i++)
setTimeout(process, i*250);
}
}

The aim is to start lots of timers with various intervals, and if a
timer fires early ignore it. The minimum timer interval is 1 second,
but a timer with interval 1.5 seconds started 1.25 seconds ago is
still useful! The loop is required since we don't know the minimum
timer interval. Note in this design, the timer in fact fires much
more frequently than required, but for most firings the "IF" statement
means nothing is done. A more advanced design could start all the
timers and keep track of them all and cancel unnecessary ones.

Peter Kasting

unread,
Apr 29, 2011, 12:42:52 PM4/29/11
to oma...@gmail.com, Ojan Vafai, Chromium-dev
On Fri, Apr 29, 2011 at 9:38 AM, Oliver Mattos <oma...@gmail.com> wrote:
New code:

function process() {
 if (Now() - lastRunTime >= 250) {
   lastRunTime = Now();
   // Do stuff...

   for (i=0; i<10; i++)
     setTimeout(process, i*250);
 }
}

The aim is to start lots of timers with various intervals, and if a
timer fires early ignore it.  The minimum timer interval is 1 second,
but a timer with interval 1.5 seconds started 1.25 seconds ago is
still useful!

This is a clever workaround, but I can't help feeling like it defeats the purpose of our clamping in background tabs, and that from the Chrome side we'd actually want to disable this behavior (e.g. by clamping when timers fire to be at least 1 sec apart, as opposed to clamping minimum timer values to 1 sec).

Of course this doesn't help solve your problem.

PK

Ojan Vafai

unread,
Apr 29, 2011, 1:28:14 PM4/29/11
to Peter Kasting, oma...@gmail.com, Chromium-dev
This workaround seems fine to me. I don't think we'll see workaounds like this used often. I expect the vast majority of pages won't care that timers in background tabs are clamped and this will make the common case cpu usage in the range we want. If we see this is becoming a common pattern on the web, we can reconsider.

Ojan

Kenneth Russell

unread,
Apr 29, 2011, 2:31:05 PM4/29/11
to oma...@gmail.com, Chromium-dev

I'm afraid there isn't a spec for this change. As I recall, the once
per second number was chosen largely because it matched the behavior
of Mozilla's mozRequestAnimationFrame API for background tabs at the
time.

The final commit implementing this change was
http://codereview.chromium.org/6577021 . There were several previous
commits to WebKit and Chromium which put the infrastructure in place,
and at least one follow-on bug fix.

-Ken

Reply all
Reply to author
Forward
0 new messages