Cache behavior in mobile browsers

I recently had to deal with a situation in which a web server, which served content primarily to mobile devices, was constantly running out of disk space.

The reason for this was that Apache was generating GBs of logs each day. The site associated with the server was a busy site, but it still seemed strange that the logs would grow to that magnitude.

A cursory examination of the logs showed that there were endless requests for static assets, like images, css files and javascript files, which would normally be cached by the browser. The requests were being responded to with a HTTP 304 response, which was even more strange, as the web server was configured to set an Expires header on all such files of 14 days.

A word about HTTP responses before we continue.

When a browser first requests a file, the web server will fetch that file from the file system and deliver it over the network with a HTTP 200 response. By default, the browser will then store that file in its cache. If the browser needs to  get the same file again, because it considers the copy in its cache to be too old, it will send what is referred to a Conditional GET request to the web server (by including a special HTTP header in the request, which includes the date the browser last accessed the file), which asks the web server to send the file again only if it has not been modified since the last request.

The web server then checks the last modified date on the file, and if it is the same as before, the web server will not send the actual file, but will instead issue a HTTP 304 response. This tells the browser that the file has not been modified since it was last accessed, and that it is safe to load that file from its cache.

Setting the Expires header of 14 days for files means that when those files are stored in cache, the browser will only make a Conditional Get request for any such file if 14 days have elapsed since it was first accessed and stored in the cache. This is a trade off between performance and control: your web server gets fewer requests, but there may be a delay in a user seeing an updated file.

In theory, this means that something like an image file should only be requested from the web server once every 14 days, which meant the behavior I was seeing in the logs was very strange indeed.

To get to the bottom of this I ran some Analog analysis on a week’s worth of logs. I targeted requests for a single-image file, and in the first pass, looked for the number of HTTP 200 responses for that image, and in the second pass, I looked for the number of HTTP 304 responses for the same file. I then did a comparison on the profile of mobile browsers making those requests.

The results are given below:

Status 200 % Status 304 %
Total 206448 100.00% 159266 100.00%
Android 2.1 917 0.44% 1449 0.91%
Android 2.2 3964 1.92% 10750 6.75%
Android 2.3 31692 15.35% 78638 49.38%
Android 3.0 57 0.03% 298 0.19%
Android 3.1 626 0.30% 2096 1.32%
Android 3.2 1938 0.94% 7332 4.60%
Android 4.0 28381 13.75% 468 0.29%
Android 4.1 1693 0.82% 78 0.05%
iOS 2 16 0.01% 0 0.00%
iOS 3 357 0.17% 61 0.04%
iOS 4 16975 8.22% 51845 32.55%
iOS 5 53818 26.07% 1412 0.89%
iOS 6* 57079 27.65% 2343 1.47%
iPod 4 878 0.43% 2181 1.37%
iPod 5 1502 0.73% 24 0.02%
iPod 6 1115 0.54% 30 0.02%
iPad 5 48 0.02% 2 0.00%
iPad 6 72 0.03% 2 0.00%

*iOS6 = iPhone 5, iOS5 = iPhone 4 etc etc…please don’t got out looking for the iPhone 6 in the shops!

The highlighted rows show the source of the problem.

Based on this data, it would appear that Android 2.3 browsers, and iOS 4 browsers (iPhone 3), have very limited caching capability.

Between them, they account for 23.57% of traffic on the site in the period in question, but 81.93% of Conditional GET requests. This would seem to suggest issues with the caching function in these browsers, which is most likely due to the cache space available to them reaching capacity.

What seems to be happening is that either new files are not being written to the cache (these phones had limited disk space), causing the browser to constantly refer to an out of date expires date on the files in the cache, of the cache is simply not functioning correctly, causing the browser to issue an unnecessary Conditional GET request.

The implications of this are pretty significant in terms of mobile web performance, which typically relies a much lower bandwidth capacity than the PC web.

Yes, it is true that Android 2.3 and iOS 4.0 are dropping out of the mix as new handsets come on the market, but given the amount of HTTP requests they generate, even a small population of older devices will have an impact on server performance.

Compare the relative data for iOS4 and iOS5 in the table above. There are 4 times as many standard HTTP 200 responses for iOS5 (iPhone 4), indicating that there are 4 times as many iPhone 4s as iPhone 3s  in use on the site, but when you factor in the HTTP 304 responses, the total number of actual HTTP requests issuing from iPhone 3s is greater!

I hope to run this analysis again in 6 months time. The results should make for interesting reading.

Leave a Reply

Your email address will not be published.

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>