Using YSlow to optimize websites

Yahoo! has released a great Firefox addon - or rather, an addon for a Firefox addon - called YSlow. YSlow allows you to analyze and suggest improvements to various performance metrics on the website you’re currently visiting.

For kicks I decided to let it loose on biq.dk. Unfortunately it gave me a disheartening grade of F:

Performance grade: F (46)

Ah well, sounds like a perfect opportunity to improve, and the rest of this entry contains the areas where the biq.dk frontpage did not receive an A-grade, and a description of the modifications I had to perform on our setup to satisfy the addon.

Make fewer HTTP requests (F)

This page has 9 external JavaScript files.
This page has 12 CSS background images.

This is probably a place where I could squeeze a bit of extra performance out of the page. I should consider setting up an asset server for our static assets. This can easily be the same machine with a different hostname - say one for each type of asset - which will “trick” the browser into fetching more assets simultaneously.

In Rails something like this is fairly easily achieved. Rails 1.2 the notion of a single asset host, which can be configured in your environment:

# Enable serving of images, stylesheets, and javascripts from an asset server
# config.action_controller.asset_host                  = "http://assets.example.com"

If that’s not enough for you, Edge Rails introduces the ability to have multiple asset hosts simply by using a numbered naming scheme.

And if that is not enough either, there’s a plugin that allows you to use a specific asset host for each type of asset. Don’t come complaining about no options, here.

To make this even simpler to implement for me, I have to do almost nothing. We already serve up the same content regardless of what you put in front of biq.dk (well, almost), so http://assets.biq.dk/images/rails.png already exits and I just have to tell Rails to use an asset server in production mode.

Another approach to this - that I can still use - would be to use the AssetPackager plugin to minimize the amount of separate JS and/or CSS files I send over the pipe, but that’s a task for another day.

Use a CDN (F)

This is overkill for us. With the vast majority of our users located in Denmark we don’t need a geographically widespread Content Delivery Network. The above-mentioned asset server is content delivery network enough for us.

Add an Expires header (F)

A bunch (20 or so) of our files didn’t even have an Expires header. Basically this means that browsers may (should?) request the file on every request, which is stupid. Stuff like Javascripts, images, and stylesheets rarely change so it makes a lot of sense caching them for a long while.

Rails even makes it even easier for us: It puts the timestamp of each files last modification at the end of each asset request (that’s why images in Rails applications are usually addressed as /images/foo.png?74734234).

This means the browser will not request an asset unitl the last modified timestamp changes (in which case the asset is considered a new asset by the browser), or until the cached version expires.

With Apache 2.2 we can use the mod_expires module to set a default Expiry header ages into the future. Note that we only want to do this for our assets, which are all kept in the public/ directory:

<Directory /var/www/applications/biq/current/public/>
  ExpiresActive On
  ExpiresDefault "access plus 1 year"
</Directory>

And voila, YSlow now gives us a C grade here instead of the F. The last 2 components to not have an expires header are unfortunately external Javascript files outside of our control.

Gzip components (F)

Nothing got gzipped initialize. Gzipping textual content is a great way to minimize bandwidth consumption since text like HTML, CSS, and JavaScript compresses very well. It does cause your server - and your users browser - to do a bit more legwork but the cost of that is - at least that’s the theory - nothing to worry about.

Using mod_deflate and a modified version of Coda Hales Apache 2 config we tell Apache 2 to compress all our text based contents for browsers that support it:

# Deflate
AddOutputFilterByType DEFLATE text/html text/plain text/xml application/xml application/xhtml+xml text/javascript text/css application/x-javascript
BrowserMatch ^Mozilla/4 gzip-only-text/html
BrowserMatch ^Mozilla/4.0[678] no-gzip
BrowserMatch \bMSIE !no-gzip !gzip-only-text/html

With one external Javascript file left uncompressed, our grade here transformed into a B.

