growse.com

News

Optimize! OPTIMIZE!!!!!!!! (or, How I'm Trying To Make Websites Go Faster)

Something that's become a bit of a strange obsession of mine recently is site optimization for speed. I've worked on a few web projects in the past few years and one of the main things that I've learned is that performance is as important as functionality. It's easy to build a site that works and then declare the job done - far more difficult to make it perform and scale properly. I tend to use this site as a bit of a sandbox for experimenting with what works and what doesn't. Which is probably why bits of it are broken a lot of the time.

There's a whole bunch of different things that can be done, some of which are worth doing, and others aren't. Some also take up a lot of effort, others less so. The easy stuff is what most people know - compression and caching lifetime. If you get these right, you're probably most of the way there to getting good performance out of a particular codebase. For image compression, one of the most important things I found was that image quality isn't half as important as a lot of people think. When I was building the images for this site, I was trying to make them look as good as possible. These images are just pointers! Navigational aids that make the site more pleasant to use. No-one's going to spend more than a couple of seconds looking at them, so no-one's going to care that there's a slight bit of dithering on the blue in a particular area. Realising that, I managed to cut the size of one of the sprites from 70KB down to about 20KB. Doing that sort of thing everywhere can add to up to a big saving.

For text compression, there's a number of approaches. Webservers and browsers have supported gzip for quite a while now, and it's remarkably effective. Yahoo think that gzip reduces the size of web content by 70% can be used by 90% of the browsers out there. Good stuff. But on top of that, there's more. I use a nice app called Minify that can take a collection of javascript or CSS files and serve them up over a single request. You take a hit on the first request, as the php concatenates the files and strips out anything unnecessary, but it gets cached on the server side after that. Yahoo again reckon that minifying before gzip'ing can save another 5% on size. It's also less work for the webserver and browser to do, as the uncompressed data is smaller.

On top of that, there's a couple of extra things that can be done. If there's a lot of images, serve them from multiple subdomains. The browser can then put in lots of simultaneous requests across these different subdomains and load the complete image set faster. Pagespeed and Firebug are absolutely invaluable for messing around with this sort of thing.

However, all of this is useless unless the application code works well. I moved from Apache/CGI to Lighttpd/FastCGI a while back and saw some progress, but a little itch tells me that it could be better. There's a couple of things I need to investigate which may improve speed a bit. I may even ditch Perl as a platform (Oh No!) and do a rewrite in something like Java. Just wait for this to break again :)

Comments

radiac - July 7, 2009, 11:49 a.m.

Do you find that lighttpd is leaky? Given nginx a try? I'm using django these days - it's a bit of a resource pig, which goes against my optimisation instincts, but there comes a point when it's nice to just get something finished for a change. CMS nearly works now. Minifying is good, and putting it into a single request is even better - as you say in the paragraph below, some browser/server configurations will limit to 2 concurrent requests per domain. However, IIRC some browsers also have total concurrent request limits, so that's something to watch out for; also the more subdomains you have, the more DNS requests visitors will have to perform on your front page. There's definitely a sweet spot somewhere. One thing you didn't mention is you can do a similar thing to minify with images; put all your nav elements into one image, then use CSS background image positioning to display the relevant part of the image on the button.

Andrew - July 8, 2009, 11:26 a.m.

I keep meaning to look at nginx. I think I get put off by the comments around fastcgi and it being a bit more of a faff to create. I do have some concerns around the CGI::Fast module - It's not clear to me if the number of fcgi processes running is basically the number of simultaneous requests that the site can handle. I'd have thought it would do something clever like forking, but who knows. Maybe nginx does it differently? I meant to mention the css spriting - I do that for the button images at the top of the page. It doesn't work for all css images though, only those that are going on elements with fixed sizes. So my <li> item has a left background image bullet that needs to be on it's own, as I don't think you can stop the rest of the sprite appearing in the element as well.

Add a new comment

Do not fill this out: