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

cad*_*zah 3 javascript performance google-chrome v8

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

因此,我需要在特定的时间间隔内调用此 API - 可以是每 3 秒、每 30 秒或每 1 分钟,...然后我有一个问题 - 要快速有效地检测任何问题,我会尽可能缩短间隔,但随后我开始担心性能。如果测量是一项如此昂贵的任务,那么测量本身可能会影响网络应用程序的性能(但希望我不认为是这种情况)

有了上述背景,我有以下问题:

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

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

jmr*_*mrk 5

(V8 开发人员在此。)

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

[编辑:感谢@Kaiido 强调这种微基准通常非常具有误导性;例如,第一次手术可能要昂贵得多;或者基准测试场景可能与实际应用程序的场景差异很大,导致结果无法延续。请记住,编写有用的微基准总是需要对幕后发生的事情进行一些理解/检查!

在这种特殊情况下,了解一下performance.memory内部工作原理,这样一个简单的测试的结果基本上是准确的;然而,正如我在下面解释的,它们也不重要。
——编辑结束]

然而,这种观察不足以解决你的问题。速度快的原因performance.memory也是频繁调用它毫无意义的原因:它只是返回一个缓存的值,它实际上并没有做任何测量内存消耗的工作。(如果确实如此,那么调用它会非常慢。)这里有一个快速测试来演示这两点:

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();
Run Code Online (Sandbox Code Playgroud)
(您还可以看到,出于安全原因,浏览器限制了计时器的粒度:报告的时间为 0 毫秒或 0.1 毫秒,绝非介于两者之间的任何值,这并非巧合。)

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

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

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