+Update: If you need to serve your content to Flash and want it to work in Internet Explorer 6, you should check out this post: Warning: Warning: GZip content, Flash Player, and Internet Explorer 6 .+

Move scripts to the bottom (D)

7 external scripts were found in the document HEAD. Could they be moved lower in the page?

Hrm, this an interesting question, and one I am not entirely certain about. More experimentation will have to prove if this is a viable option for us, but for now I have to leave it as it is.

Minify JS ©

None of our JavaScript files have been obfuscated or minified. They’re simply the generic Prototype and Scriptaculous stuff. While I suppose I could run the javascripts through a processor of sorts when deploying, the benefit of this seems miniscule when the scripts are already being served compressed.

Configure ETags (F)

To be honest, I had never heard of these “ETags” until I ran YSlow. But according to Yahoo!s thirteen simple rules for speeding up your website I don’t need to worry about them since we’re serving biq.dk from a single webserver, and ETag issues apparently only crop up when serving the same assets from multiple servers.

The resulting Performance Grade: C (71)

Not bad, a C grade. There are still things I can improve, obviously, but the above are the quick improvements I could kick out during an hour or so, and they should already have improved the user experience quite a bit.

YSlow is a great little addon, and having it hand out grades is genious. Nothing motivates like being told you suck, and having the possibility of a higher score dangled in front of you.

Comments

Arkadiusz July 27, 2007

Nice article about small, but pretty damn useful tool.
Thanks for sharing.

We've got also F - need to do some improvements as well;)

------
Btw. I believe it is extension of Firebug extension ;)

Jørgen Bang Erichsen July 30, 2007

Nice article!

I played around with YSlow as well and it is pretty neat.

Actually, much of the functionality of the AssetPackager plugin can be found in Edge Rails which allows you to specify stuff like


This will generate one css file containing all your css and one Javascript file containing all your Javascripts and thereby reducing the number of http requests.

/Jørgen

Olle Jonsson August 10, 2007

Oh, this is good. Thanks Mentalized, and thanks Yahoo! Developer Network.

Much about web caching can be learnt about in the amazing mnot caching tutorial which explains expiry headers and ETags, and all that jazz.

If you ever write any large amount of JavaScript, you might want to check out JSLint - a syntax checker and grammar complainer for JavaScript. It goes hand in hand with Minifying - the JSLint app was made to make scripts always comply with what the minifying algorithm can deal with. If your JS passes JSLint, it will pass minification. And, it will look better. The Minify project is for PHP, but there are tons of other implementations of the algorithm, also one for Ruby. JSLint details page tells more about these implementations.

Re: extensions to Firebug. Neat sub-niche! FirePHP is a crazy PHP-live-in-your-Firebug extension project, but it was too alpha, even for me. Screenshot with comments explains more about it.

raghavendra August 14, 2007

hey nice article , i am trying to use yslow ! i am at F. please tell me how can i improve the performance at development level. likewise while we run the server on webrick or mongrel cluster without a apache configured.

also i havent got the javascripts being moved to bottom of page . found in head , can u explain me please .

Jakob S August 14, 2007

raghavendra, most of the stuff that can be improved only makes sense in a production environment with a production grade server setup. Don't worry about it until you're ready for that step.

That said, I am sure Yahoo!s Thirteen Simple Rules for Speeding Up Your Web Site which you can find at http://developer.yahoo.com/performance/rules.html can explain things to you.

Robert Berger August 21, 2007

So if you do the Apache mod_expire config you mention in Add an Expires header, will that work if you are using a mongrel_cluster behind the Apache balance_proxy? It seems to not work for me off hand.

Thanks for a useful tutorial in any case!

Jakob S August 21, 2007

Robert, if you're serving your static assets from Mongrel, then no, it probably won't make a difference.

Truth be told, though, you probably should not serve your assets through Mongrel. Apache is great at pushing out static files, so use it to do that. That way you also get the benefit of improved caching.

Commenting on this entry has been closed.