Mat*_*ant 4 javascript html5 memory-leaks google-chrome canvas
我正在使用画布制作游戏,并且遇到了我无法确定的奇怪的Chrome行为.有时当我加载游戏时,Chrome任务管理器会报告它每秒分配+ 300MB,在大约10秒左右的时间内增加到几GB的内存,并且在选项卡崩溃之前它不会停止.
当我尝试运行javascript探查器时,问题就会停止.当我运行探查器加载选项卡时,它非常稳定.当问题发生时,然后我启动探查器,它将立即从1.5GB变为稳定的40MB.堆快照向我展示了如果游戏稳定运行我会期待什么.
我的游戏正在运行window.setInterval(我已尝试requestAnimationFrame并递归setTimeout并且问题仍然存在),并且更频繁地发生这种情况设置为高,这意味着当我将游戏设置为30FPS时,这很少发生,并且当我设置它时到60FPS,它发生超过一半的时间.这只发生在Chrome上,Firefox看起来很好.
当Chrome似乎仅在分析器运行时进行垃圾收集时,如何调试?
另外,我注意到当我将FPS推到60时,我的一些动画和键盘输入有点滑稽.我认为这可能是相关的,但在Firefox中也是如此.
小智 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);
}
Run Code Online (Sandbox Code Playgroud)
如果帧速率为60 FPS,那么每帧的时间将为1000/60,即大约16.667ms.
如果您innerLoopTime非常接近这个时间,您将知道您需要优化循环内执行的代码,或降低帧速率.
您可以使用调试器在函数内获取每步的时间成本,但调试器本身会增加总计的开销.所以测量时间,但成本较低..无论如何扭曲并转向这一点,这将是妥协的问题.