Chrome快速内存泄漏。如何调试当运行JavaScript分析器修复泄漏时?

4
我正在使用canvas制作游戏,但遇到了奇怪的Chrome行为,无法确定原因。有时候当我加载游戏时,Chrome任务管理器会报告每秒分配+300MB的内存,仅需10秒左右就可以增加几GB的内存,直到标签崩溃,这种情况一直持续下去。
当我尝试运行javascript分析器时,问题停止了。当我在运行分析器的标签中加载时,它是完全稳定的。当问题发生时,我启动分析器,内存从1.5GB立即降至稳定的40MB。堆快照显示了我期望的游戏稳定运行的情况。
我的游戏正在运行window.setInterval(我已经尝试过requestAnimationFrame和递归setTimeout,但问题仍然存在),并且如果设置得高,则更容易出现此问题,这意味着当我将游戏设置为30FPS时,很少会出现此问题,而当我将其设置为60FPS时,超过一半的时间都会出现此问题。这只会在Chrome上发生,Firefox似乎没问题。 当Chrome似乎只在运行分析器时进行垃圾回收时,该如何调试? 此外,我注意到当我将FPS推到60时,我的一些动画和键盘输入有点奇怪。我认为这可能有关,但Firefox也存在此问题。

为什么有人给这个点了踩?至少留下一条评论解释一下踩的原因! - ffflabs
1
嗨,马特,游戏或渲染循环更多地受到工作负载的驱动,而不是通过调用常规回调将其推向极限。FPS是工作负载的结果,而不是相反。t0->完成工作->T1->渲染->完成工作... t1-t2将是您的fps的关键因素。我建议您改变引擎的循环行为,否则您将永远陷入这个问题中。 - user996758
我不确定我完全理解。你能给我提供一个讨论这个问题的资源链接吗? - MattDiamant
3个回答

5

JavaScript是单线程的,这意味着所有的工作都需要在同一个线程上完成,包括排队事件(来自setTimeout/rAF、键等)、渲染到画布等。

如果循环非常紧密(时间预算方面),那么浏览器将没有任何空间来执行其他任务,例如GC - 对于Chrome而言,这个任务似乎是次要的,而对于Firefox而言,它会给予更高的优先级(可能是为了从其引擎中获得更好的性能)。基本上,运行的代码将阻止浏览器执行除执行代码本身之外的其他事情。

这种情况的一个很好的指标是,当您降低FPS以留出更多的空间用于事件队列、清理等时。当分析器正在运行时,它会获得更高的优先级,以捕捉各种各样的东西,因此由于某种原因,在分析器运行时GC会更早地“偷跑”(缺乏更好的术语)。但这非常取决于浏览器,我不知道这里的每个底层细节。

如果浏览器无法清除事件队列中的事件,它最终会堆积起来,在最坏的情况下会阻塞/冻结/崩溃浏览器。

在任何情况下,要调试这个问题(以确定原因)是很困难的,因为您不会从程序上获得访问内存或CPU使用情况等的权限。

最接近的方法是在循环内部使用高分辨率计时器,在代码开始和结束时检查它是否接近帧速率时间。

例如:

function loop() {

    var startTime = performance.now();

    ... other code ...

    var innerLoopTime = performance.now() - startTime;

    requestAnimationFrame(loop);
}

如果你的帧率是60 FPS,那么每帧的时间将为1000/60,约为16.667ms。
如果你的innerLoopTime非常接近这个时间,那么你就知道需要优化循环内执行的代码,或者降低帧率。
你可以使用调试器来获取函数内每步所需的时间成本,但调试器本身会增加总体开销。因此要进行时间测量,但代价更低...这将是一个妥协问题,无论如何扭曲此一问题。

Web Workers怎么样?它们在不同的线程中运行,如果可能的话。 - Kyslik

2
我发现JavaScript代码中一个巨大的内存泄漏源通常是闭包。如果你在setInterval中访问了一个在外部声明的变量,那么你很可能会泄漏一些内存。至于这是否是实际问题的根本原因,另外一个问题。
如果你想更好地理解闭包以及它们对你的js性能的影响,请看IBM关于这个主题的这篇文章。它提供了良好的示例和避免使用它们造成内存泄漏的方法,以及其他一些可能导致内存泄漏的来源。

1
我们注意到Chrome + Canvas的性能不如Firefox + Canvas。至于在打开Chrome开发工具时发生GC,那么我猜测您可能有一些代码以恰当的方式推动Chrome进行GC。您是否有某种窗口调整处理程序?可能还有其他类似的东西在起作用。

如果有疑问,请将代码二分,直到不再出现为止。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接