I ran some tests to know how the mobile smartphones behave with the cache policy returned by the HTTP headers.
Tests were run on :- Iphone 3G OS 2.2
- Iphone 3GS OS 3.1.2
- Iphone 3GS OS 3.1.3
- Iphone 3GS OS 4.0
- Iphone 4 OS 4.0.1
- Iphone 4, OS 4.3.3
- Iphone 3G OS 4.2.1
- BlackBerry 9800 (BB 6)
- Nexus S (Android 2.3)
- HTC Desire (Android 2.1 update1)
- Samsung I9000 (Android 2.2)
- Orange Tactile (Android 2.1 update1)
- Samsung Wave GT-S8500 (Bada 1.0)
- Samsung Wave 2 GT-S8530 (Bada 1.2)
- HTC Hero (Android 1.5)
- Samsung OMNIA (Windows Phone 7.0, IE7 mobile)
Caching a single light resource
First, if you want your browser to cache resources you should return the right http headers.
I used expires and cache-control headers to ask the browser to cache.
Expires: [Expiration time in GMT Format]
Cache-Control: max-age=[Expiration time in seconds]
For my test I used "mod expires" on my Apache server.
My first test was very simple and I worked with small objects (10Kb). The goal of this first test was to know if the mobile's browser caches any resources.
I put some static resources on a web server, reachable at static.mywebserver.com. Then I created a webpage which loads one static resource. This page is hosted on 2 different domains: mywebserver1.com and mywebserver2.com. In the web page there is also a link that allows me to navigate from one domain to the other.
I ran this test several times with different types of resources:
- a JavaScript file
- a CSS file
- an image file
- an HTML page through an iframe
- an audio file
- a video file
I also tested the behavior of the device using dynamic loading by adding DOM Nodes with JavaScript.
Here the example of the webpage which loads the JavaScript static resource:
<html>
<head>
<title>Iphone Cache test</title>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<meta content="width=device-width, initial-scale=2.0; maximum-scale=1.0; user-scalable=false"/>
<meta content="yes">
<script src="http://static.mywebserver.com/file_10Ko.js"></script>
</head>
<body>
<p><a href="http://mywebserver1.com">MyWebServer1</a></p>
<p><a href="http://mywebserver2.com">MyWebServer2</a></p>
</body>
</html>
1.1.Refreshing the page
I started to load the page at mywebserver1.com and refreshed it to know if the resource was fetched from the cache or from network. Two ways were used to refresh the page:
- Click on the refresh button
- Edit the url in the address bar and click on the "Go" button.
| OS/Browsser | Edit URL + OK | Refresh Button |
|---|---|---|
| Iphone 3G OS 2.2.1 | Fetch from network(0) | Fetch from network |
| Iphone 3GS OS 3.1.2 | Fetch from cache | Fetch from network |
| Iphone 3GS OS 3.1.3 | Fetch from cache | Fetch from network |
| Iphone 3GS OS 4.0 | Fetch from cache | Fetch from network |
| Iphone 4 OS 4.0.1 | Fetch from cache | Fetch from network |
| Iphone 4, OS 4.3.3 | Fetch from cache | Fetch from network |
| Iphone 3G OS 4.2.1 | Fetch from cache | Fetch from network |
| BlackBerry 9800 (BB 6) | Fetch from network(0) | NA |
| Nexus S (Android 2.3) | Fetch from cache (1) | NA |
| HTC Desire (Android 2.1 update1) | Fetch from cache | Fetch from network |
| Samsung I9000 (Android 2.2) | Fetch from cache | NA |
| Orange Tactile (Android 2.1 update1) | Fetch from cache | NA |
| Samsung Wave GT-S8500 (Bada 1.0) | Fetch from cache | Fetch from network |
| Samsung Wave 2 GT-S8530 (Bada 1.2) | Fetch from cache | Fetch from network |
| HTC Hero (Android 1.5) | Fetch from cache | Fetch from network |
| Samsung OMNIA (Windows Phone 7.0, IE7 mobile) | Fetch from cache | Fetch from network |
(0) I ran some other tests to try to better understand the strange behavior of the BB9800, and the Iphone OS 2.2.1 concerning the "Go button". I noticed that, in fact, if I clicked on "Go" button without changing the URL, all the content was refreshed. Nevertheless, if I changed the URL from mywebserver1 to mywebserver2 the content from static.mywebserver.com (already loaded from mywebserver1.com) was fetched from the cache.
(1) If the content was in the disk cache, the content was fetched from the cache whereas if the content was stored on memory cache, the browser fetched the resource from the network (see section “max size of a single resource”)
1.2.Browsing from the first to the second website
The second step was to navigate from webserver1.com to webserver2.com using the link in the static page.
For all devices, except on Iphone OS 2.2.1, the result was that the static resource was fetched from the cache at each time.
On Iphone, the HTML content of the iframe was never cached.
When I navigated from mywebserver1 to mywebserver2 with IOS 2.2.1 the resource was not taken from the cache the first time but the second time it did(when I was on mywebserver2 and returned to mywebserver1).
2. Max size of a single resource
I observed that all type of resources haven't the same size limit to stay in the browser's cache. During this test I noticed two types of cache on Android 2.2 and 2.3:
- A memory cache
- A persistent disk cache
When I navigated from webserver1 to webserver2, I managed to cache more than 2Mb for a single resource but when I restarted the device, this same resource was not taken from the cache. If the resource was less than 2Mb, rebooting the phone had no effect and the resource was taken from the cache.
| OS/Browser | Js | CSS | Image | Audio | Video | Html through Iframe |
|---|---|---|---|---|---|---|
| 3G / OS2.2 | 0.95Mb | 1Mb(0) | 7.5Mb | 0Mb | 0Mb | 0 |
| 3Gs / OS3.1.2 | 7.5Mb | 1Mb(0) | 7.5Mb | 0Mb | 0Mb | 0 |
| 3Gs / OS3.1.3 | 7.5Mb | 1Mb(0) | 7.5Mb | 0Mb | 0Mb | 0 |
| 3Gs / OS4.0 | 7.5Mb | 1Mb(0) | 7.5Mb | 0Mb | 0Mb | 0 |
| Iphone 4 / OS 4.0.1 | 7.5Mb | 1Mb(0) | 7.5Mb | 0Mb | 0Mb | 0Mb |
| Iphone 4 / OS 4.3.3 | >10Mb | >10Mb | >10Mb | 0Mb | 0Mb | 0Mb |
| Iphone 3G / OS 4.2.1 | >10Mb | >10Mb | >10Mb | 0Mb | 0Mb | 0Mb |
| BlackBerry 9800 (BB6) | 10Mb | 10Mb | 10Mb | 0Mb | NA | 10Mb |
| Nexus S (Android 2.3) | 2Mb(3) | 2Mb(3) | 2Mb(3) | 0Mb | 0Mb | 2Mb(3) |
| HTC Desire (Android 2.1 update1) | 6Mb(1) | 6Mb(1) | 6Mb(1) | NA(5) | NA(5) | 6Mb(1) |
| Orange Tactile (Android 2.1 update1) | 6Mb(1) | 6Mb(1) | 6Mb(1) | NA(5) | NA(5) | 6Mb(1) |
| Samsung I9000 (Android 2.2) | 2Mb(3) | 2Mb(3) | 2Mb(3) | NA(5) | NA(5) | 2Mb(3) |
| Samsung Wave GT-S8500 (bada 1.0) | 150Ko | 150Ko | 150Ko | NA(4) | NA(4) | 150Ko |
| Samsung Wave2 GT-S8530 (bada 1.2) | 150Ko | 150Ko | 150Ko | NA(4) | NA(4) | 150Ko |
| HTC Hero (Android 1.5) | 6Mb(1) | 6Mb(1) | 6Mb(1) | NA(4) | NA(4) | 6Mb(1) |
| Samsung Omnia (Windows Phone 7.0, IE 7 mobile) | >10Mb(2) | >10Mb(2) | >10Mb(2) | NA(4) | NA(4) | >10Mb(2) |
(0) More than 1Mb of CSS crashed the browser during the experiment
(1) Cache size parameter in the browser settings
(2) I stopped the test at little more than 10Mb; I don’t have the exact limit size
(3) Disk cache. Memory cache accepted more (3.5Mb of JavaScript, 5Mb of CSS and more than 8Mb for images): see section “Life cycle of cached resources”
(4) Video and audio tag not implemented
(5) Bugs on video and audio implementation, I did not manage to pass the test
- On Android 2.2 and 2.3, two type of cache exist
- A persistent disk cache
- A temporary memory cache
3.Total cache size for a web site
For this test I tried to load a maximum of resources (hosted on static.mywebserver.com) from mywebserver1 and then navigated to mywebserver2 and observed if the resources were fetched from network or from the cache.
| OS/Browser | Total limit |
|---|---|
| 3G / OS2.2 | 7.5Mb |
| 3Gs / OS3.1.2 | 7.5Mb |
| 3Gs / OS3.1.3 | 7.5Mb |
| 3Gs / OS4.0 | 7.5Mb |
| Iphone 4 / OS 4.0.1 | 7.5Mb |
| Iphone 4 / OS 4.3.3 | >10Mb |
| Iphone 3G / OS 4.2.1 | >10Mb |
| BlackBerry 9800 (BB6) | 10Mb |
| Nexus S (Android 2.3) | 6Mb(2) |
| HTC Desire (Android 2.1 update1) | 6Mb(1) |
| Orange Tactile (Android 2.1 update1) | 6Mb(1) |
| Samsung I9000 (Android 2.2) | 6Mb(2) |
| Samsung Wave GT-S8500 (bada 1.0) | 2.5Mb |
| Samsung Wave2 GT-S8530 (bada 1.2) | 2.5Mb |
| HTC Hero (Android 1.5) | 6Mb(1) |
| Samsung Omnia (Windows Phone 7.0, IE 7 mobile) | >10Mb(3) |
(1) Cache size parameter in the browser settings
(2) Disk cache. Memory cache accepted more (3.5Mb of JavaScript, 5Mb of CSS and more than 8Mb for images): see section “Life cycle of cached resources”
(3) I stopped the test at little more than 10Mb; I don’t have the exact limit size
Note: A total of ~6.3Mb is a maximum to display several images on OS3.1.2, OS3.1.3, OS4.0, otherwise some images are not displayed. This limit is ~4.5Mb for OS2.2.1
4. Total cache size
I ran the same previous script on several domains to know if the size limitation was for a unique website or for several websites. In fact the limitations above are browser’s limitations and I did not manage to cache more.
| OS/Browser | Total limit |
|---|---|
| 3G / OS2.2 | 7.5Mb |
| 3Gs / OS3.1.2 | 7.5Mb |
| 3Gs / OS3.1.3 | 7.5Mb |
| 3Gs / OS4.0 | 7.5Mb |
| Iphone 4 / OS 4.0.1 | 7.5Mb |
| Iphone 4 / OS 4.3.3 | >10Mb |
| Iphone 3G / OS 4.2.1 | >10Mb |
| BlackBerry 9800 (BB6) | 10Mb |
| Nexus S (Android 2.3) | 6Mb(2) |
| HTC Desire (Android 2.1 update1) | 6Mb(1) |
| Orange Tactile (Android 2.1 update1) | 6Mb(1) |
| Samsung I9000 (Android 2.2) | 6Mb(2) |
| Samsung Wave GT-S8500 (bada 1.0) | 2.5Mb |
| Samsung Wave2 GT-S8530 (bada 1.2) | 2.5Mb |
| HTC Hero (Android 1.5) | 6Mb(1) |
| Samsung Omnia (Windows Phone 7.0, IE 7 mobile) | >10Mb(3) |
(1) Cache size parameter in the browser settings
(2) Disk cache. Memory cache accepted more (3.5Mb of JavaScript, 5Mb of CSS and more than 8Mb for images): see section “Life cycle of cached resources”
(3) I stopped the test at little more than 10Mb; I don’t have the exact limit size
5. Lifecycle of cached resources
I ran some test to detect if the cache was cleaned on several actions:
- Lock/unlock
- Power of
- Quit Safari
- Close Tabs
Results:
| OS/Browser | Lock / unlock | Power Off | Close al tabs | Quit browser |
|---|---|---|---|---|
| 3G / OS2.2 | Resources fetched from cache | Resources fetched from network | Resources fetched from network | Resources fetched from cache |
| 3Gs / OS3.1.2 | Resources fetched from cache | Resources fetched from network | Resources fetched from network | Resources fetched from cache |
| 3Gs / OS3.1.3 | Resources fetched from cache | Resources fetched from network | Resources fetched from network | Resources fetched from cache |
| 3Gs / OS4.0 | Resources fetched from cache | Resources fetched from network | Resources fetched from network | Resources fetched from cache |
| Iphone 4 / OS 4.0.1 | Resources fetched from cache | Resources fetched from network | Resources fetched from network | Resources fetched from cache |
| Iphone 4 / OS 4.3.3 | Resources fetched from cache | Resources fetched from network | Resources fetched from network | Resources fetched from cache |
| Iphone 3G / OS 4.2.1 | Resources fetched from cache | Resources fetched from network | Resources fetched from network | Resources fetched from cache |
| BlackBerry 9800 (BB6) | Resources fetched from cache | Resources fetched from cache | Resources fetched from cache | Resources fetched from cache |
| Nexus S (Android 2.3) | Resources fetched from cache | Resources fetched from cache | Resources fetched from cache | Resources fetched from cache |
| HTC Desire (Android 2.1 update1) | Resources fetched from cache | Resources fetched from cache | Resources fetched from cache | Resources fetched from cache |
| Orange Tactile (Android 2.1 update1) | Resources fetched from cache | Resources fetched from cache | Resources fetched from cache | Resources fetched from cache |
| Samsung I9000 (Android 2.2) | Resources fetched from cache | Resources fetched from cache | Resources fetched from cache | Resources fetched from cache |
| Samsung Wave GT-S8500 (bada 1.0) | Resources fetched from cache | Resources fetched from cache | Resources fetched from cache | Resources fetched from cache |
| Samsung Wave2 GT-S8530 (bada 1.2) | Resources fetched from cache | Resources fetched from cache | Resources fetched from cache | Resources fetched from cache |
| HTC Hero (Android 1.5) | Resources fetched from cache | Resources fetched from cache | Resources fetched from cache | Resources fetched from cache |
| Samsung Omnia (Windows Phone 7.0, IE 7 mobile) | Resources fetched from cache | Resources fetched from cache | Resources fetched from cache | Resources fetched from cache |
- Powering off Iphone cleared the cache
- Closing all tabs on Iphone cleared the cache
- Experiments made on Iphone let’s think that there is no disk cache on Iphone but only memory cache.
6. Launched from the homescreen
I decided to bookmark the webapp on the home screen and launch it to see if the previously cached elements were retrieved from the cache or from the network.
Iphone
For each device and OS version of Iphone, each time I launched the webapp, I saw the resources fetched from network.
The only cache mechanism was through several calls to one single resource in a webapp. For example, if you display twice the same logo in a webpage, only one request is sent to the network.
Android, Bada, WP7
At each time, there was no difference of behavior between opening the browser (then reaching our webapp) and launching webapp from home screen : the content was well cached.
Conclusion
This first experiment has to be completed with others tests to validate all that results concerning the cache size limit but we can say:
- Native Iphone cache is not well adapted to enhance webapp performance so keep your resources as light as possible. Consider that user cache is always empty for an Iphone user when you develop your webapp
- When a webapp is launched from the springboard on Iphone, at each startup, resources are fetched from the network, so no cache benefit.
- On Android and Bada, cache mechanism is well implemented but the storage size offered by the device is small compared to desktop browser. The size limitation is quickly reached.
- Samsung OMNIA/WP7 seems to work well with a cache limit bigger than other device/OS
- Alternative such as applicationCache from HTML5 specs should be used if you want to load your app faster.
- Use local storage and database storage to keep data on the client
As we have problems with comments on our Wordpress, please leave comments via the forum or email me directly julien.vandenbossche__a-t__orange-ftgroup.com