频繁调用 Performance API 会导致性能问题吗?
我想使用 performance.memory
,目的是检测webapp生命周期内是否存在内存泄漏问题。
因此,我需要在特定的时间间隔内调用此 API - 可以是每 3 秒、每 30 秒或每 1 分钟,...然后我有一个问题 - 要快速有效地检测任何问题,我会尽可能缩短间隔,但随后我开始担心性能。如果测量是一项如此昂贵的任务,那么测量本身可能会影响网络应用程序的性能(但希望我不认为是这种情况)
有了上面的背景,我有以下问题:
是
performance.memory
这样的方法会影响浏览器的主线程性能,所以我应该关心使用频率?是否有正确的方法或过程来确定(Javascript)任务是否影响设备的性能?如果问题1不确定,那么我将不得不尝试其他方法来找出调用内存测量的正确间隔。
I want to measure the memory usage of my web SPA using performance.memory
, and the purpose is to detect if there is any problem i.e. memory leak during the webapp's lifetime.
For this reason I would need to call this API for specific time interval - it could be every 3 second, every 30 second, or every 1 minute, ... Then I have a question - to detect any issue quickly and effectively I would have to make the interval as short as I could, but then I come up with the concern about performance. The measuring itself could affect the performance of the webapp if the measuring is such a expensive task (hopefully I don't think that is the case though)
With this background above, I have the following questions:
Is
performance.memory
such a method which would affect browser's main thread's performance so that I should care about the frequency of usage?Would there be a right way or procedure to determine whether a (Javascript) task is affecting the performance of a device? If question 1 is uncertain, then I would have to try other way to find out the proper interval for calling of memory measurement.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
(这里是 V8 开发人员。)
调用
performance.memory
非常快。您可以自己在快速测试中轻松验证这一点:只需循环调用它一千次并测量需要多长时间。[编辑:感谢@Kaiido 强调这种微基准一般可能会非常具有误导性;例如,第一次手术可能要昂贵得多;或者基准测试场景可能与实际应用程序的场景差异很大,导致结果无法延续。请记住,编写有用的微基准总是需要对幕后发生的事情进行一些理解/检查!
在这种特殊情况中,了解一些
performance.memory
内部工作原理后,这样一个简单测试的结果基本上是准确的;然而,正如我在下面解释的那样,它们也不重要。--编辑结束]
但是,这种观察不足以解决您的问题。 Performance.memory 速度快的原因也是频繁调用它毫无意义的原因:它只是返回一个缓存的值,它实际上并没有做任何测量内存消耗的工作。 (如果确实如此,那么调用它会非常慢。)这里有一个快速测试来演示这两点:
(You can also see that browsers clamp timer granularity for security reasons: it's not a coincidence that the reported time is either 0ms or 0.1ms, never anything in between.)
(第二)然而,这并不像乍看起来那么严重,因为“为了快速有效地检测任何问题,我必须尽可能缩短间隔”的前提是错误的:在垃圾收集中对于各种语言,内存使用量上下波动(可能达到数百兆字节)是完全正常的。这是因为寻找可以释放的对象是一项昂贵的工作,因此垃圾收集器经过仔细调整以实现良好的折衷:它们应该尽快释放内存,而不会将 CPU 周期浪费在无用的忙碌工作上。作为平衡的一部分,它们适应给定的工作负载,因此这里没有可引用的一般数字。
在野外检查应用程序的内存消耗是一个好主意,您不是第一个这样做的人,并且
performance.memory
是最好的工具(目前)。请记住,您正在寻找的是长期上升趋势,而不是短期波动。因此,每 10 分钟左右测量一次就完全足够了,而且您仍然需要大量数据点来查看统计上有用的结果,因为任何单个测量都可能发生在垃圾收集周期之前或之后。例如,如果您确定所有用户在 10 秒后的内存消耗量高于 5 秒后的内存消耗量,那么这只是按预期工作,无需执行任何操作。然而,如果您注意到 10 分钟后,读数在 100-300 MB 范围内,20 分钟后在 200-400 MB 范围内,一小时后读数在 500-1000 MB 范围内,那么是时候去寻找那个泄漏。
(V8 developer here.)
Calling
performance.memory
is pretty fast. You can easily verify that in a quick test yourself: just call it a thousand times in a loop and measure how long that takes.[EDIT: Thanks to @Kaiido for highlighting that this kind of microbenchmark can in general be very misleading; for example the first operation could be much more expensive; or the benchmark scenario could be so different from the real application's scenario that the results don't carry over. Do keep in mind that writing useful microbenchmarks always requires some understanding/inspection of what's happening under the hood!
In this particular case, knowing a bit about how
performance.memory
works internally, the results of such a simple test are broadly accurate; however, as I explain below, they also don't matter.--End of edit]
However, that observation is not enough to solve your problem. The reason why
performance.memory
is fast is also the reason why calling it frequently is pointless: it just returns a cached value, it doesn't actually do any work to measure memory consumption. (If it did, then calling it would be super slow.) Here is a quick test to demonstrate both of these points:(You can also see that browsers clamp timer granularity for security reasons: it's not a coincidence that the reported time is either 0ms or 0.1ms, never anything in between.)
(Second) however, that's not as much of a problem as it may seem at first, because the premise "to detect any issue quickly and effectively I would have to make the interval as short as I could" is misguided: in garbage-collected languages, it is totally normal that memory usage goes up and down, possibly by hundreds of megabytes. That's because finding objects that can be freed is an expensive exercise, so garbage collectors are carefully tuned for a good compromise: they should free up memory as quickly as possible without wasting CPU cycles on useless busywork. As part of that balance they adapt to the given workload, so there are no general numbers to quote here.
Checking memory consumption of your app in the wild is a fine idea, you're not the first to do it, and
performance.memory
is the best tool for it (for now). Just keep in mind that what you're looking for is a long-term upwards trend, not short-term fluctuations. So measuring every 10 minutes or so is totally sufficient, and you'll still need lots of data points to see statistically-useful results, because any single measurement could have happened right before or right after a garbage collection cycle.For example, if you determine that all of your users have higher memory consumption after 10 seconds than after 5 seconds, then that's just working as intended, and there's nothing to be done. Whereas if you notice that after 10 minutes, readings are in the 100-300 MB range, and after 20 minutes in the 200-400 MB range, and after an hour they're 500-1000 MB, then it's time to go looking for that leak.