我写了一个小脚本来按执行时间比较函数的实现。例如,它运行一个functon函数1e6次,并对每个调用的执行时间求和。我不知道应该将performance.now()
调用放在什么位置。第一种选择是在函数调用之前和之后将它们放入for
循环中,然后在每次迭代后仅对结果求和。第二种选择是将performance.now()
调用放在循环本身之前和之后。第一种情况感觉更准确,但在我的机器上,最终结果稳定地比第二种情况大30%。有人可以向我解释为什么吗? performance.now()
的正确位置是什么?
第一个选项-performance.now()
在循环内调用。在我的计算机上计算150个1e6的阶乘大约需要1300毫秒:
function factorial(x) {
return x === 1 ? 1 : x * factorial(x - 1);
}
function measure(func, arg, times) {
let timeSpent = 0;
for(var i = times;i--;) {
let t1 = performance.now();
func(arg);
let t2 = performance.now();
timeSpent += t2 - t1;
}
console.log(`Tested function ${func.name} has been executed ${times} times with argument ${arg} and it has taken %d ms. in total.`, timeSpent);
}
measure(factorial, 150, 1e6);
第二个选项-performance.now()
在循环之外调用。在我的计算机上计算150个1e6的阶乘大约需要1000毫秒:
function factorial(x) {
return x === 1 ? 1 : x * factorial(x - 1);
}
function measure(func, arg, times) {
let t1 = performance.now();
for(var i = times;i--;) func(arg);
let t2 = performance.now();
console.log(`Tested function ${func.name} has been executed ${times} times with argument ${arg} and it has taken %d ms. in total.`, t2 - t1);
}
measure(factorial, 150, 1e6);
答案 0 :(得分:0)
进行性能评估时,我会考虑以下几点:
我正在使用的 time 服务的准确性是什么,它返回的是“壁钟时间”还是“ cpu时间”
我需要从测量中获得什么精度(1%、. 1%,10%?)
我想花多少时间进行性能测试?
在进行评估之前我是否需要“热身时间”(例如,如果我正在评估事务运行所需的时间,并且我使用的是Java或javascript之类的JITted语言,那么我可能想放弃前N个结果的时间。另一方面,如果我正在测量一个“批处理”程序-某个程序只运行一次-则不需要这样做。
通常,时间服务的精度介于数百微秒到几毫秒之间。所以-您想确保自己在所测量的内容周围进行足够的循环,以免您担心时间功能引起麻烦。因此,如果我有一个精确到(例如)100us的计时器,那么我将确保我运行了足够多的循环,以花费至少1000us(1ms)甚至10ms。
在进行性能测量时,还有很多原因会导致抖动。抖动是您在进行性能测量时在实践中不可避免的可变性。所以-我还要重复执行几次性能测试,并查看这些测试的均值,标准差,以查看结果的一致性(这也有助于阐明JIT编译器之类的东西,因为当您查看时会发现一些非常离群的异常值根据您的结果)。
要真正回答您的问题,我将选择您的第二个选择。您想确保已完成足够的工作,以确保时间服务的准确性不成问题。