William Chan's blag

Resource Prioritization in Chromium

Resource prioritization is a difficult problem for browsers, because they don’t fully understand the nature of the resources in the page, so they have to rely on heuristics. It seems like the main document is probably the most important resource, so it’d be good to prioritize that highly. Scripts block parsing, and stylesheets and block rendering. Both can lead to discovering other resources, so it’s probably a good idea to prioritize them reasonably highly too. Then you have other resources like media and async XHRs and images. For the exact algorithm Chromium uses, you can refer to the code. It’s noticeably suboptimal with regards to sync vs async resources, and there is probably more room for improvement. Indeed, we’re kicking around some ideas we hope to play around with in the near future.

Note that it’s already difficult for browsers to characterize resource priority appropriately, and the techniques that web developers have to employ to get good cross browser performance make the situation worse. For example, Steve and Guy have great recommendations on various techniques to load scripts or stylesheets without blocking. The problem, from a resource prioritization perspective, is these techniques defeat the attempts of the browser to understand the resources and prioritize them accordingly. The XHR based techniques will all get a lower priority. The JS based techniques for adding a script tag defeat browser attempts to speculatively parse when blocked. The script in iframe technique gives the script the priority of a subframe (high). Really, what web devs probably want to do is declare the script/stylesheet resource as async.

Now, how important is resource prioritization? Well, it depends, primarily on the number of domains content is hosted on and the number of resources. That’s because the main places we use resource prioritization are in our host resolution and connection pool priority queues. Chromium unfortunately caps the concurrent DNS lookups to 6 due to the prevalence of crappy home routers. Our connection pools cap concurrent connections per host to 6, per proxy to 32, and total to 256. Once you’ve got a TCP connection though, application level prioritization no longer plays a role, and the existing TCP connections will interleave data “fairly”. What this also implies is that for truly low priority resources, you may actually want to starve them. You want to throttle them to reduce network contention with higher priority resources although when doing so, you run the risk of underutilizing the pipe.

It’s sort of silly that the browser has to throttle itself to prevent network contention. What you really want is to send all the requests to the server tagged with priorities and let the server respond in the appropriately prioritized order. Turns out that some browsers already support this. Now, what happens if the browser and website both support SPDY? Well, then resource prioritization actually has significant effects, and higher priority resources may crowd out lower priority resources on the pipe (which probably is generally, but not always, good for page load time), depending on the server implementation. So if you’re utilizing one of the aforementioned loading techniques to asynchronously load resources, then you may incur performance hits due to suboptimal prioritization or lack of ability for the rendering engine to speculatively issue a request for said resource (when parsing is blocked). Thus, if HTTP/2.0 adopts SPDY features like multiplexing & prioritization, then it’ll become more important for web content to use appropriate markup to allow browsers to figure out appropriate resource prioritization.