[翻译]localStorage性能的好坏
原文地址:Is localStorage performance a problem?
如果说2012年对于web开发世界来说有什么值得记住的事的话,关于localStorage性能的争论一定高居榜首。这场争论开始于Christian Heilmann写的一篇文章: There is no simple solution for localStorage(中文版:本地存储并不简单)。在这篇文章里,他得出了几个关于localStorage性能差的几个论断。除此之外,他还建议对现有api进行改变以及对于可选api(IndexedDB、webSQL)的优化。
但是这篇文章的读者并不多,只有很少的文章进行深入分析。John Allsopp写了一篇叫localStorage perhaps not so harmful的文章,在这篇文章里他分析了通过localStorage读写10KB的数据的时间。我也写了一篇文章来说明我的观点: localStorage无罪!(In defense of localStorage)。在这篇文章里我比较了相同条件下的localStorage和cookie(和磁盘访问读写的性能差不多)的读写性能。我和John Allsopp根据分析得出的结论都认为localStorage的性能问题并没有严重到抛弃使用它的地步。
在和Mozilla的Taras Glek(在他自己的博客上写了一篇相关主题的文章:PSA: DOM localStorage considered harmful)交流之后,我意识到自己和John Allsopp的测试方法和localStorage真正的运行方式相比是有缺陷的。
localStorage的关键问题在于它是通过同步操作的方式来进行文件I/o操作。写入localStorage的数据都会保存到磁盘上,除非主动删除数据,否则数据是永远不会过期的。用过nodeJs的人都知道,对于文件的I/O是非常昂贵和不一致的(不可信赖)。任何时间点任何的程序都可以访问文件。举例来说,你注意到过当一个杀毒软件运行的时候你的电脑是如何慢下来的吗?在理想状态下,你读取的文件不会有其他程序在同一时间访问该文件。在极端坏的情况下,如果你想读取一个文件,就必须等待文件上的锁被释放(其他程序操作文件时会锁定文件)。
这就引申出一个浏览器的问题:到底什么时候磁盘的数据才应该被读取?只有两种可能。第一种,数据可以在页面加载时就被读取,这样可以确保后面的读取快速操作。当然,这也意味着localStorage将会影响页面的加载时间,即使localStorage读取的数据并不会使用。在理想情况下,你并不会注意到这有多大不同。但在极端坏的情况下,这可能会导致页面加载时间的延长。
第二种方式是在localStorage第一次被使用(JS操作)的时候再从磁盘读取数据。这样可以阻止对于页面加载的中断,但也意味着在第一次通过localStorage访问数据的时候浏览器会中断对于页面的处理(js执行、页面渲染等)。磁盘文件的所有localStorage数据都会被写进内存以加快后面对于localStorage数据的读取速度。同样地,通过localStorage保存的数据会首先写入内存,以后再写入到磁盘文件里,以加快写的速度。firefox和chrome都使用了第二种方式(opera好像也是如此,我没有验证过)。这也导致了通过像jsPerf这样从不加载页面的工具来测量localStorage的性能是很难保证准确度的。
现在问题已经很清楚了:第一次通过localStorage.getItem()读取数据的时间是不可预测的。此外,这是一个阻塞型方法,因此浏览器会停止处理页面直到数据从磁盘中读出。后面我和John Allsopp的一起合作的测试(第一次慢读取,后面的快读取)表明localStorage也不是那么坏。最近,Chromium的工程师William Chan做了一些通过测量第一次读取时间来判断localStorage性能的分析。
William的分析结果表明在Windows, Mac, 和Linux上75百分位数(就是说75%的测验都是很快的,只有25%有点慢)的测验读取速度都很快。事实上,在Windows和Linux上,只有99百分位数(99%的测试的首次读取时间小于1s,只有1%的测试超过1s)的测试的首次读取时间超过一秒(Mac上仍旧小于1s)。如下图表所示:
注:百分位数(percentile)的概念参考百度百科http://baike.baidu.com/view/1323573.htm
William Chan’s localStorage Read Performance Numbers
Taras Glek在Google+ comment上说他也分析出firefox也有类似的性能特征。Taras Glek和William的结论都证明了localStorage的性能并不像我们一开始想的那样低下。
尽管如此,我还是自己做了一些试验。通过在高级浏览器下使用performance.now(),在不支持时使用Date对象的方式来测量localStorage的首次读取时间和后面的读取时间。下面是我的一些发现(除非特别声明,测试环境都是Windows 7):
- 在chrome下,第一次读取花费大约1ms,后面的读取花费0ms;
- 在Firefox下,第一次读取花费大约0.5ms,后面的读取花费大约0.1ms;
- 在IE9下,第一次读取和后续的读取都花费0ms。我不确定IE是如何加载这些数据的,当IE采取的方式应该和其他浏览器大不一样;
- 在opera下,第一次读取花费大约1ms,后面的读取花费0ms;
- 在IOS 6下的Safari下,第一次读取花费了整整24ms,后续的读取花费0ms。
在上面的结论中有个有趣的现象,safari好像会把所有的数据都保存在内存中,直到应用程序关闭才再次读取磁盘。只要safari保持运行,数据读取将继续只花费0ms。
基于以上结果,我没有看到在桌面电脑上不使用localStorage的任何理由。虽然99百分位数有些差的数据,但这仅仅是一些极端值。从平均数来看,localStorage的性能在所有浏览器下还是表现的很好的,即使是第一次读取的时候。
在移动设备下还需要更多更深入的研究。在移动设备上对磁盘进行操作比桌面设备更加昂贵,我们应该尽量减少对于磁盘的操作。不过,至少在IOS下这种花费通过只有在每个应用程序session中才读取一次的方式减轻了很多。由于大多数情况下用户并不会关闭safari,因此我们应该判断是否有必要花费初始化读取数据的时间。如果24ms比从服务器读取相同资源的时间要少,那么通过localStorage存储数据的性价比就会很高。
总的来说,我还是觉得对于localSorage性能差的论断有点草率。最新的数据表明localStorage的性能并不像早期有些文章写的那样让人不敢使用这项技术。磁盘I/O操作虽然一般情况下比较慢,但这是一个很好的例子表明越多的人关注和亲身测试对于一些有争论的观点对人们错误的引导有很大的抑制作用(事实胜于雄辩)。有很多网站都在使用这个api,但并没有哪家网站公开宣称localStorage存在性能问题。没有了性能上的问题,虽然在页面加载时使用localStorage需要思量再三,但我还是会尽可能的使用localStorage。
补充:在windows 8的IE10下,默认localStorage是不可访问的。如果我们直接使用localStorage的话,控制台会报Error:拒绝访问。解决方式如下:Get the Internet Explorer script error which says "Access denied error for LocalStorage"
[翻译]localStorage性能的好坏的更多相关文章
- 【官网翻译】性能篇(四)为电池寿命做优化——使用Battery Historian分析电源使用情况
前言 本文翻译自“为电池寿命做优化”系列文档中的其中一篇,用于介绍如何使用Battery Historian分析电源使用情况. 中国版官网原文地址为:https://developer.android ...
- Qualcomm_Mobile_OpenCL.pdf 翻译-8-kernel性能优化
这章将会说明一些kernel优化的小技巧. 8.1 kernel合并或者拆分 一个复杂的应用程序可能包含很多步骤.对于OpenCL的移植性和优化,可能会问需要开发有多少个kernel.这个问题很难回答 ...
- Unity性能优化(3)-官方教程Optimizing garbage collection in Unity games翻译
本文是Unity官方教程,性能优化系列的第三篇<Optimizing garbage collection in Unity games>的翻译. 相关文章: Unity性能优化(1)-官 ...
- Unity性能优化(4)-官方教程Optimizing graphics rendering in Unity games翻译
本文是Unity官方教程,性能优化系列的第四篇<Optimizing graphics rendering in Unity games>的翻译. 相关文章: Unity性能优化(1)-官 ...
- Unity性能优化(2)-官方教程Diagnosing performance problems using the Profiler window翻译
本文是Unity官方教程,性能优化系列的第二篇<Diagnosing performance problems using the Profiler window>的简单翻译. 相关文章: ...
- Unity性能优化(1)-官方教程The Profiler window翻译
本文是Unity官方教程,性能优化系列的第一篇<The Profiler window>的简单翻译. 相关文章: Unity性能优化(1)-官方教程The Profiler window翻 ...
- 最有效地优化 Microsoft SQL Server 的性能
为了最有效地优化 Microsoft SQL Server 的性能,您必须明确当情况不断变化时,性能将在哪些方面得到最大程度的改进,并集中分析这些方面.否则,在这些问题上您可能花费大量的时间和精力 ...
- AlwaysON同步性能监控的三板斧
延迟是AlwaysOn最大的敌人之一 延迟是AlwaysON的最大敌人之一.对AlwaysON而言,其首要目标就尽量减少(无法避免)主副本.辅助副本的数据延迟,实现主副本.辅助副本的“数据同步”.只有 ...
- ch6 影响 MySQLServer 性能的相关因素
第6章影响 MySQLServer 性能的相关因素 前言: 大部分人都一致认为一个数据库应用系统(这里的数据库应用系统概指所有使用数据库的系统)的性能瓶颈最容易出现在数据的操作方面,而数据库应用系统的 ...
随机推荐
- 格式化字符串format函数
自python2.6开始,新增了一种格式化字符串的函数str.format(),可谓威力十足.那么,他跟之前的%型格式化字符串相比,有什么优越的存在呢?让我们来揭开它羞答答的面纱. 语法 它通过{}和 ...
- [LeetCode] 204. Count Primes 解题思路
Count the number of prime numbers less than a non-negative number, n. 问题:找出所有小于 n 的素数. 题目很简洁,但是算法实现的 ...
- 单机使用tungsten 同步mysql数据到mongodb
[注意],当前的测试环境仅仅是一台服务器. 部署测试的tungten版本是2.1.2-xxxx; Requirements: mysql配置
- 安卓开发24:FrameLayout布局
FrameLayout布局 FrameLayout是五大布局中最简单的一个布局.FrameLayout布局中的元素会根据先后顺序重叠起来.利用FrameLayout布局元素重叠的特性,我们一般可以做一 ...
- C++ —— 类模板的分离式编译
目录 对于C++中类模板的分离式编译的认识 具体的实例 1.对于C++中类模板的分离式编译的认识 为什么C++编译器不能支持对模板的分离式编译(博文链接) 主要内容:编译器编译的一般工作原理.对模版的 ...
- SKNode类
继承自 UIResponder:NSObject 符合 NSCodingNSCopyingNSObject(NSObject) 框架 /System/Library/Frameworks/Sprit ...
- 在自己电脑上建立SVNserver
转载处:http://blog.csdn.net/shmily570/article/details/8227690 传统的Subversionserver配置方法: 一.准备工作 1.获取 Subv ...
- JAVA - hashcode与equals作用、关系
Hashcode的作用 总的来说,Java中的集合(Collection)有两类,一类是List,再有一类是Set.前者集合内的元素是有序的,元素可以重复:后者元素无序,但元素不可重复. ...
- HDU 5144 NPY and shot(三分法)
当时做这道题时一直想退出物理公式来,但是后来推到导数那一部分,由于数学不好,没有推出来那个关于Θ的最值,后来直接暴力了,很明显超时了,忘了三分法的应用,这道题又是典型的三分求最值,是个单峰曲线,下面是 ...
- 属性动画详解 Interpolator TypeEvaluator
概述 产生原因 3.0以前,android支持两种动画模式,tween animation,frame animation,在android3.0中又引入了一个新的动画系统:prope ...