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

时间:2017-06-11 06:47:45

标签: javascript while-loop do-while execution-time

while循环

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

do..while循环

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

因此whiledo..while之间的区别在于,以编程方式 In,同时,执行的测试多于

那是

如果一个循环从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');
&#13;
&#13;
&#13;

正如您所看到的on the image和代码示例一样,while循环占用了15毫秒,而do while仅占用了5毫秒。

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

测试10个元素

enter image description here

按照@pid

的建议进行更新

测试1000

enter image description here

需要23分钟进行1次额外测试

测试10000

enter image description here

一次额外测试多397.91 mS

进行测试

  

Chrome(58.0.3029.110)

     

Edge 14

2 个答案:

答案 0 :(得分:18)

编辑:我有一个答案(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');

我已将两个功能反转,时间仍然相同。 也就是说,第一个总是慢于第二个。 这证明循环没有任何意义,它完全受渲染引擎的约束。 (渲染无关紧要)

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

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

console.time('outer');
console.time('inner');
for (var i = 0; i < 10; i++);
console.timeEnd('inner');
console.timeEnd('outer');

innerouter测量值之间的差异是测量开销并且对测量本身(Heisenberg任何人?)的影响如此之大,以至于计时非常快的功能(下一步)到ms标记)容易出现测量误差。 TRUE但IRRELEVANT

尝试将代码包装在很长的周期内(例如重复1000-100000次),以减少测量的影响。 这不是个案

通过上述说明,长周期将具有微小的测量差异,但测试表明差异与的周期数一致,因此 NOT 只是一个测量开销。

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

  • 这不是whiledo..while的问题,因为颠倒两个函数的顺序并不会反转时间:第一个总是较慢的一个;
  • 这不是测量开销的问题,因为差异会扩展到宏观比例(它应该是一个变量,但数量很少 - 但事实并非如此);
  • 它与渲染无关,因为我在某些时候完全删除了它;
  • inner-outer 片段显示,通过将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');

  

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

答案 1 :(得分:0)

实际上差别很小。由于在定时代码中调用document.write(),所以会出现感知问题。以下简单代码显示do和while之间没有显着差异:

typeof this.props.children === 'undefined'

在此处试试:http://www.johnwheater.net/JAVASCRIPT/PLAY3/html/main.html