Faster than Stack Overflow
February 21, 2011This blog is faster than Stack Overflow.
The ASP.NET MVC website, designed and maintained by some of the best developers in the world, has been beat by this home-grown blog engine running on a $10/month shared hosting provider.
I don’t mean to gloat. I just mean my web app pwnz yours!!1
I kid, I kid. As a collective of web performance best practices, Google’s Page Speed is a pretty good measure of how fast a website performs from the client point of view. Naturally, several Page Speed recommendations can come at the cost of server-side performance (or just development overhead) so maxing out your score can quickly become an effort of diminishing returns.
Beyond the 80s
When I built this blog I had a score in the low 80s which isn’t too difficult to achieve on a basic website. Based on nothing more than a gut assertion, I’d say a score in the 80s is the baseline for “good” performance. It means you made an effort. Do the easy and obvious stuff: use proper markup, minify/combine CSS and JavaScript, and avoid many requests, you’ll probably score somewhere in the 80s.
A score in the 90s takes a bit more work, and frankly it may be a better choice to work on server-side performance or useful features depending on your situation. My efforts to score as high as a 94 was for little more than to see if I could get a new high score in this little game of web performance.
Optimization techniques for the ASP.NET website
The following is an assortment of techniques for improving your page speed ranking.
Combine and minify Javascript and CSS
I’m not going go into this in detail. There are many solutions and implementation examples you can find with a few Google searches. What I do want to do is highlight Justin Etheredge’s SquishIt utility. It’s small, simple, slick and easy.
For instance, take all the CSS files on your site (or page) and add them to a bundle like so:
<%= Bundle.Css()
.Add("~/css/reset.css")
.Add("~/css/text.css")
.Add("~/css/960.css")
.Render("~/css/combined_#.css")
%>
And out comes something like this:
<link rel="stylesheet" type="text/css" href="/css/combined_55A2DED9A14F8B269A584B0E56382BE4.css" />
One CSS file, whitespace minified. Would you like fries with that? If you’re wondering what the ugly mess of characters in the name is for – that’s the hash of the file contents. It’s necessary so when you change one of the source files, SquishIt knows it needs to create a new bundle (and your browser knows not to use the cached old version it may have).
Check out SquishIt on Justin’s blog for more details.
Optimize Images by applying lossless compression
This was actually new to me. There are several tools available that can perform lossless compression on JPEG and PNG files with no effect on image quality. Google recommends a few tools here.
I downloaded all my Windows Live Writer generated PNG files and ran them through PUNIG, a .NET GUI frontend for OptiPNG. A minute later I had 5MB of images reduced to 4.5MB or so. That’s not amazing, and frankly it’s not worth it to me and this blog, but things like this can add up in bandwidth costs. 10% reduced payload, for free? Something to consider.
Leverage browser caching
This can be done programmatically, but if you have access to IIS 7’s admin console (or want to create a web.config) you can easily turn this on for certain directories.
Go to and open the HTTP Response Headers feature
Click “Set Common Headers…” in the Actions pane
Check “Expire Web content” as desired.
Remove query strings from static resources
Resources with a “?” in the URL are not cached by some proxy caching servers, so if you serve up files like I do on this blog (eg. /image.axd?picture=image_84.png) they may not be cacheable by some proxy servers.
This is something I’m tempted to do because it’s not too hard – even if I wanted to retain the functionality of my image handler, I could just do some URL rewriting to appease Google and any caching server. But you know what. I ain’t here to be perfect. I’m just not certain this is such a big deal. Frankly, I’d say the proxy servers that don’t honor query strings like this are the ones that need fixing. This is perfectly normal and typical HTTP behavior.
Some rules worth avoiding
As I mentioned, not every page speed rule will be worth it.
Minify HTML
Sure, if minifying CSS and Javascript reduces payload, so would minifyingHTML. But on almost any website, the HTML is dynamically generated by server-side code. Is it worth the CPU cycles to send every page output through some squisher just to save a few K in download size? Probably not. Combined with caching of said HTML? Only maybe.
Still, who actually does this? I’ll put this in the “no thanks” category.
Remove unused CSS
This may be the most contradictory rule. Yes, requiring a browser to download a bunch of CSS styles that aren’t even used by the page is a waste. But you also want to serve as few total CSS files as possible so the browser likely has them in cache.
10 pages with 10 small, distinct CSS files, or 10 pages with 1 big CSS file? If you expect your users to hit several pages, you are probably better off forcing them to download 1 big CSS file just once – especially once you consider the development overhead of former option.
Conclusion
Use Google Page Speed to evaluate how well you are taking advantage of client-side performance techniques. While a higher score does imply your site is speedier, there are trade-offs you may have to consider.
At the end of the day, if you have control over your website platform and a make a small effort, you can get a pretty good score. Or you can be CNN.com and just say F&$% it. Really, CNN? A 64 score? 16 Javascript files, no compression, or minification?
Tags: page speed, google, optimization
Categories: ASP.NET, ASP.NET MVC, CSS, IIS

