Web Storage has quickly become one of the most popular HTML5-related additions to the web developer toolkit. More specifically, localStorage has found a home in the hearts and minds of web developers everywhere, providing very quick and easy client-side data storage that persists across sessions. With a simple key-value interface, we’ve seen sites take advantage of localStorage in unique and interesting ways:

  • Disqus, the popular feedback management system, uses localStorage to save your comment as you type. So if something horrible happens, you can fire back up the browser and pick up where you left off.
  • Google and Bing store JavaScript and CSS in localStorage to improve their mobile site performance (more info).

Of the use cases I’ve seen, the Google/Bing approach is one that seems to be gaining in popularity. This is partly due to the difficulties of working with the HTML5 application cache and partly due to the publicity that this technique has gained from the work of Steve Souders and others. Indeed, the more I talk to people about localStorage and how useful it can be for storing UI-related information, the more people I find who have already started to experiment with this technique.

What I find intriguing about this use of localStorage is that there’s a built-in, and yet unstated, assumption: that reading from localStorage is an inexpensive operation. I had heard anecdotally from other developers about strange performance issues, and so I set out to quantify the performance characteristics of localStorage, to determine the actual cost of reading data.

The Benchmark

Not too long ago, I created and shared a simple benchmark that measured reading a value from localStorage against reading a value from an object property. Several others tweaked the benchmark to arrive at a more reliable version. The end result: reading from localStorage is orders of magnitude slower in every browser than reading the same data from an object property. Exactly how much slower? Take a look at the following chart (higher numbers are better).

Chart comparing reading from an object to reading from localStorage

You may be confused after looking at this chart because it appears that reading from localStorage isn’t represented. In fact, it is represented, you just can’t see it because the numbers are so low as to not even be visible with this scale. With the exception of Safari 5, whose localStorage readings actually show up, every other browser has such a large difference that there’s no way to see it on this chart. When I adjust the Y-axis values, you can now see how the measurements stack up across browsers:

Chart comparing reading from an object to reading from localStorage

By changing the scale of the Y-axis, you’re now able to see a true comparison of localStorage< versus object property reads. But still, the difference between the two is so vast that it's almost comical. Why?

What's Going On?

In order to persist across browser sessions, values in localStorage are written to disk. That means when you're reading a value from localStorage, you're actually reading some bytes from the hard drive. Reading from and writing to a hard drive are expensive operations, especially as compared reading from and writing to memory. In essence, that's exactly what my benchmark was testing: the speed of reading a value from memory (object property) compared to reading a value from disk (localStorage).

Making matters more interesting is the fact that localStorage data is stored per-origin, which means that it's possible for two or more tabs in a browser to be accessing the same localStorage data at the same time. This is a big pain for browser implementors who need to figure out how to synchronize access across tabs. When you attempt to read from localStorage, the browser needs to stop and see if any other tab is accessing the same area first. If so, it must wait until the access is finished before the value can be read.

So the delay associated with reading from localStorage is variable - it depends a lot on what else is going on with the browser at that point in time.

Optimization Strategy

Given that there is a cost to reading from localStorage, how does that affect how you would use it? Before coming to a conclusion, I ran another benchmark to determine the effect of reading different size pieces of data from localStorage. The benchmarks saves four different size strings, 100 characters, 500 characters, 1000 characters, and 2000 characters, into localStorage and then reads them out. The results were a little surprising: across all browsers, the amount of data being read did not affect how quickly the read happened.

I ran the test multiple times and implored my Twitter followers to get more information. To be certain, there were definitely a few variances across browsers, but none that were large enough that it really makes a difference. My conclusion: it doesn't matter how much data you read from a single localStorage key.

I followed up with another benchmark to test my new conclusion that it's better to do as few reads as possible. The results correlated with the earlier benchmark in that reading 100 characters 10 times was around 90% slower across most browsers than reading 10000 characters one time.

Given that, the best strategy for reading data from localStorage is to use as few keys as possible to store as much data as possible. Since it takes the roughly same amount of time to read 10 characters as it does to read 2000 characters, try to put as much data as possible into a single value. You're getting hit each time you call getItem() (or read from a localStorage property), so make sure that you're getting the most out of the expense. The faster you get data into memory, either a variable or an object property, the faster all subsequent actions.

