缓存 Array.length 是老生常谈的小优化
问题
缓存 Array.length
是老生常谈的小优化。
// 不缓存
for (var i = 0; i < arr.length; i++) {
...
}
// 缓存
var len = arr.length;
for (var i = 0; i < len; i++) {
...
}
// 或者
for (var i = 0, len = arr.length; i < len; i++) {
...
}
但以前写过 Java 的笔者一直对这种破碎的写法感到不适,也对这种写法的实际优化效果产生疑问。
且推崇这种写法的朋友似乎很多也是“前辈这么说+自己想了一下觉得有道理”。
由于 for 循环搭配 Array.length
是极度常用的 JavasScript 代码,所以还是有必要搞清楚的。
结论
经过一番摸索后笔者得到的结论是:缓存 Array.lengh
对优化的影响没有想象中的大,甚至可能会有所减慢。
理由
从测试结果上看
stackoverflow 上也有这个讨论,For-loop performance: storing array length in a variable 。
accepted 的答案是说缓存会起到加速的结果,给出了 jsPerf 测试。
但是有答案反对,也给出了 jsPerf 测试。
两个答案的区别在于“循环不变量代码移动(Loop-invariant code motion)”,accepted 答案的测试循环里没有访问到数组,是不实际的,后面会讲到。
从另一篇文章 Shoud I have to cache my array’s length? 的测试结果也可以看出缓存差别不大。
还有这篇 JavaScript's .length Property is a Stored Value
从 V8 的中间代码分析
这篇文章 How the Grinch stole array.length access 从 V8 的 hydrogen 探讨 Array.length
在 for 循环中的处理。
正如上面提到的“循环不变量代码移动”,V8 引擎会聪明的把能确定不变的代码移到循环外。
所以像下面这种代码也不会影响引擎对 Array.length
的优化:
function uncached(arr) {
for (var i = 0; i < arr.length; i++) {
arr[i]
}
}
而当在循环中调用函数时,V8 会尝试将函数进行内联,从而继续进行“循环不变量代码移动”优化。
但当函数不可内联时,V8 就没辙了,每次循环都要重新计算一遍 length
function BLACKHOLE(sum, arr) {
try { } catch (e) { }
}
function uncached(arr) {
var sum = 0;
for (var i = 0; i < arr.length; i++) {
sum += arr[i];
if (sum < 0) BLACKHOLE(arr, sum);
}
return sum;
}
但这时即便是在循环外缓存了 length
也是没有用的,引擎没法预判数组的变化,当需要访问数组元素时会触发 bounds check ,从而照样要计算一遍 length
。所以缓存 length
是没有用的。
甚至,由于多了一个变量,底层的寄存器分配器每次循环还要多一次恢复这个变量。当然这个只有在大规模的情况下才会看出区别。
结尾
当然这篇文章也有局限性,仅仅讨论了 V8 引擎,也没有讨论访问 length
代价更高的 HTMLCollection
。但这已经足够说明两者差别不大,一般情况下我们不用再局限于缓存的写法,可以放开来按照自己喜欢的方式去写循环了。
【完】
原文:http://div.io/topic/966
缓存 Array.length 是老生常谈的小优化的更多相关文章
- check the element in the array occurs more than half of the array length
Learn this from stackflow. public class test { public static void main(String[] args) throws IOExcep ...
- [Bug]The maximum array length quota (16384) has been exceeded while reading XML data.
写在前面 在项目中,有客户反应无法正常加载组织结构树,弄了一个测试的程序,在日志中查看到如下信息: Error in deserializing body of reply message for o ...
- SPFA 小优化*2
/* bzoj 2763 SPFA小优化 循环队列+SLF 顺面改掉自己之前手打qeueu的坏毛病*/ #include<iostream> #include<cstring> ...
- Array.length vs Array.prototype.length
I found that both the Array Object and Array.prototype have the length property. I am confused on us ...
- 【转】The magic behind array length property
Developer deals with arrays every day. Being a collection, an important property to query is the num ...
- [MySQL5.6] 最近对group commit的小优化
[MySQL5.6] 最近对group commit的小优化 http://www.tuicool.com/articles/rEZr2q 最近花了一些时间在做MySQL Group Commit的优 ...
- Count and Say (Array Length Encoding) -- LeetCode
The count-and-say sequence is the sequence of integers beginning as follows:1, 11, 21, 1211, 111221, ...
- SPFA的小优化
标签:闲扯 SPFA的小优化 1. 向队尾加入元素时,如果它比对首还优,就把把它直接和队首交换. 拿一个双端队列来实现 (手写 , head ,tail STLdeque亲测及其慢) 这个小优化其 ...
- Math.floor(Math.random() * array.length),splice
1.Math.floor(Math.random() * array.length) 返回长度内的索引 eg: changeLimit () { function getArrayItems(arr, ...
随机推荐
- windows下搭建及配置mantis缺陷管理工具
在windows XP 操作系统下,如何更快.更容易地搭建及配置mantis缺陷管理工具呢?以下是我实践的具体步骤: 一.安装mantis的前提环境,需要先安装Apache HTTP Server2. ...
- 【巧妙算法系列】【UVA 11384】 Help is needed for Dexter 正整数序列
Help is needed for Dexter Time Limit: 3 Second Dexter is tired of Dee Dee. So he decided to keep Dee ...
- 【贪心+中位数】【新生赛3 1007题】 Problem G (K)
Problem G Time Limit : 4000/2000ms (Java/Other) Memory Limit : 32768/32768K (Java/Other) Total Sub ...
- putty保持连接不自动段开
经常在网上看到有人说自己利用putty工具登录服务器总是连接不上,这样的情况自己在刚接触putty时也遇到过.在 Connection 里面有个 Seconds between keepaliaves ...
- canvas模糊事件处理
不知道大家项目中有没有用到canvas时还有时候会出现模糊的情况: 具体推测可能是屏幕改变了,然而canvas的渲染对象并没有跟着一起变: 这里简单介绍个对象,window.devicePixelRa ...
- Java中使用webservice,简化开发(xfire的webservice)
首先,使用到的jar先导入项目中, xbean-spring-2.8.jar, wsdl4j-1.6.1.jar, commons-httpclient-3.0.jar, commons-codec- ...
- 设置Proxy Server和SQL Server实现互联网上的数据库安全
◆首先,我们需要了解一下SQL Server在WinSock上定义协议的步骤: 1. 在”启动”菜单上,指向”程序/Microsoft Proxy Server”,然后点击”Microsoft Man ...
- 对获取config文件的appSettings节点简单封装
转:http://www.cnblogs.com/marvin/archive/2011/07/29/EfficiencyAppSetting.html C#的开发中,无论你是winform开发还是w ...
- Hadoop配置文件-mapred-site.xml
name value Description hadoop.job.history.location job历史文件保存路径,无可配置参数,也不用写在配置文件里,默认在logs的history文件 ...
- Python第一印象,大法好!
为了用flask开发web应用,这两天就开始看了一点点Python.还没看到用Python写网站后台的那部分,就被其强大的数据处理能力和语法的灵活性吸引.肯定是我少见多怪,不过看到人家灵活使用Pyth ...