Background TABs in browser load 20+ times slower
Recently we troubleshooted a performance issue, reported by one of the customers of Plumbr who was using our Real User Monitoring solution. While investigating browser behaviour loading a particular page, we stumbled upon a major difference in time it takes to load a web page in a background browser tab vs a tab in foreground.
To quantify this difference, we investigated 1.8 million user interactions in UI and compared the duration of such user interactions for two subsets:
- interactions that loaded fully while being in foreground;
- interactions that loaded partially or fully while being in background.
The difference was stunning. The load time for interactions in background tabs was 22 to 56 times longer than for the interactions in foreground:
In the chart above we plotted out the difference of (partially) background interactions to the fully foreground interactions. Different performance percentiles gave a slightly different view:
- median load time for background interactions was 24x worse,
- 90th percentile was 22 times slower,
- 99th percentile loaded 56 times slower
than for the foreground interactions.
The metric we were investigating was the difference between the interaction in UI (a click on a button for example) until the last resource fetched from the server as a result of the interaction is downloaded in the browser. So yes, TTLB is the metric here.
When we understood the extent of this difference, we started to look for the cause. Apparently, the browser vendors have been heavily optimizing for the resource usage in order to save the battery in handheld devices. We discovered at least two such optimizations having an impact for the background tabs:
Page load time difference in background: limited parallelism
Background tabs set a per-frame simultaneous loading limit lower than for the foreground tabs. For example, Google Chrome limits the number of resources fetched to six when the tab is in the focus and to three when in background per server/proxy. Other browser vendors use different limits – for example the IE 7 used to limit this to just two for foreground tabs. IE 10 increased this to eight parallel requests per server/proxy.
What it means is that only a limited number of requests from the browser are permitted to go to the network stack in parallel. Excessive requests are queued and executed when the previous request finishes. Thus, all requests will run eventually, but with a delay depending on the number of simultaneous loads permitted and the time it takes to complete the requests.
To illustrate this behavior, we built a small test case that loads 13 resources from the server. Loading each resource takes one second to complete (a server-side delay simulating a dynamic response). When we launched two interactions – one in the foreground and one in the background – we faced the following on the Chrome Developer Tools:
In the first image, the page was loaded in foreground. In the second image, the page was loaded in the background tab. It is immediately visible that the first instance loads six resources in parallel and is thus able to complete the loading in around three seconds, while the second example uses just three parallel requests and is thus completing the pageload in five seconds.
Page load time difference in background: CPU throttling
A second reason for the interactions being slower in background tabs is related to how the CPU access gets throttled for background tabs. Again, the intentions are good – if the background tabs are CPU-heavy it will put significant burden on the battery life.
Different browser vendors are implementing it differently. For example, Google Chrome limits timers in the background to run only once per second. In addition, Chrome will delay timers to limit average CPU load to 1% of the processor core when running in background.
A small experiment we carried out involved loading and parsing the Angular 1.7.8 JS library and measure the first contentful paint event on the otherwise empty page loaded. We used the version hosted in Cloudflare CDN for the experiment. What we ended up confirming is that the page which just loads the library (and does nothing with it afterwards) renders in 200ms in a foreground tab and in 2,200ms in a background one.
Take – away
The fact that background tabs load slower due to browser-specific optimizations is likely not a surprise to our tech-savvy readers. What might be surprising is how heavy such optimizations are – the results show a difference of 22-56x when measuring the user interaction duration in foreground vs background tabs.
Should you be worried about this behavior and start to optimize accordingly? Most likely not – user experience as such is not really impacted if the slowly loading TAB is not in the focus for the user. However, it is crucial to understand this massive difference and to be able to exclude such interactions from your performance optimizations as (likely) wasteful.
Finally – we only exposed two of such optimizations in this blog post. There are likely several others. If you know of any other limitations for background tabs, let us know in the comments.