如下面的代码所示,当我增加字符串的大小时,它导致0毫秒的差异。而且,随着字符串数的增加,会出现不一致的情况。
我在这里做错什么了吗?
let stringIn = document.getElementById('str');
let button = document.querySelector('button');
button.addEventListener('click', () => {
let t1 = performance.now();
functionToTest(stringIn.value);
let t2 = performance.now();
console.log(`time taken is ${t2 - t1}`);
});
function functionToTest(str) {
let total = 0;
for(i of str) {
total ++;
}
return total;
}
<input id="str">
<button type="button">Test string</button>
我也尝试使用await
,但是结果是相同的(请参见下面的代码段)。包含下面代码的函数是async
:
let stringArr = this.inputString.split(' ');
let longest = '';
const t1 = performance.now();
let length = await new Promise(resolve => {
stringArr.map((item, i) => {
longest = longest.length < item.length ? longest : item;
i === stringArr.length - 1 ? resolve(longest) : '';
});
});
const diff = performance.now() - t1;
console.log(diff);
this.result = `The time taken in mili seconds is ${diff}`;
我也尝试过this answer as,但这也不一致。
作为一种解决方法,我尝试使用console.time
功能,但是它不允许渲染时间,而且也不准确。
更新:我想构建一个类似于jsPerf的界面,该界面与之非常相似,但用途不同。通常,我想比较取决于用户输入的不同功能。
答案 0 :(得分:4)
有3件事可以帮助您了解正在发生的事情:
浏览器会降低performance.now()
的精度以防止Meltdown和Spectre攻击,因此Chrome可以提供最高0.1 ms的精度,FF 1ms等。这使得无法测量较小的时间范围。如果功能非常快-0
毫秒是可以理解的结果。 (感谢@kaiido)来源:paper,additional links here
多线程环境中的任何代码(包括JS)都不会以恒定的性能执行(至少由于OS线程切换)。因此,要多次获得一致的值是无法实现的目标。要获得准确的数字-应多次执行函数,并取平均值。这甚至可以以低精度performance.now()
起作用。 (无聊的解释:如果函数比0.1 ms快得多,并且浏览器通常给出0ms的结果,但是不时某个函数运行会中奖,浏览器将返回0.1ms ...更长的函数会更频繁地赢得此彩票) / p>
大多数JS引擎中都有“优化编译器”。它优化了常用功能。优化非常昂贵,因此JS引擎仅优化常用功能。这解释了几次运行后性能的提高。首先,功能以最慢的方式执行。经过几次执行后,它进行了优化,并提高了性能。 (是否应添加预热运行?)
通过将70kb文件复制粘贴到输入中,我能够在代码段中获取非零数字。在优化第三次运行功能之后,但即使在此之后-性能也不是恒定的
time taken is 11.49999990593642
time taken is 5.100000067614019
time taken is 2.3999999975785613
time taken is 2.199999988079071
time taken is 2.199999988079071
time taken is 2.099999925121665
time taken is 2.3999999975785613
time taken is 1.7999999690800905
time taken is 1.3000000035390258
time taken is 2.099999925121665
time taken is 1.9000000320374966
time taken is 2.300000051036477
第一点的解释
让我们说发生了两个事件,目的是在两个事件之间找到时间。 第一个事件发生在时间A,第二个事件发生在时间B。浏览器将舍入精确值A和B并返回它们。
要研究的几个案例:
A B A-B floor(A) floor(B) Ar-Br
12.001 12.003 0.002 12 12 0
11.999 12.001 0.002 11 12 1
答案 1 :(得分:2)
浏览器比我们想象的要聪明,它进行了很多改进,并且在内存分配,可重复执行的代码,按需CPU分配等方面采用了缓存技术。例如V8,它是支持Chrome和Node.js caches code execution cycles and results的JavaScript引擎。此外,您的结果可能会受到浏览器在执行代码时使用的资源的影响,因此即使有多个执行周期,您的结果也可能会有所不同。
正如您所提到的,您试图创建jsPerf克隆,请看Benchmark.js,该库由jsPerf开发团队使用。
运行性能分析测试真的很难,我建议在具有预定义和预分配资源的Node.js环境中运行它们,以获取结果。
答案 2 :(得分:0)
您可能会看一下https://github.com/anywhichway/benchtest,它只是重用了Mocha单元测试。请注意,在单元级别的性能测试仅应是性能测试的一部分,还应使用仿真器来模拟实际情况并在应用程序级别测试代码以评估 网络影响,模块交互等。