Mobify Developer Blog Mobify

Smartphone Browser localStorage is up to 5x Faster than Native Cache (New Research)

As a web developer you know that creating engaging web UX means quickly delivering content that captures your visitor's attention.

The storage API, including localStorage, was designed to help web developers provide more app- like behaviour for the web than cookies previously allowed.

But it turns out you can also use localStorage to make your mobile website faster!

How much faster? Well, you can load some critical path resources such as a JavaScript that's required for your UX up to 3 - 5x faster using localStorage than from the browser's native cache. Using millions of data points from Real User Monitoring (RUM) I had the following surprising results.

Bar plot of trimmed means.
20% trimmed mean results of native browser cache vs localStorage performance. Mean performance for localStorage is always faster than the browser's native cache and for iOS 5 & 6, dramatically so.


What does this mean? It means you should absolutely be using localStorage for essential resources rather than depending on the browser's cache. This is a bold claim I'm happy to back with data, and I'm also very curious to hear from the community on your own test results. For more details on how I collected and analyzed my results, read on.

Background: the web community weighs in on localStorage

Web developers may have read some discussion in early 2012 when web storage APIs experienced a flurry of concern around performance.

The most concise summary of the developer community's performance concerns are expressed in Chris Heilmann's post on Mozilla Hacks. Chris's arguments hinge on four key criticisms of localStorage:

  • localStorage is synchronous (can block rendering)
  • localStorage performs file I/O (unbounded worst case performance)
  • Browsers load the data into memory on the first request (wastes user-agent RAM)
  • localStorage is persistent (if you never visit a site again, disk space is wasted)

These criticisms notwithstanding, localStorage remains attractive for mobile web developers for several reasons:

  • Browser native caches are shared between websites and are often small on mobile devices - as Guy Podjarny has determined, sometimes smaller than 5MB
  • Some browser caches are not persistent (contents lost when the app exits)
  • Native browser cache performance & behavior of mobile user-agents is highly variable
  • Latency on mobile is high - good caching is required for good performance
  • localStorage content eviction policy is directly under developer control, browser native cache is not

That localStorage is synchronous, performs file I/O, uses RAM & storage on user-agents is not in dispute. However, what is important is to find out what the performance is like in actual smartphone browsers executing scripts on real websites in the wild.

Experimental design

The experiment focused on the time taken to load a 25KB (uncompressed size) JavaScript payload. The content of the JavaScript payload was the Dust templating library with one small modification - after the library is loaded, a hook was executed to notify the RUM test that loading was complete so that time to load could be measured accurately. There were two experimental conditions, described below. Data collected included the user-agent, condition & the timing result.

Condition 1: browser native cache performance

