Faster websites – Improving User Experience

At Google I/O (Google’s developer conference), Steve Souders (the creator of YSlow) presented a few ideas for making websites even faster.

When it comes to optimizing a website for speed and user experience, there’s only so much you can do from the backend.  The most room for performance improvement is in client-side frontend.  Anywhere between 80 and 90 percent of the page load time is spent on the frontend, not on the backend doing server processing.

Four ideas for improving frontend performance:

1) Load external resources in parallel with domain sharding.
On a site with lots of external resources like images, CSS, or JS files, most browsers request these resources one at a time (in series).  This is because of the limit on the number of concurrent connections to each server that is configured in the browser.  By placing external resources on multiple domain names you can effectively raise the number of connections and reduce the time it takes to load these resources.  Having more connections allows the browser to fetch more external resources at the same time (in parallel).

While this runs contrary to one of the other rules of optimization that says you should reduce DNS lookups, the benefits of introducing a new domain name can outweigh the time wasted by a request that is blocked waiting for the server.  Eliminating blocks on a “critical path” can reduce the time your browser spends idle.

Some of the newer browsers like Firefox 3, IE 8, Safari, and Chrome have raised the concurrent connection limit to cut down on bottlenecks and speed up page load performance.

2) Reduce idle network time by flushing the document early.
This only applies to websites that are database-driven or spend a signifcant time on server-side processing.  Flushing the document early can allow the browser to start loading images and external resources while the server is still building the rest of the page.  Typically, the server builds up the response in server-side buffers and sends the entire document as one large chunk when all the processing is complete.  This means that the browser and client network connection are idle while the server is processing and then develop a huge backlog of external resources to load when the document is sent.  You can utilize some of this idle time by sending portions of the document as they are complete.  Sending the document head with CSS and JS resources allows the browser to start to load these resources even while the rest of the document is still being constructed on the server.

When using this strategy to speed up a website, pay attention to the concurrent connection limit as the main request for the document still counts as one open connection!  Use domain sharding as discussed earlier to further minimize network bottlenecks.

3) Improve render speed by simplifying CSS selectors.
CSS is parsed by browsers from right to left, not left to right as it is written.  So even though you have a bunch of ID selectors at the beginning of your rule, leaving a generic selector as the last selector can effectively nullify the benefit of the ID selectors.  The rightmost selector (key selector) ideally should be as precise as possible.  By adding an ID or class to the rightmost selector, you can reduce the number of possible matches the browser finds for each rule.

div#main div#head div#nav ul#links li.item a { ... }

div#main div#head div#nav ul#links li.item a.navlink { ... }

In the first example, the a selector causes the browser to consider all <a> elements and then work up each subtree checking selectors from right to left.  However, if the class navlink were added to the last selector and similarly added to the document for the appropriate <a> tags, the browser would only consider <a> elements with the navlink class, a much smaller set of elements.

However, improving CSS performance comes at the cost of adding weight to the document and the flexibility of the CSS rules.  See the Mozilla Developer Center for a more detailed explaination of how browsers handle CSS.

4) Going beyond gzipping – and the 15% who don’t get gzipped responses.
15% of users worldwide (maybe even 20% of US users) don’t get gzipped responses.  The major reason for this is proxies and anti-virus programs that munge the Accept-Encoding header the browser sends. It’s thought that these programs do this so that the response they get is uncompressed, making it easier to scan.  While the ideal solution would be for the proxy and anti-virus vendors to allow gzip compressed responses, there is a workaround.

The workaround alternative is to not assume that the response will be compressed with gzip and instead minify the html, CSS, and Javascript.  Minifying in addition to gzipping only saves an extra 3-5%, but minifying without gzipping saves up to 30% from the plain response!  While this isn’t much compared to the 70% gzip could save you, 30% less network transfer time could be a big deal for the 15-20% of users who would have otherwise gotten full, un-compressed, un-minified responses.

Ultimately speed impacts revenue.
If Google were to become 500ms slower, they might see a 20% drop in traffic.  Amazon could stand to lose 1% of sales for every 100ms slower their site ran.  What does site performance mean to you?

Video and slides from the session are available on the Google I/O website.

Leave a Reply