在向用户显示输出的同时准确测量Javascript函数性能

问题描述 投票:4回答:2

正如您在下面的代码中看到的,当我增加字符串的大小时,它会导致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这样的界面,它与它非常相似,但用途不同。大多数情况下,我想比较不同的功能,这将取决于用户输入。

javascript node.js performance performance-testing
2个回答
4
投票

有3件事可以帮助你理解发生的事情:

  1. 浏览器正在减少performance.now()精度,以防止熔化和幽灵攻击,因此Chrome提供最大0.1 ms精度,FF 1ms等。这使得无法测量小时间帧。如果功能非常快 - 0 ms是可以理解的结果。 (谢谢@kaiido)来源:paperadditional links here
  2. 多线程环境中的任何代码(包括JS)都不会以恒定的性能执行(至少由于OS线程切换)。因此,为多次单次运行获取一致的值是无法实现的目标。要获得一些精确的数字 - 应该多次执行函数,并取平均值。这甚至可以用于低精度performance.now()。 (无聊的解释:如果功能比0.1毫秒快得多,浏览器经常给出0毫秒的结果,但是一些功能运行的时间会赢得抽奖,浏览器将返回0.1毫秒...更长的功能将更频繁地赢得这个抽奖)
  3. 在大多数JS引擎中都有“优化编译器”。它优化了常用的功能。优化是昂贵的,因此JS引擎仅优化常用功能。这解释了几次运行后的性能提升。首先,功能以最慢的方式执行。几次执行后,它被优化,性能提高。 (应该添加热身运行吗?)

我能够在你的代码片段中获得非零数字 - 通过将70 kb文件复制粘贴到输入中。在第3次运行功能优化后,即使在此之后 - 性能不是恒定的

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

第1点的说明

让我们说发生了两件事,目标是在他们之间找时间。第一个事件发生在时间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

2
投票

浏览器比我们想象的更聪明,有很多改进和缓存技术可用于内存分配,可重复代码执行,按需CPU分配等。例如V8,为Chrome和Node.js caches code execution cycles and results提供动力的JavaScript引擎。此外,您的结果可能会受到浏览器在代码执行时使用的资源的影响,因此即使多次执行周期,您的结果也可能会有所不同。

正如您所提到的那样,您正在尝试创建一个jsPerf克隆,请查看Benchmark.js,这个库由jsPerf开发团队使用。

运行性能分析测试非常困难,我建议在具有预定义和预分配资源的Node.js环境中运行它们,以获得结果。

© www.soinside.com 2019 - 2024. All rights reserved.