The objective of condition 1 was to benchmark performance of the browser native cache on smartphones. In this condition, the JS payload is loaded twice, the first time to populate the browser cache and the second to measure timing for instantiating a script from browser cache. The payload is delivered with both a one month future EXPIRES and CACHE-CONTROL: max-age=2592000 headers set (if you're not familiar with cache control headers, or want a refresh, this is a great introduction). In this condition the content of the payload is set using the src= attribute of a script tag.

Condition 2: localStorage performance

The objective of condition 2 was to benchmark performance of localStorage on smartphones. In this condition, the JS payload is first written to localStorage after being JSON-encoded. After the payload is stored, I read back the content of localStorage and measure the time taken for the JavaScript contained in the payload to execute the callback hook. In this condition the content of the payload is inserted inside a script tag as a textnode.

Experiment validity threats

The most significant threat to the validity of this experiment is that in both conditions I am retrieving the data immediately after writing it. A subsequent test might involve reading data several days later when other browsing activity has taken place. However -- this modified experiment is unlikely to favor the native cache as it is much more likely that content will be evicted from the native cache after several days of user browsing activity. localStorage does not suffer from this eviction problem. In this respect, I believe these results understate the performance improvement available from using localStorage.

The second validity threat is that performance may vary if localStorage is fully utilized. Will Chan measured desktop localStorage performance for relatively small storage sizes - and saw very good results on desktop as well. What's interesting is that he found that performance degrades considerably as the amount of data stored in localStorage in desktop Chrome increases. More testing is required to determine the impact of a heavily utilized localStorage cache on mobile.

Results

For data analysis, I applied a 20% trimmed mean to both native browser cache and localStorage conditions discarding 10% of the lowest and highest measured results. This was done to reduce the sensitivity of the results to outliers and is considered a robust estimator.

Candlestick plot of localStorage performance results.
This candlestick plot shows the results of my performance test. For each browser type and condition, I plot the mean (red mark), the 95% confidence interval (dark gray box), and the min/max values (whiskers).


The figure above summarizes my results. As you can see the mean performance of localStorage is better than browser native cache behaviour in all cases. In many notable cases, such as iOS 5 and iOS 6, localStorage outperforms mean native cache performance by a factor of 5. Summary values are in the table below.

Smartphone OS localStorage
Mean (ms)
native browser
Mean (ms)
localstorage
StdDev
native browser
StdDev
Android 2.2 299.94 509.32 164.76 537.95
Android 2.3 133.50 154.76 57.65 215.13
Android 4.0 97.05 103.44 31.80 179.36
Android 4.1 75.60 85.57 21.60 132.03
Android 4.2 55.28 83.76 23.28 121.51
iPhone iOS5 21.61 132.90 8.64 177.69
iPhone iOS6 15.71 73.86 7.27 109.32

Variance in localStorage performance is much smaller than browser native cache variance. This can be seen by the much smaller confidence interval present in the localStorage condition. It's also readily apparent in the standard deviation column of the table above. This is especially true for Android 2.2 devices where native cache behaviour varies wildly, but the effect is present in all devices, including newer smartphones running both the iOS and Android operating systems.

On Android the minimum time (bottom whisker on the candlestick plot) measured for native cache performance beats the minimum time from localStorage. This suggests that under ideal circumstances the native cache is faster, but my real world tests suggest these ideal circumstances are the exception rather than the rule and mediocre or worst-case behavior from the native cache is common. On iOS 5 and iOS 6 the minimum load time for localStorage and native browser behaviour are nearly identical, but mean time for localStorage is significantly faster.

For completeness, I've included in the appendix the histogram data from each of the OS versions measured for both browser native cache and localStorage conditions. Features of note are described in the captions. These graphs provide more insight into the mediocre & worst-case behavior of native caches and localStorage.

Conclusion

localStorage is an attractive alternative to the mobile browser's native cache for critical page resources with much better average-case performance (2-5x better for recent OS releases) than the native cache. Because web developers have explicit control over the eviction strategy from localStorage, key resources can be preserved or updated in a more optimal way than is possible with generic native browser caching strategies.

Final caveats

There are very significant performance gains to be realized by using localStorage. Keep in mind, however, that there are also tradeoffs when using localStorage.

  • localStorage space is relatively small, 5MB on most browsers, and it can only store string data. This is effectively halved because localStorage stores strings as double-byte characters (UTF-16).
  • localStorage reads and writes do block the rendering thread. Where possible reads/writes should be done after initial page rendering is complete. You may want to avoid operations that are likely to cause performance problems such as a very large numbers of operations (thousands or tens of thousands of reads or writes), as well as read/write operations larger than 1MB.
  • Browsers should do a better job of exposing storage space used by websites taking advantage of the web storage APIs to smartphone users. Be a good neighbour and don't use localStorage recklessly, use it for key resources that are in your critical path.
  • You'll need to manage your website's cache eviction & resource updates to localStorage manually.

Your Turn

Do you use localStorage API in your work? What do you use it for and how does it perform?

Let me know by leaving a comment!

Appendix

Additional data plots are available in the appendix.

Peter McLachlan

Twitter LinkedIn

Peter’s background in HCI research and large-scale system architecture drives the evolution of Mobify’s Mobile Cloud. On sunny days, he leads workouts on Mobify’s rooftop patio.

View all posts by Peter McLachlan →

Hope that article was useful for you!

Would you like to receive more mobile web tips in your inbox, right when we publish them?

Subscribe to Mobify’s Developer Blog!

You'll be joining a community of awesome, like-minded mobile developers.

And you'll get articles full of mobile web development tips and tricks, in your inbox, right when we publish them.