If 2012 will be remembered for anything specific in the web development world, the debate over performance issues with localStorage will surely be high on the list. The debate began with a post by Christian Heilmann entitled, There is no simple solution for localStorage, in which he made several claims about poor localStorage performance and called for changes to the existing API or the development of an alternative API.

The problem with the article was that it didn’t have any numbers, so that set off a large number of follow-up articles taking up the task of providing numbers. John Allsopp wrote localStorage perhaps not so harmful, in which he measured the amount of time it took to read and write 10KB using localStorage. I also entered the mix with an my article, In defense of localStorage, in which I compared the read and write performance of localStorage to that of cookies (which have similar performance characteristics due to disk access). We both determined that localStorage didn’t seem slow enough to warrant throwing it away.

After catching up with Taras Glek from Mozilla (who wrote his own post on the subject, PSA: DOM localStorage considered harmful), I realized that both John’s benchmark and my own were flawed in their approach due to the way that localStorage actually works.

The key issue with localStorage is that it’s a synchronous operation that does file I/O. All of the data stored in localStorage is written to disk in order to persist across sessions. As anyone who has worked with Node.js realizes, file I/O is expensive and inconsistently so. There are any number of processes that could be accessing files at any point in time. For example, have you ever noticed how your computer slows down while an antivirus program is run? In a perfect world, there is no other process trying to access the file at the same time that you are in the read happens quickly. In the worst case, you have to wait for a lock to be released on the file before it can be read.

This introduces a problem for browsers: when should the data be read from disk? There are really only two options. First, the data could be read during page load to make sure that all subsequent read operations are fast. Of course, that would mean that localStorage would affect page load time even if it’s never used during the page lifecycle. In the perfect case, you wouldn’t notice much of a difference, but in the worst case, you could be adding milliseconds (or seconds) to the page load time.

The second approach is to wait until localStorage is accessed for the first time and then read the data from disk. This prevents any interruption of page load time but does mean that the browser will freeze when the first read happens. All of the data in the file is read into memory so each subsequent read from localStorage is fast. Likewise, writes our first stored into memory and then written to disk later so that is fast. Both Firefox and Chrome take this approach (Opera appears to as well, but I haven’t confirmed), which makes it hard to measure localStorage performance using a tool like jsPerf that never loads the page.

So the issue is clear: the time it takes for the first called to localStorage.getItem() is unpredictable. Additionally, it is a blocking call, so the browser freezes while waiting for data to be read from disk. The benchmarks that John and I used grouped together the first, slow read with all of the subsequent fast reads, so our numbers don’t really mean much. Recently, Chromium engineer William Chan did some analysis on localStorage performance measuring the first read.

Williams findings showed that reads were very fast through the 75th percentile on Windows, Mac, and Linux. In fact, it was only in the 99th percentile that the initial read took longer than a second on Windows and Linux (still less than a second on Mac). See the figure below.

William Chan's localStorage Read Performance Numbers
William Chan’s localStorage Read Performance Numbers

Taras noted in a Google+ comment that he saw a similar performance characteristics and Firefox. So it seems like Taras and William have proven that the performance issues around localStorage aren’t as dire as first thought.

Still, I decided to do some testing on my own. I measured the first read from localStorage and then subsequent reads using performance.now() if available and Date objects otherwise. Here’s what I found (on Windows 7 unless otherwise noted):

  • On Chrome, the first read takes ~1ms and subsequent reads take 0ms.
  • On Firefox, the first read takes ~0.5ms and subsequent reads take ~0.1ms.
  • On Internet Explorer 9, all reads take 0ms. I’m not sure how Internet Explorer is loading this data, but it doesn’t appear to be the same as with other browsers.
  • On Opera, first read takes ~1ms and subsequent reads take 0ms.
  • For Safari on iOS 6, the very first read takes up to 24ms and subsequent reads take 0ms. The interesting thing here is that Safari appears to keep everything in memory and never reads from disk again until the application is shut down. As long as Safari remains running, reads continue to take 0ms.

At this point, I don’t see any reason not to use localStorage on the desktop. Yes, there are some poor numbers in the 99th percentile, but there will always be outliers to the norm. On average, performance seems pretty good across desktop browsers even on that initial read.

For mobile, there’s more research needed. Clearly disk operations on a mobile device are going to be more expensive than on the desktop and you should try to limit those as much as possible. However, at least iOS is somewhat mitigating the cost by only doing it once per application session. Since most users won’t be shutting down Safari on a regular basis, you need to decide if it’s worth taking the hit for that initial read or not. If 24 ms is faster than what it would take to get the same resource from the server, then it may well be worth the hit to store that data in localStorage.

