won*_*ng2 233 javascript performance loops
我从书中学到了你应该写这样的循环:
for(var i=0, len=arr.length; i < len; i++){
// blah blah
}
Run Code Online (Sandbox Code Playgroud)
所以arr.length
每次都不会计算.
其他人说编译器会对此做一些优化,所以你可以写:
for(var i=0; i < arr.length; i++){
// blah blah
}
Run Code Online (Sandbox Code Playgroud)
我只是想知道哪种是最好的练习方式?
jon*_*ohn 318
用大多数现代浏览器执行此测试后......
目前,最快的循环形式(在我看来,语法最明显).
带有长度缓存的循环标准
for (var i = 0, len = myArray.length; i < len; i++) {
}
Run Code Online (Sandbox Code Playgroud)
我想说这肯定是我鼓掌JavaScript引擎开发人员的情况.应该优化运行时间以保持清晰,而不是聪明.
gnu*_*nur 87
循环遍历javascript数组的绝对最快方法是:
var len = arr.length;
while (len--) {
// blah blah
}
Run Code Online (Sandbox Code Playgroud)
有关完整比较,请参见http://blogs.oracle.com/greimer/entry/best_way_to_code_a
CGo*_*odo 36
截至2016年6月,在最新的Chrome中进行一些测试(2016年5月浏览器市场占71%,并且还在增加):
我相信这个线程太老了,误导程序员认为他们需要缓存长度,或者使用带有减量的反向遍历来实现更好的性能,编写代码比简单直接的for循环更不易读,更容易出错.因此,我建议:
如果您的应用程序迭代了很多项目,或者您的循环代码位于经常使用的函数中,那么直接的for循环就是答案:
for (var i = 0; i < arr.length; i++) {
// Do stuff with arr[i] or i
}
Run Code Online (Sandbox Code Playgroud)如果您的应用程序没有真正遍历大量项目,或者您只需要在这里和那里进行小的迭代,那么使用标准forEach回调或您选择的JS库中的任何类似函数可能更容易理解并且更不容易出错.索引变量范围已关闭,您不需要使用括号,直接访问数组值:
arr.forEach(function(value, index) {
// Do stuff with value or index
});
Run Code Online (Sandbox Code Playgroud)如果您在迭代数十亿行时确实需要花几毫秒时间,并且数组的长度不会在整个过程中发生变化,您可以考虑在for循环中缓存长度.虽然我认为现在真的没有必要:
for (var i = 0, len = arr.length; i < len; i++) {
// Do stuff with arr[i]
}
Run Code Online (Sandbox Code Playgroud)Fel*_*ing 31
如果订单不重要,我更喜欢这种风格:
for(var i = array.length; i--; )
Run Code Online (Sandbox Code Playgroud)
它可以缓存长度,写入时间要短得多.但它会以相反的顺序迭代数组.
nul*_*ube 24
它只是2018年所以更新可能会很好......
而且我真的不同意接受的答案.它在不同的浏览器上推迟.有些做得forEach
更快,有些for-loop
,while
这里有一些是所有方法http://jsben.ch/mW36e的基准
arr.forEach( a => {
// ...
}
Run Code Online (Sandbox Code Playgroud)
因为你可以看到很多for-loop for(a = 0; ... )
然后值得一提的是,没有'var'变量将被全局定义,这会极大地影响速度,所以它会变慢.
var arr = arr = new Array(11111111).fill(255);
var benches =
[ [ "empty", () => {
for(var a = 0, l = arr.length; a < l; a++);
}]
, ["for-loop", () => {
for(var a = 0, l = arr.length; a < l; ++a)
var b = arr[a] + 1;
}]
, ["for-loop++", () => {
for(var a = 0, l = arr.length; a < l; a++)
var b = arr[a] + 1;
}]
, ["for-loop - arr.length", () => {
for(var a = 0; a < arr.length; ++a )
var b = arr[a] + 1;
}]
, ["reverse for-loop", () => {
for(var a = arr.length - 1; a >= 0; --a )
var b = arr[a] + 1;
}]
,["while-loop", () => {
var a = 0, l = arr.length;
while( a < l ) {
var b = arr[a] + 1;
++a;
}
}]
, ["reverse-do-while-loop", () => {
var a = arr.length - 1; // CAREFUL
do {
var b = arr[a] + 1;
} while(a--);
}]
, ["forEach", () => {
arr.forEach( a => {
var b = a + 1;
});
}]
, ["for const..in (only 3.3%)", () => {
var ar = arr.slice(0,arr.length/33);
for( const a in ar ) {
var b = a + 1;
}
}]
, ["for let..in (only 3.3%)", () => {
var ar = arr.slice(0,arr.length/33);
for( let a in ar ) {
var b = a + 1;
}
}]
, ["for var..in (only 3.3%)", () => {
var ar = arr.slice(0,arr.length/33);
for( var a in ar ) {
var b = a + 1;
}
}]
, ["Duff's device", () => {
var i = 0;
var r = arr.length % 8;
var n = (arr.length - r) / 8;
if (r > 0) do {
var b = arr[i++] + 1;
}
while (--r);
if (n > 0) do {
var b = arr[i] + 1;
var c = arr[i+1] + 1;
var d = arr[i+2] + 1;
var e = arr[i+3] + 1;
var f = arr[i+4] + 1;
var g = arr[i+5] + 1;
var h = arr[i+6] + 1;
var k = arr[i+7] + 1;
i = --n >>> 3;
}
while (n);
}]
, ["Duff's device negative", () => {
var r = arr.length % 8;
var n = (arr.length-r) / 8; ///Math.floor(arr.length / 8);
var i = arr.length ; // -1;
while(r){
var b = arr[--i] + 1;
--r;
}
while(n){
var b = arr[i] + 1;
var c = arr[i-1] + 1;
var d = arr[i-2] + 1;
var e = arr[i-3] + 1;
var f = arr[i-4] + 1;
var g = arr[i-5] + 1;
var h = arr[i-6] + 1;
var j = arr[i-7] + 1;
i = --n >>> 3;
}
}]];
function bench(title, f) {
var t0 = performance.now();
var res = f();
return performance.now() - t0; // console.log(`${title} took ${t1-t0} msec`);
}
var globalVarTime = bench( "for-loop without 'var'", () => {
// Here if you forget to put 'var' so variables'll be global
for(a = 0, l = arr.length; a < l; ++a)
var b = arr[a] + 1;
});
var times = benches.map( function(a) {
arr = new Array(11111111).fill(255);
return [a[0], bench(...a)]
}).sort( (a,b) => a[1]-b[1] );
var max = times[times.length-1][1];
times = times.map( a => {a[2] = (a[1]/max)*100; return a; } );
var template = (title, time, n) =>
`<div>` +
`<span>${title} </span>` +
`<span style="width:${3+n/2}%"> ${Number(time.toFixed(3))}msec</span>` +
`</div>`;
var strRes = times.map( t => template(...t) ).join("\n") +
`<br><br>for-loop without 'var' ${globalVarTime} msec.`;
var $container = document.getElementById("container");
$container.innerHTML = strRes;
Run Code Online (Sandbox Code Playgroud)
body { color:#fff; background:#333; font-family:helvetica; }
body > div > div { clear:both }
body > div > div > span {
float:left;
width:43%;
margin:3px 0;
text-align:right;
}
body > div > div > span:nth-child(2) {
text-align:left;
background:darkorange;
animation:showup .37s .111s;
-webkit-animation:showup .37s .111s;
}
@keyframes showup { from { width:0; } }
@-webkit-keyframes showup { from { width:0; } }
Run Code Online (Sandbox Code Playgroud)
<div id="container"> </div>
Run Code Online (Sandbox Code Playgroud)
coc*_*cco 20
2014年While
又回来了
只是思考逻辑.
看这个
for( var index = 0 , length = array.length ; index < length ; index++ ) {
//do stuff
}
Run Code Online (Sandbox Code Playgroud)
for
环具有3个参数现在告诉我为什么这应该比以下更快:
var length = array.length;
while( --length ) { //or length--
//do stuff
}
Run Code Online (Sandbox Code Playgroud)
while
只有一个参数当Chrome 28显示for循环比while更快时,我完全感到困惑.这必须有某种程度
"呃,每个人都在使用for循环,让我们在开发chrome时专注于它."
但是现在,在2014年,while循环重新开始使用chrome.它的速度提高了2倍,在其他/旧版浏览器上它总是更快.
最近我做了一些新的测试.现在在现实世界中,那些短代码是没有价值的,而jsperf实际上无法正确执行while循环,因为它需要重新创建array.length,这也需要时间.
你不能在jsperf上获得while循环的实际速度.
你需要创建自己的自定义功能并检查 window.performance.now()
是的......没有办法让while循环更快.
真正的问题实际上是dom操纵/渲染时间/绘图时间,或者你想要调用它.
例如,我有一个画布场景,我需要计算坐标和碰撞......这是在10-200 MicroSeconds(而不是毫秒)之间完成的.它实际上需要几毫秒才能呈现所有内容.如DOM中那样.
但
loop
在某些情况下,还有另一种使用for的超级高效方式...例如复制/克隆数组
for(
var i = array.length ;
i > 0 ;
arrayCopy[ --i ] = array[ i ] // doing stuff
);
Run Code Online (Sandbox Code Playgroud)
注意参数的设置:
说,这证实了机器喜欢 -
写这篇文章我想把它缩短一点并删除一些无用的东西并用同样的风格写下这个:
for(
var i = array.length ;
i-- ;
arrayCopy[ i ] = array[ i ] // doing stuff
);
Run Code Online (Sandbox Code Playgroud)
即使它更短,看起来再使用i
一次会减慢一切.它比前一个for
循环慢了1/5 while
.
注:在;
以后的looo是非常重要的,而不{}
即使我刚刚告诉你jsperf不是测试脚本的最好方法..我在这里添加了这2个循环
http://jsperf.com/caching-array-length/40
这是关于javascript性能的另一个答案
这个答案是为了展示编写javascript的高效方法.因此,如果您无法阅读,请询问并获得答案或阅读有关javascript的书籍http://www.ecma-international.org/ecma-262/5.1/
prz*_*moc 11
http://jsperf.com/caching-array-length/60
我准备的最新版测试(通过重用旧版本)显示了一件事.
缓存长度不是那么重要,但它并没有害处.
上面链接的每个第一次测试(在新打开的选项卡上)都会在我的Debian Squeeze 64位(我的桌面硬件)中为Chrome,Opera和Firefox中的最后4个片段(图表中的第3,第5,第7和第10个)提供最佳结果).后续运行给出了完全不同的结果.
性能方面的结论很简单:
!==
而不是使用<
.shift()
数组也很有效.TL;博士
如今(2011.10)下面的模式看起来是最快的.
for (var i = 0, len = arr.length; i !== len; i++) {
...
}
Run Code Online (Sandbox Code Playgroud)
请注意,缓存arr.length
在这里并不重要,所以你可以测试i !== arr.length
并且性能不会下降,但是你会得到更短的代码.
PS:我知道在片段中shift()
它的结果可以用来代替访问第0个元素,但是我在某种程度上忽略了重用之前的修订版(它有错误的while循环),后来我不想丢失已经获得的结果.
纯粹表现中的"最佳"?或性能和可读性?
纯粹的性能"最好"是这个,它使用缓存和++前缀运算符(我的数据:http://jsperf.com/caching-array-length/189)
for (var i = 0, len = myArray.length; i < len; ++i) {
// blah blah
}
Run Code Online (Sandbox Code Playgroud)
我认为无缓存for循环是执行时间和程序员阅读时间的最佳平衡.每个以C/C++/Java开头的程序员都不会浪费ms来阅读这篇文章
for(var i=0; i < arr.length; i++){
// blah blah
}
Run Code Online (Sandbox Code Playgroud)
**缓存循环内的数组长度,几秒钟的时间将被躲避.如果数组中有更多项目,那么取决于数组中的项目,与时间的Ms*有很大的不同
**
sArr; //Array[158];
for(var i = 0 ; i <sArr.length ; i++) {
callArray(sArr[i]); //function call
}
***end: 6.875ms***
Run Code Online (Sandbox Code Playgroud)
**
**
sArr; //Array[158];
for(var i = 0,len = sArr.length ; i < len ; i++) {
callArray(sArr[i]); //function call
}
***end: 1.354ms***
Run Code Online (Sandbox Code Playgroud)
**
var el;
while (el = arr.shift()) {
el *= 2;
}
Run Code Online (Sandbox Code Playgroud)
考虑到这将消耗阵列,吃掉它,不留任何东西......
归档时间: |
|
查看次数: |
177023 次 |
最近记录: |