- Category: Programming
- Created on Wednesday, 16 February 2011 15:49
- Last Updated on Saturday, 15 March 2014 21:26
Let us take a this hypothetical situation. You have to serve a web page. You want the whole page to be sent back in 500 ms (milliseconds). If your user has a good network and he is not too far from your webserver, you can further assume that around 50 ms will be spent on the network. This means that you have 450 ms to collect all the data about this web request, do the fancy manipulations (sorting/filtering/updating files etc.) and serve it to the user. You need to make four external calls to get this data - 2 of them to an external web service and 2 of them to your own database.
Not the completely right answer and the right answer(s)
Most people will say - "we will cache the results of the slow database query and the slow webservice call ". In my opinion, depending on only caching to give your users a page within 500 ms is not the right answer. Listed below are some of the techniques, that together with caching, will make sure your users see a fast loading page -
- Have a timeout when you make your external calls
- Eliminate the slow call
- Do the slow call after the page load (deferred call)
I will explain each of these options in the sections below
Have a timeout when you make your external calls
Curl has the CURLOPT_TIMEOUT_MS option that can be set using curl_setopt. For MySQL queries, there does not seem to be a nice way to have a timeout. When you get a timeout, serve the user with some failback content.
If you have a cache through which you pass your external calls, you should need to serve the failback content only a under few circumstances, for example, in case of connection failure or if the backend service gets overloaded due to some runaway queries. It is a good idea to keep a log whenever you need to serve a failback content, so that you can analyze the failures later.
Eliminate the slow call
Do not make the slow call at all. Have a cronjob which makes the call (maybe every 10 minutes) and then updates a local store (for example sqlite db or a file) with the results. In you application, query this local sqlite db or the file and show that results in your webpage.
Note that I am not in favor of using memcache or APC as your local store in this case. The reason is that you do not have any control over the eviction policy of your items. When you use a file or a sqlite db for this, you are sure that the item will be there (except in the event of a disk or memory corruption). A further precaution that you should have is to store the timestamp when the cronjob last updated your local store.
A caveat to this approach is that you cannot use this when your slow call is specific to each user of your site (for example, the friends of a user). Having said that, it is my opinion that a lot of external calls can be sucessfully converted into a call to a local store. Some examples -
- news stories that are based on user's state or country
- the number of people currently on a site
- the number of people who have "liked" or "tweeted" a particular story on the frontpage of your site
- the top N entries on your site
Convert it into a deferred call
the page. The way this works is that you send the page back to the
user and this page has a placeholder (e.g a
div element) for the
content that is specific to this user and might take more than 500 ms
to compute. The browser can then makes an ajax call to request the
content for this module and populate it later. The trickiest decision
is how to decide which modules can be downloaded as an ajax call.
- general information about the user, e.g. name, summary, karma count, friend's online
- last searches performed by the user
- news content from around user's zip code
It is a good idea to have a timeout for the ajax call, else the user might see the spinning wheel in his browser window if the ajax call fails or hangs.
Caching is great, but by itself it cannot guarantee users a consistently fast loading website. Use the techniques outlined above, in conjunction with caching to give your users a faster loading site.
Leave your comments about this article here