如何使用console.time进行微基准测试,以衡量编译器优化中的微小差异?

时间:2019-03-29 21:30:01

标签: javascript microbenchmark

此代码是this other one的改编...这是一个丑陋的代码,但问题在于“如何进行基准测试”。

  1. 新的console.time函数可测量“实际执行时间”,还是不太可靠? PS:最好使用Date.now()(或类似Unix终端time之类的外部时间参考)?
    PS:更好吗?

  2. 如何将“编译器优化”视为忽略无用的循环?

以下基准旨在衡量=====几乎相同的运营成本。问题在于每个浏览器(Firefox和Chorme)导致的平均时间不同...因此,

  1. 在优化相反时,可以使用“所有浏览器的平均时间”吗?还有另一种估算执行时间的方法吗?

在不同的浏览器中或通过NodeJ自己进行测试...请记住,它不是通常的性能(“更快吗?”),而是现实,这是一种检查编译器正在平均执行ECMA 262规定的方式。

var testString = "444442";
var testNumber = 444442;
var testString2 = "444443";
var testObject = {};
var testObject2 = {x:1};

const MAX = 1000000;
var name;
var result;

name='===';
result = 0;
console.time('Operation '+name);
for(var i = 0; i < MAX; i++){
    result += Number(
       (testString2 === testString || testNumber === testNumber) && (testObject2 === testObject || testString === testString) && (result === testNumber || testObject === testObject)
       &&      (testString2 === testString || testNumber === testNumber) && (testObject2 === testObject || testString === testString) && (result === testNumber || testObject === testObject)
       &&      (testString2 === testString || testNumber === testNumber) && (testObject2 === testObject || testString === testString) && (result === testNumber || testObject === testObject)
       &&      (testString2 === testString || testNumber === testNumber) && (testObject2 === testObject || testString === testString) && (result === testNumber || testObject === testObject)
       &&      (testString2 === testString || testNumber === testNumber) && (testObject2 === testObject || testString === testString) && (result === testNumber || testObject === testObject)
       &&      (testString2 === testString || testNumber === testNumber) && (testObject2 === testObject || testString === testString) && (result === testNumber || testObject === testObject)
       &&      (testString2 === testString || testNumber === testNumber) && (testObject2 === testObject || testString === testString) && (result === testNumber || testObject === testObject)
       &&      (testString2 === testString || testNumber === testNumber) && (testObject2 === testObject || testString === testString) && (result === testNumber || testObject === testObject)
       &&      (testString2 === testString || testNumber === testNumber) && (testObject2 === testObject || testString === testString) && (result === testNumber || testObject === testObject)
       &&      (testString2 === testString || testNumber === testNumber) && (testObject2 === testObject || testString === testString) && (result === testNumber || testObject === testObject)
      )
      testNumber++
}
console.timeEnd('Operation '+name);

var result0 = result;

name='=='
result = 0;
console.time('Operation '+name);
var result = null;
for(var i = 0; i < MAX; i++){
  result += Number(
    (testString2 == testString || testNumber == testNumber) && (testObject2 == testObject || testString == testString) && (result == testNumber || testObject == testObject)
    &&      (testString2 == testString || testNumber == testNumber) && (testObject2 == testObject || testString == testString) && (result == testNumber || testObject == testObject)
    &&      (testString2 == testString || testNumber == testNumber) && (testObject2 == testObject || testString == testString) && (result == testNumber || testObject == testObject)
    &&      (testString2 == testString || testNumber == testNumber) && (testObject2 == testObject || testString == testString) && (result == testNumber || testObject == testObject)
    &&      (testString2 == testString || testNumber == testNumber) && (testObject2 == testObject || testString == testString) && (result == testNumber || testObject == testObject)
    &&      (testString2 == testString || testNumber == testNumber) && (testObject2 == testObject || testString == testString) && (result == testNumber || testObject == testObject)
    &&      (testString2 == testString || testNumber == testNumber) && (testObject2 == testObject || testString == testString) && (result == testNumber || testObject == testObject)
    &&      (testString2 == testString || testNumber == testNumber) && (testObject2 == testObject || testString == testString) && (result == testNumber || testObject == testObject)
    &&      (testString2 == testString || testNumber == testNumber) && (testObject2 == testObject || testString == testString) && (result == testNumber || testObject == testObject)
    &&      (testString2 == testString || testNumber == testNumber) && (testObject2 == testObject || testString == testString) && (result == testNumber || testObject == testObject)
  )
}
console.timeEnd('Operation '+name);

if (result0 != result)
console.log("OOPS BUG, result0 differing result: ", result0, result)

name='NoOp'
result = 0;
console.time('Operation '+name);
for(var i = 0; i < MAX; i++){
    result =  true && true && true &&
    true && true && true &&
    true && true && true &&
    true && true && true &&
    true && true && true &&
    true && true && true &&
    true && true && true &&
    true && true && true &&
    true && true && true &&
    true && true && true &&
    true && true && true &&
    true && true && true &&
    true && true && true &&
    true && true && true &&
    true && true && true &&
    true && true && true &&
    true && true && true &&
    true && true && true &&
    true && true && true &&
    true && true && true
}
console.timeEnd('Operation '+name);

采样结果(切零毫秒)

在Firefox上:

操作===:80毫秒 操作==:200毫秒 NoOp操作:8毫秒

在Chrome上:

操作===:21毫秒 操作==:27毫秒 NoOp操作:22毫秒

在NodeJS上:

操作===:108毫秒 操作==:152毫秒 NoOp操作:9毫秒

结论:===在所有编译器中都快一点。


问题:运行this answer(“ Rick测试”)的其他引用代码,

在Firefox上:

操作===:1089 u 操作==:280 u NoOp操作:281 u

在Chrome上:

操作===:352 u 操作==:349 u NoOp操作:349 u

在NodeJS上:

操作===:201 u 操作==:387 u NoOp操作:195 u

结论:==(不是===)在浏览器中速度更快,但在Node中则相反。


最终结论:即使使用更多循环等,基准结果也无法收敛。似乎Rick的测试经过了优化(在编译器上进行了更改),而上面的则没有。

最终结论:即使使用更多循环等,基准结果也不会收敛。似乎Rick的测试受到(依赖于编译器的)优化的影响,而上述测试(在此页中)则不受此限制。

PS:当然,理想情况下(根据规范),在比较相等的数据类型时,运算符=====具有相同的时间,因此很难测量差异...但这是问题,我想用console.time来检查一下这个小区别。

0 个答案:

没有答案