Earlier I blogged about terrible UI responsiveness resulting from a poorly placed setTimeout. I’ve long suspected that SetTimeouts are to blame for everything. Now with help of bz and sfink I have proof.
Turns out webpages like to keep users entertained and spin setTimeout loops to poll the servers to synchronize news tickers, social networking shoe-ins, collaborative editing, etc. Most pages do this regardless of whether they are a background or a foreground tab. Firefox tries to mitigate this by not allowing background tabs to schedule setTimeouts < 2seconds. Turns out this is a pretty weak defense.
In my personal browsing: etherpad, twitter, zimbra burn through cpu cycles. See this bug comment for an example of setTimeout terrorism with less than 10 tabs. In Firefox these setTimeouts cause significant UI lag, but they will also eat your battery life, overheat your laptop, etc. I filed bug 715376 to add functionality to cope with this. The plan is to prioritize foreground tab activity and do exponential setTimeout decay on abusive background tabs. We basically have to write something similar to an OS scheduler. Ideally we’d also follow that up with unloading idle tabs, ie bug 675539.
If you are curious about what tabs are abusing your browser my diagnostic builds will be available on try in a few hours. Install a modified version of about:telemetry to see the report.
What should well-behaved web apps do?
You can detect when your tab becomes inactive via window.onblur, then throttle or disable your page activity. I know using focus is suboptional for this. There is also a vendor-prefixed visibility api (thanks!).
Now you know why your browser keeps your CPU wide awake :)
Update:
Wrote this post in a rush on the way out, thanks for the visibility links. I am aware that some webpages need to do work in the background. However that work should be as minimal as possible, this is often not the case.
Project Idea:
Would be nice if someone wrote an extension that goes through tabs and nukes any outstanding setTimeouts/XHRs/etc.