Overall, I still feel that the cries of bad localStorage performance were premature. The data that is now available indicates that performance isn’t as horrible as some of the early blog posts posited. Yes, disk I/O always has the potential to be slow, but I think this was a good example of why it’s important to get actual numbers before warning people away from what has arguably become one of the most popular HTML5 APIs. There are still a lot of sites relying on this functionality and none that have come out publicly to say that localStorage performance was a problem. I know I will still use it without worrying about performance issues, although I will definitely think twice before using it during page load.

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.

10 Responses to “Is localStorage performance a problem?”

  1. Ilya Grigorik

    Nicholas, great writeup. Glad to see Will’s findings being replicated in other browsers as well — I never did understand the “localStorage is slow” meme, so it’s great to finally put it to rest.

    Having said that, I do have a knitpick: “Clearly disk operations on a mobile device are going to be more expensive than on the desktop and you should try to limit those as much as possible.”

    There is nothing “clear” about why IO operations on mobile devices should be slow: it’s all flash. There have been researching showing that performance of various flash vendors can vary quite a bit, but that applies more to drop is flash cards than OEM installed flash, which tends to go through a much more rigorous cycle.

    The 24ms IO delay on iOS is suspicious. I’d love to get more data points from more mobile devices. To start, even just comparing Chrome and Safari on iOS.

  2. Adventskalender am 2. Dezember « F-LOG-GE

    [...] Performance Calendar ist dieses Jahr ebenfalls wieder aktiv. Gestern handelte ein Artikel von localStorage, heute geht es um “Synthetic performance [...]

  3. Andrea Giammarchi

    funny that you started saying there were no numbers in Christian post then you end up without numbers on mobile saying that Safari will have same performances than desktop version? Mobile has always been the main concern with localStorage, not Desktop browsers, IMHO, so it woul dbe nice to have real world cases with localStorage frozen/sync calls.

    Said that, the elephant in the room is that IndexedDB asks instantly with a boring modal confirmation if the browser can access disk data rather than allow at least 5Mb as it is for localStorage and/or WebDatabase through SQLite.

    Until this ultra annoying problem that forces all developers to prefer a blocking localStorage over IndexedDB I believe the debate is absolutely philosophical because IndexedDB as it is right now is a no-go while Firefox does not want to support SQLite neither does IE :-/

    So, I would say … to be continued, with more numbers on mobile, and concrete alternatives suggested by vendors.

  4. HB

    Nice write-up. Have you done similar research on writing to localStorage? I worked on an app that could potentially make a ton of writes and reads in short order and it seemed like write speeds were not as reliably fast as reads (as expected).

  5. HB

    Looking back, my comment wasn’t specific enough based on the article… That is, any way to get the actual comparable numbers for writes, jsPerf aside?

    I worked on an app that could potentially fire a ton of writes/reads across multiple tabs, and as you said disk i/o is inconsistently expensive. The project got scrapped for unrelated reasons but it would be nice to know how good or bad it is to do a lot of reads AND writes.

  6. Project Eighty Seven » Is localStorage performance a problem?

    [...] posted by stoyan @ Performance Calendar [...]

  7. Eric Elliott

    Great write-up. It dispelled some of my concerns about localStorage, and the advice about being careful about checking localStorage on page load is worth considering.

  8. 【翻译】本地存储并不简单 | 易资讯

    [...] 这篇来自Chris Heilmann的《There is no simple solution for local storage》发表以后,实际上在国外引起了相当的讨论——John Allsopp 的《localStorage perhaps not so harmful》以及 Nicholas C.Zakas 的《In defense of localStorage》,他们都在表达这样一个观点:localStorage引起的性能问题并没有那么大。年底的时候,Zakas又专门发表了《Is localStorage performance a problem?》总结了这次的讨论。(国内似乎没有什么反响?)有兴趣的话,可以看看。 [...]

  9. technology blog

    If 2012 are remembered for all the world specific within the internet development world, the controversy over performance problems with localStorage can certainly be high on the list. the controversy began with a post by Christian Heilmann entitled, there’s no straightforward answer for localStorage, during which he created many claims concerning poor localStorage performance and required changes to the present API or the event of another API.The problem with the article was that it didn’t have any numbers, so go away an oversized range of follow-up articles usurping the task of providing numbers.

  10. deju

    hi, the article is great. it need about 24ms to read the localstorage to memory, but just 4ms when i test it, so i think it’s worth it. but i have some questions about how to insert them to html(like css or js).

    i writed a mobile website, read 65kb string from the localstorage, and then insert it to the head(as style tag). the process costs about 100ms. it’s too slow. but i don’t know what the problem is?

    the program like below:
    1, dom = getElementById(‘style_id’)
    1, read from storage, give it to var str
    2, var node = createTextNode(str)
    3, dom.appendChild(node)

    we had a empty tag in .

    can you give me some suggestions?


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