Common Performance Bottlenecks

There’s tons of information out there about performance. It can be easy to get overwhelmed. Let’s fight overwhelm and talk about the most common performance bottlenecks so you can concentrate on what’s most important.

Round Trip Time

We’ve talked before about how bandwidth isn’t usually the limiting factor in web browsing: latency is. This will dictate how quickly things will get to your user. You can’t fight the speed of light, nor can you upgrade your user’s ISP, so how can you reduce the round trip time to your user? You can move your content closer to them with a CDN (content delivery network). If you’ve got users spread around the world, inventing in a CDN can make their experience better.

Caching

You’ve heard the truism, “The fastest request is the one not made.” You can reduce the number of requests that a returning user needs to make to your site by caching resources. If you need your users to see your changes immediately after you deploy new code or content, add a version hash to the end of your files. That way, changed files will be requested and unchanged files will still be cached.

JavaScript

Javascript is a tricky beast. On one hand, you have tools (like async and delay) to control the loading more granularly. On the other, these same tools can deceive you into a false sense of performant pages.

Parse Time

All JS, whether it’s loaded async or not, needs to be parsed by the browser. By pushing out the loading of unessential files, you can get your critical render path shorter so your paints will come sooner. However, async is not free. The user’s browser has to parse it.

Why does it matter that all JS needs to be parsed? It locks down the thread so that the user can’t interact with the page. On machines with faster processors, it’s not that big a deal. On low end mobile devices and old tablets, it can significantly retard the user’s ability to use your page in a timely way.

Execution Time

This should go without saying, but make sure that the JS that you write follows best practices. Keep your code as efficient as possible so that it executes quickly.

Client-Side Rendering Considerations

Recently, I was looking at a React site that didn’t set up the image requests efficiently. The browser had to download the JS, then parse it, and only then did it see that it needed to get images, so then it downloaded them well after they should have been. Review the waterfall for your page and make sure that the necessary assets are being requested as soon as possible. Keep an eye out for strange things and consider if your client-side rending JS might have something to do with the issue.

Images

Images can make up a large part of your page weight, so making sure that they’re performant can lead to significant gains.

Correct Size

If you’re loading a high-resolution image and all you need it for is a small thumbnail, you’re loading more bytes than you need to. Make sure you’re following best practices for retna images and not loading higher resolution images than you need.

Optimized

Your images should be at a proper compression that fits with your user’s needs. Google recommends compressing at 85% for JPEG. This way, you’re shrinking the file a bit, but not introducing too many distracting artifacts into the image.

Only loaded if necessary

Again, don’t make unnecessary network requests. If there are images above the fold where the user will see them, load them as fast as possible. However, if they’re not in the user’s initial view, don’t. It may be that the user will just use the header bar to search for a product and you won’t need to load them at all. You can then lazy-load the images when they come into view. There are a bunch of tools out there to help you with this. If your product owner or client doesn’t want the blurrly to sharp experience on scroll, you can still delay the load the out-of-sight images to the onload event so that they won’t interfere with other needed assets on the page.

Progressivly loaded

User perception of speed is important. It’s preferable to load a bit at a time, so the user knows something is going on, rather than loading the whole page all at once at the end. Because of this, you want your images to load progressivly: rather than drawing from the top, they should load the whole image in a blurry state that gets more clear as the image finishes loading. Your users will probably think the image is completely loaded at 60-75%. Even if they’re more discerning, they’ll still percieve the page as being loaded faster. Progressivly load your images!

Modern formats

We’ve started exploring the different modern image formats you can use (article on WebP, article on JPEG XR). If you use them, they are generally more compact than a simliarly-compressed JPEG or PNG. The problem is is that the browser support is spotty. Your JPEG XR won’t work in Firefox, and your JPEG 2000 only works in Safari. This may change in the coming years, and in the meantime, you can use a <picture> tag to help the browser spot which image it should use. You’ve also got to host the extra assets, so you’ll need to calculate if the work of dealing with all that is worth the performance gains to you.

Unminified and compressed files

For your JS and CSS, you’ll want to minify them to remove excess characters (you don’t want your users to have to download your 30 line rant comment in your JS) and compress your text-based responses with something like gzip as well.

CSS

There are things that you can do to make your CSS better (not having too many stylesheets and don’t load unused CSS rules). However, CSS is rarely the bottleneck for performance. Get the other things great and then worry about your CSS.

Sources:
Designing for Performance by Lara Hogan
High Performance Browser Networking by Ilya Grigorik
Udacity Course on Web Performance with Ilya Grigorik
High Performance Images by Colin Bendell, Tim Kadlec, Yoav Weiss, Guy Podjarny, Nick Doyle & Mike McCall from O’Reilly Press

Leave a Reply

Your email address will not be published. Required fields are marked *