为什么while和do ...之间的巨大时差在JavaScript中

Sag*_*r V 8 javascript while-loop execution-time do-while

while循环

测试条件,如果是,则执行代码

do..while循环

第一次执行.然后测试并执行.

所以之间的差异while,并do..while进行,程序在同时,一个试验进行比同时做多

那是

如果一个循环从1到50在while一个语句的循环中执行,它将有51个测试(50个真和1个假),语句将执行50次.

同样

如果一个循环从1到50在do..while循环中执行一个语句,它将有50个测试(第一个测试将不会执行),语句将执行50次.

所以,只有一个测试/检查少.而已.

但是当我测试执行所花费的时间时,它显示出很大的差异.

function whileFn() {
  var i = 0;
  while (i < 10) {
    document.write(i);
    i++;
  }
}

function doWhileFn() {
  var i = 0;
  do {
    document.write(i);
    i++;
  } while (i < 10)
}

console.time('whileFn');
whileFn();
console.timeEnd('whileFn');

document.write('<br/>');

console.time('doWhileFn');
doWhileFn();
console.timeEnd('doWhileFn');
Run Code Online (Sandbox Code Playgroud)

正如您在图像和代码示例中看到的那样,while循环花费do while了15毫秒,而只花了5毫秒.

这种巨大差异背后的原因是什么?

测试10个元素

在此输入图像描述

按照@pid的建议更新

测试1000

在此输入图像描述

需要23mS进行1次额外测试

测试10000

在此输入图像描述

一次额外测试多397.91 mS

进行测试

Chrome(58.0.3029.110)

边缘14

pid*_*pid 19

编辑:我有一个答案(TL; DR:跳到最后)

我自己做了一些测试.

function whileFn() {
  var i = 0;
  while (i < 10) {
    document.write(i);
    i++;
  }
}

function doWhileFn() {
  var i = 0;
  do {
    document.write(i);
    i++;
  } while (i < 10)
}


console.time('doWhileFn');
doWhileFn();
console.timeEnd('doWhileFn');

document.write('<br/>');

console.time('whileFn');
whileFn();
console.timeEnd('whileFn');
Run Code Online (Sandbox Code Playgroud)

我已经颠倒了这两个函数,时间仍然是一样的.也就是说,第一个总是比第二个慢.这证明循环没有任何意义,它完全受渲染引擎的约束.(渲染无关紧要)

如果你document.write()完全删除,差异就会减少更多. (无关)

要正确测量时间,您必须考虑时间本身的测量,实际上这显示了测量时间的开销:

console.time('outer');
console.time('inner');
for (var i = 0; i < 10; i++);
console.timeEnd('inner');
console.timeEnd('outer');
Run Code Online (Sandbox Code Playgroud)

inner和outer测量之间的差异是测量开销和对测量本身的影响(Heisenberg任何人?),以至于定时非常快的功能(在ms标记旁边)容易出现测量误差.真实但不相同

尝试将代码包装在很长的周期内(例如重复1000-100000次)以减少测量的影响. 这证明不是这种情况

通过上面的语句长周期将有一个微小的测量差异,但试验表明,区别尺度与周期数,这样是不是只是一个测量成本.

要回顾迄今为止的调查结果:

  • 它不是一个问题while和do..while,因为反相的两个函数的顺序不反转的定时:第一始终是较慢的一个;
  • 这不是测量开销的问题,因为差异会扩展到宏观比例(它应该是一个变量,但数量很少 - 但事实并非如此);
  • 它不是关于渲染,因为我在某些时候完全删除了它;
  • 的内外片段显示长周期具有通过更换一个微小的测量开销10与大量,但是这是不适合的问题的原码的情况下-在这里所不同的是成比例的周期数.

编辑:结论

这是一项交替测试.再次测量A,B,A,再次测量B,最后再测量A:向前移动越多,它收敛得越多.

证明:

function whileFn() {
  var i = 0;
  while (i < 10) {
    document.write(i);
    i++;
  }
}

function doWhileFn() {
  var i = 0;
  do {
    document.write(i);
    i++;
  } while (i < 10)
}


console.time('doWhileFn');
doWhileFn();
console.timeEnd('doWhileFn');

document.write('<br/>');

console.time('whileFn');
whileFn();
console.timeEnd('whileFn');

document.write('<br/>');

console.time('doWhileFn');
doWhileFn();
console.timeEnd('doWhileFn');

document.write('<br/>');

console.time('whileFn');
whileFn();
console.timeEnd('whileFn');

document.write('<br/>');

console.time('doWhileFn');
doWhileFn();
console.timeEnd('doWhileFn');
Run Code Online (Sandbox Code Playgroud)

说明: JS引擎在运行时将源JS编译为本机代码.它具有逐步的性能扩展,但它只能在它返回后编译一个函数.这意味着该功能在较长时间内被编译并逐步优化.事实上,这是V8的众所周知的特征.由于这种边缘条件(初始测量是不准确的),在AB情景中测量的内容不具有代表性.ABABA情景显示A和B 随时间收敛,并且当测量远离边缘(初始)条件时测量结果.