频繁调用 Performance API 会导致性能问题吗?

Would calling Performance API frequently be causing a performance issue?

我想使用 performance.memory 测量我的 web SPA 的内存使用情况,目的是检测是否存在任何问题,即在 webapp 的生命周期内是否存在内存泄漏。

出于这个原因,我需要为特定的时间间隔调用此 API - 可以是每 3 秒、每 30 秒或每 1 分钟,......然后我有一个问题 - 到快速有效地检测任何问题我必须尽可能缩短间隔,但随后我想到了对性能的担忧。如果测量是一项如此昂贵的任务,测量本身可能会影响 webapp 的性能(希望我不认为是这种情况)

基于以上背景,我有以下问题:

  1. performance.memory这样的方法会影响浏览器主线程的性能,所以我应该关心使用频率吗?

  2. 是否有正确的方法或程序来确定 (Javascript) 任务是否影响设备的性能?如果问题1不确定,那么我将不得不尝试其他方法来找出调用内存测量的合适间隔。

(此处为 V8 开发人员。)

调用 performance.memory 非常快。您可以在自己的快速测试中轻松验证这一点:只需在循环中调用它一千次并测量需要多长时间。

[编辑: 感谢@Kaiido 强调这种微基准可以一般 非常具有误导性;例如,第一次手术可能要贵得多;或者基准场景可能与实际应用程序的场景如此不同,以至于结果无法延续。请记住,编写有用的微基准测试总是需要一些 understanding/inspection 幕后发生的事情!

在这个特殊的 案例中,稍微了解一下 performance.memory 的内部工作原理,这种简单测试的结果大致准确;但是,正如我在下面解释的那样,它们也无关紧要。
--编辑结束]

但是,该观察结果不足以解决您的问题。 performance.memory 快的原因也是频繁调用它毫无意义的原因:它只是 returns 一个缓存值,它实际上没有做任何测量内存消耗的工作。 (如果是,那么调用它会非常慢。)这是一个快速测试来证明这两点:

function f() {
  if (!performance.memory) {
    console.error("unsupported browser");
    return;
  }
  let objects = [];
  for (let i = 0; i < 100; i++) {
    // We'd expect heap usage to increase by ~1MB per iteration.
    objects.push(new Array(256000));
    let before = performance.now();
    let memory = performance.memory.usedJSHeapSize;
    let after = performance.now();
    console.log(`Took ${after - before} ms, result: ${memory}`);
  }
}
f();
(您还可以看到,出于安全原因,浏览器会限制计时器的粒度:报告的时间为 0 毫秒或 0.1 毫秒,绝非巧合。)

(第二)然而,这并不像乍看起来那么严重,因为前提是“要快速有效地检测到任何问题,我必须尽可能缩短间隔”这一前提被误导了: 在 garbage-collected 种语言中,内存使用量上下波动是完全正常的,可能高达数百兆字节。这是因为找到可以释放的对象是一项代价高昂的工作,因此垃圾收集器经过仔细调整以获得良好的折衷:他们应该尽快释放内存,而不会将 CPU 周期浪费在无用的繁忙工作上。作为该平衡的一部分,它们会适应给定的工作量,因此此处没有可引用的一般数字。

在野外检查应用程序的内存消耗是个好主意,您不是第一个这样做的人,performance.memory 是最好的工具 (for now)。请记住,您正在寻找的是 long-term 上升趋势,而不是 short-term 波动。因此,每 10 分钟左右测量一次就足够了,您仍然需要大量数据点才能看到 statistically-useful 结果,因为任何一次测量都可能发生在垃圾收集周期之前或之后。

例如,如果您确定所有用户在 10 秒后的内存消耗高于 5 秒后的内存消耗,那么这只是按预期工作,无需执行任何操作。然而,如果您注意到 10 分钟后读数在 100-300 MB 范围内,20 分钟后读数在 200-400 MB 范围内,一小时后读数为 500-1000 MB,那么是时候去寻找那次泄漏。