In the last post I’ve introduced simple techniques to improve the performance of a web application. In this post I will talk about performance optimization on the browser side. With a few easy steps, the pages will load a lot faster and you will reduce bandwidth consumption and load on your servers.
Yahoo! has released a great tool called YSlow. YSlow analyzes web pages and suggests ways to improve their performance based on a set of rules for high performance web pages. It is an addon for Firebug, which in turn is an add-on for Firefox.
There are 22 rules defined in YSlow:
Since I like to learn by example, I’ve created a simple, rather ugly web application called Cootweets. It will be some sort of a “geo tagged flickr image with a tweet attached to it”-thing. So throughout this blog post, I will try to optimize the start page of Cootweets to satisfy YSlow’s requirements. I won’t talk about every rule, just the ones that YSlow complained about. Here is what the start page looks like: :
So lets get started and make the start page load faster.
Expires headers basically tell the browser how long it can cache a specific component. That avoids unnecessary HTTP requests on subsequent page views. That speeds up page load, saves bandwidth and reduces the load on the servers. If you use a CDN, setting the Expires headers will save you money.
Cootweets runs on Nginx and Passenger. Here is how I changed the Nginx configuration:
If you are running Apache, the solution is similar, but somehow I could not convince Apache only to cache assets that have a time stamp appended. I tried the same regular expression I used with Nginx, but then Apache just didn’t set any Expires headers at all. This actually makes sense, because the directive is called FilesMatch and not RequestMatch. I have come up with a workaround using Apache variables.
However, this does not set the time dynamically. Well of course, we could alter the Apache configuration on each deploy to fix this but that seems cumbersome for such a little task. If someone knows how to do this dynamically with an Apache directive, please let me know.
You can check if it works by looking at the HTTP headers returned from the webserver. YSlow offers a convenient way to do this but you can also use curl with the –head option to look at the headers.
Looking at the browser logs, I have noticed something strange. Even though the Expires headers are set correctly, Safari and Firefox still requested the components at the server and got back a 304 Not modified. While this is an improvement, I prefer no requests over a few requests. It took me quiet some time to figure out that this only happens when an explicit reload is triggered in the browser.
An here for Apache:
YSlow is a very useful tool to quickly analyze the page load performance. It offers a rich set of information and tools comfortably integrated in Firefox. Google has recently released a similar tool called Page Speed. The cool thing about page speed is that it actually estimates the bandwitdh reduction that could be achieved, so make sure to check it out too.
In this post, I take a stand against the strategy to solve all performance issues of a web application by throwing in more and bigger hardware. While it is in fact true, that hardware is cheap in comparison, you will inevitably hit a brick wall some time in the near future, if your traffic keeps growing and you don’t change your application to perform better. Of course, you might need bigger and better hardware at some point, but with a few relatively simple steps, you can postpone that investment. This is part 1 of a series of blog posts.
So you have deployed your brand new web app. There where a few minor issues during the deployment but nothing to worry about. One day you realize that your web app becomes slower each day as the user base grows and the traffic increases. What can you do to improve this?
Well, you could call in the big guns and install more and bigger machines, hardware load balancers, caching solutions, reverse proxies and database replication. If that is not enough, there is always database sharding. This will cost a lot of time, money and expertise to get this setup up and running. Of course, these resources are very limited and you would rather spend them on new features. If you don’t, your company may no longer exist in a few months.
Here is the good news: You can start off by taking smaller steps. I try to follow the principles YAGNI and KISS when developing software, so why not follow them when improving the performance of a website, right? So let’s get started.
What means faster? In general, it is referred to something like requests per second combined with the number of concurrent users. But that is not the whole story. In my opinion, the performance of a website should be measured in the page responsiveness perceived by the user. So that includes the time needed to display a page.
Assuming a rather standard web application, we are going to take the following steps to improve the performance of our web application.
In the next part I will talk about page responsiveness and client side caching, so stay tuned.