ABOUT THE AUTHOR
Nicholas Zakas photo Nicholas C. Zakas (@slicknet) is a front-end consultant, author, and speaker. He worked at Yahoo! for almost five years, where he was front-end tech lead for the Yahoo! homepage and a contributor to the YUI library. He is the author of Professional JavaScript for Web Developers (Wrox, 2012), Professional Ajax (Wrox, 2007), and High Performance JavaScript (O'Reilly, 2010). Nicholas is a strong advocate for development best practices including progressive enhancement, accessibility, performance, scalability, and maintainability. He blogs regularly at http://www.nczonline.net/ and can be found on Twitter via @slicknet.

26 Responses to “localStorage Read Performance”

  1. localStorage Read Performance « Raanan Avidor

    [...] this article http://calendar.perfplanet.com/2011/localstorage-read-performance/ by stoyan, published on December 02, 2011 at 07:29AM. Share this:StumbleUponDiggRedditLike [...]

  2. Philip Tellis

    There’s an optimisation that browser authors could make. When a page is opened, simply load all localStorage for that origin into memory in parallel. They can also use a single in-memory copy across tabs and just implement copy-on-write or lock-on-write followed by an async disk sync.

  3. Jake Archibald

    Interesting findings, but you suggest that localStorage may be slower than HTTP but don’t return to that with any data. How does localStorage compare to reading data from a far-future cached file? As in, is there a benefit to caching js via localStorage?

  4. Lennie

    For those that are confused about: how this is not comparing localStorage with getting your data from remote ?

    I think Nicholas means you could send the data along with the first response, the HTML-page, and have fresh data that way.

  5. Nicholas C. Zakas

    @Philip – Considering that localStorage can hold up to 5MB of data, that’s probably not a good general rule. Plus, subsequent reads post-load would result in disk access anyway, since you can’t be certain that other tabs haven’t changed the data.

    @Jake – Yes, bad editing on my part (I thought I had removed those references during the final edit). Initially I was going to do a comparison to HTTP requests and just ran out of time. I’ll be looking into that next, so keep your eyes peeled for a follow up!

  6. Paul Sayre

    There seems to be a corollary between IE8 implementing Web Storage and JSON support at the same time. You say there is little difference between small strings and large. Since Web Storage is generally used in conjunction with JSON encoding, what kinda of performance differences do you see when encoding and storing a large and small object?

  7. Stoyan

    @Jake, @Nicholas – and sorry for the sensationalist blurb and tweet on my part :)

  8. Philip Tellis

    It may be a bad idea on mobile, but on the desktop, 5MB is far smaller than the total RAM available on the system, and in fact the total RAM currently used by the browser.

    Regarding subsequent reads, they don’t need to go to disk either, since all tabs could share the same in-memory copy of localStorage. You’d need to write to disk on an update, but you do not need to re-read from disk.

  9. Wim Leers

    I don’t think this is good benchmark. You’re comparing reads per second (I presume, because you failed to include legends for the charts). That’s not the typical use case. Typically, we need to retrieve a value once per page load.

    I think you should have listed the average/mean latency to access data in localStorage, and compared that with average/mean latencies to servers around the world. That is the more common use case, at least in a WPO context.

    In your introduction, you said:

    What I find intriguing about this use of localStorage is that there’s a built-in, and yet unstated, assumption: that reading from localStorage is less expensive than making an HTTP request. After all, it wouldn’t make sense to read data locally if you could get fresh, updated data remotely for the same cost.

    Yet that’s not what you’ve compared here!

  10. Pomeh

    Thanks for this article Nicholas. There is plenty of useful information in there :)

    However, as some other people have pointed out, with those benchmark, we can’t say that localStorage is slower or faster than HTTP request. Your first benchmark result says that “reading from localStorage is [..] slower [..] than reading [..] from an object property”. But this doesn’t include the cost of the actual HTTP request or whatever you need to bring that “object” to the client side. I’m pretty sure the conclusion would be the same with that comparison but actually we don’t have any data to prove it, so I’ll let you the time to finish that.

    Cheers

  11. Joe Developer

    Sorry Nicholas, but this is pretty unsurprising and seems to miss the point.

    Did you think that localStorage was memory based?

    Operations per second isn’t the measure you are looking for, it is ms per request, contrasted with http requests and compared with a webworker transport as a bonus.

    That said, spelling out the desirability of ‘big lumps’ of data in this context is useful.

  12. Rick Waldron

    @Jake – your mention of web worker “transport” caught my eye, I’m assuming you’re referring to XMLHttpRequest made from within a worker thread? I’m interested in understanding more about the approach you have in mind.

  13. Rick Waldron

    Haha, I’m writing from my phone as I follow my girlfriend around while she Christmas shops… I meant @Joe Developer. Whoops! Please forgive :)

  14. Kyle Simpson

    It’s also important to emphasize that because localStorage (and sessionStorage) are both synchronous API’s, they cause fits for brower implementers that have to deal with multi-process communication, which further reduces the performance. It also leads to many weird quirks (such as what’s mentioned above), because there’s no defined behavior for how to resolve “conflicts” between two different processes accessing the same localStorage container at the same time.

    An asynchronous API would have helped reduce the difficulty of communication between multiple processes (increasing performance a little bit), but it would have come at the cost of more complexity for the author. Sad tradeoff. Would be nice if JS would finally adopt a sane language-level construct for async manipulation.

  15. Rounded Corners 310 – Gangster /by @assaf

    [...] reading Nicholas Zakas investigates localStorage read performance and finds a lot more disk I/O than you’d [...]

  16. GDR!

    You start by comparing localStorage to a network round-trip and and comparing localStorage to in-memory object properties. This makes no sense to me.

  17. Marcel Duran

    Is sessionStorage also fetched/written in disk? Any benchmarks comparing sessionStorage vs localStorage vs in-memory-object timings?

  18. Lennie

    Yes, I also missed a comparison with sessionStorage. :-/ I wouldn’t expect it to need the disk.

  19. sexyprout

    Totally agree with Tim and GDR, looks like the guy doesn’t know shit about what he’s talking about…

  20. Frank M

    Wow… @sexyprout, harsh words, don’t you think?! Take the article with a grain of salt. Nicholas may not have provided info on the comparison vs. HTTP, but give credit where it’s due.

    NCZ is considered, in my books and I’m sure in many others’, one of the fore-runners of JS development and performance optimization, so if there _is_ someone who knows what he’s talking about, Nicholas is one of them.

    Nicholas: Thanks for the info about the size of data being stored not having an affect of read performance.

  21. Performance Calendar » Mobile UI performance considerations

    [...] data out of localStorage is a performance hit. When it comes to mobile, however, it is less of a hit than latency, especially latency with [...]

  22. HTML5 localStorage « nelsonslog

    [...] some performance notes here and here confirm it’s not just me seeing bad performance. One issue is that localStorage [...]

  23. Paul Maneesilasan

    Good article NCZ, as always, thanks for your knowledge contrib ;)

    To be honest though, your findings are a bit intuitive. Disk read vs memory access… Orders of magnitude different…

    My biggest issues are with 1) storing everything as strings, and 2) while a JSON style interface is nice for basic things, having a SQL-like interface would be great. Sounds like I want a DB right?

    What I’m really waiting for is indexeddb, and am surprised Safari and Opera are so slow to adopt (IE doesn’t surprise me : )

    In all though, localstorage is just as it’s name reads, and it does what it says :) For now, I’m doing my best to resist writing a DB-like wrapper around it :p

    Cheers,
    Paul

  24. Focus sur le client-side storage | Atol Conseils & Développements

    […] La récupération des données est synchrone, et plus le volume de données stockées est important, plus la récupération d’une entrée prend du temps. Cela est d’autant plus à prendre en compte lors de développement d’application pour smartphone, qui ne dispose pas de la puissance des machines de bureau. (Voir localStorage read performance[EN]) […]

  25. Measuring localStorage Performance | High Performance Web Sites

    […] 2011 & 2012, Nicholas Zakas wrote three blog posts about the performance of localStorage. In the last one, The performance of localStorage […]

  26. 7 Speed reading review

    t it amazing how much clearer this passage becomes simply by adding a single schematically significant word.
    The information you need can be found at Here
    you will videos, articles, webinars, and programs designed with your brain learning in mind.
    One of the most exciting and, yet, perhaps worrying aspects of computer technology,
    is the Internet.

Leave a Reply

You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>
And here's a tool to convert HTML entities