为什么for循环比小数组的循环更快,而对于更大的数组更慢?

Bre*_*den 16 javascript arrays performance

在JavaScript中,我注意到ES6 for ... of循环的性能与传统for (start; stop; step)循环有很大不同.

基准

const n = 10000;
const arr = Array(n).fill().map((e, i) => i); // [0, n)

console.log('n =', n);

let sum1 = 0;
console.time('for let i');
for (let i = 0; i < arr.length; i++) {
  sum1 += arr[i];
}
console.timeEnd('for let i');

let sum2 = 0;
console.time('for of');
for (let v of arr) {
  sum2 += v;
}
console.timeEnd('for of');
Run Code Online (Sandbox Code Playgroud)

结果

n = 10
for let i: 0.350ms
for of: 0.015ms
-----
n = 100
for let i: 0.354ms
for of: 0.023ms
-----
n = 1000
for let i: 0.429ms
for of: 0.111ms
-----
n = 10000
for let i: 1.048ms
for of: 2.138ms
-----
n = 100000
for let i: 9.452ms
for of: 13.644ms
Run Code Online (Sandbox Code Playgroud)

(使用Node.js v10.11.0测试)

如您所见,随着n增加,for-of循环的速度以比循环标准更快的速率减小.为什么for-of循环对于较小的数组更快,而对于较大的数组则更慢?

Rus*_*ell 7

在对较小的值进行基准测试时,开销操作会对测试产生更大的影响.

例如,如果变量初始化和内存分配需要0.1 ms,则n> 1000时可忽略不计,但n = 10时有效.

在这种情况下,for/of运算符允许V8引擎优化循环操作(减少上面的开销).例如,它可以将阵列项预加载到堆栈或类似物上.

for/let操作将独立于整个数组处理每个项目,并且在变量使用中更明确(减少引擎可以执行的优化量).


Kos*_*tyn 5

我建议看看微基准测试概念,并熟悉JS中微基准测试这个很好的答案.

简而言之,当测试类似于循环的小时候时,您可以轻松地让您的测试逻辑干扰其他正在进行的流程.例如,如果您在测试用例中交换执行顺序以便for of之前执行for let,您可能会注意到较小n值的令人惊讶的时间更改(扰流板:在这种情况下for let赢得比赛的n=10n=100)

所以,你的原因问题的答案:for let你的列表中的速度较慢,因为它更接近程序启动并在更"冷"的vm上执行,同时也为随后的for let声明加热.越大n,这种副作用越小,测量执行时间越短.

这就是为什么微基准测试意味着执行一系列相同的测试而不仅仅是一个测试 - 在较高规模上产生小的副作用并不显着

另外,请注意语句性能的规范测量单位是"每单位时间的总操作",而不是每单个操作的绝对时间

您可以在此处找到您主题的示例微基准标记