最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

html - Chrome Rapid Memory Leak. How To Debug When Running Javascript Profiler Fixes Leak? - Stack Overflow

programmeradmin2浏览0评论

I'm making a game using canvas, and am running into strange Chrome behavior that I can't pin down. Sometimes when I load the game, the Chrome Task Manager will report that it's allocating +300MB a second, ramping up to over a few GB of memory in just a matter of 10 seconds or so, and it doesn't stop until the tab crashes.

When I try to run the javascript profiler, the problem stops. When I load the tab with the profiler running, it is perfectly stable. When the problem happens, and then I start the profiler, it will go from 1.5GB to a stable 40MB immediately. And the heap snapshot shows me what I would expect if the game was running stably.

My game is running on window.setInterval (I've tried requestAnimationFrame and recursive setTimeout and the problem still happens), and it happens more often with this is set high, meaning that when I set the game to 30FPS, this rarely ever happens, and when I set it to 60FPS, it happens over half the time. This is only happening on Chrome, Firefox seems fine.

How do I debug this, when Chrome seems to do garbage collection only when the profiler is running?

Also, I've noticed that some of my animations and keyboard inputs are a little funny when I push the FPS to 60. I assume that this could be related, but this is also the case in Firefox.

I'm making a game using canvas, and am running into strange Chrome behavior that I can't pin down. Sometimes when I load the game, the Chrome Task Manager will report that it's allocating +300MB a second, ramping up to over a few GB of memory in just a matter of 10 seconds or so, and it doesn't stop until the tab crashes.

When I try to run the javascript profiler, the problem stops. When I load the tab with the profiler running, it is perfectly stable. When the problem happens, and then I start the profiler, it will go from 1.5GB to a stable 40MB immediately. And the heap snapshot shows me what I would expect if the game was running stably.

My game is running on window.setInterval (I've tried requestAnimationFrame and recursive setTimeout and the problem still happens), and it happens more often with this is set high, meaning that when I set the game to 30FPS, this rarely ever happens, and when I set it to 60FPS, it happens over half the time. This is only happening on Chrome, Firefox seems fine.

How do I debug this, when Chrome seems to do garbage collection only when the profiler is running?

Also, I've noticed that some of my animations and keyboard inputs are a little funny when I push the FPS to 60. I assume that this could be related, but this is also the case in Firefox.

Share Improve this question asked May 7, 2014 at 18:22 MattDiamantMattDiamant 8,8014 gold badges38 silver badges47 bronze badges 3
  • Why did someone downvoted this? At least leave a ment explaining the downvote! – ffflabs Commented May 7, 2014 at 18:25
  • 1 Hi Matt, Gaming or rendering loop are more drived by the work load than pushing it to limit calling regular callback. The FPS is the result of the work load not the reverse. t0-> do the job ->T1 -> render -> do the job.. t1-t2 will be the key factor for your fps. I suggest you change the loop behavior of your engine, otherwize you will stuck with this problem forever. – user996758 Commented May 12, 2014 at 16:57
  • I'm not sure that I understand fully. Can you link me to a resource that talks about this? – MattDiamant Commented May 12, 2014 at 18:18
Add a ment  | 

3 Answers 3

Reset to default 5 +25

JavaScript is single-threaded which means all the work needs to be done on the same thread including queuing events (from setTimeout/rAF, keys etc.), rendering to canvas and so forth.

If the loop is very tight (time-budget-wise) there will simply not be any room for the browser to do other tasks such as GC - for Chrome this task seem to be secondary versus Firefox which gives this higher priority (likely to get more performance out of its engine). Basically the running code will block the browser from doing other things than executing the code itself.

A good indicator of this is when you lower the FPS leaving more space for event queue, clean-up etc. When the profiler is running it get more priority in order to catch all sort of things so for some reason GC gets to "sneak" in earlier when profiler is running (in lack of better term). But this is very browser specific and I do not know every underlying details here.

If the browser cannot purge events in the event queue it will eventually stack up and in worst case block/freeze/crash the browser.

In any case, it's hard to debug this (for pin-pointing reasons) as you won't, programmatically, have access to memory or CPU usage etc.

The closest thing is to use a high-resolution timer at the beginning and end of the code inside the loop to see if it es close to the frame rate time.

For example:

function loop() {

    var startTime = performance.now();

    ... other code ...

    var innerLoopTime = performance.now() - startTime;

    requestAnimationFrame(loop);
}

If your frame rate is 60 FPS then the time per frame would be 1000/60, or about 16.667ms.

If your innerLoopTime is very close to this time you will know that you need to optimize the code executed inside the loop, or lower the frame rate.

You could use the debugger to get time-cost per step inside the function but the debugger itself will add an overhead to the total. So do measuring the time, but the cost is lower.. it will be a matter of promise no matter how one twist and turn this one.

I've found that a huge source of memory leaking in javascript code is usually closures. If you're accessing a variable inside your setInterval that was declared outside, then you're most likely leaking some memory. As to whether or not this is the actual root cause of the issue is another question.

If you want to understand closures more and how they affect the performance of your js in action, look at this article by IBM on the topic. It gives good examples and ways to avoid memory leaks using them, as well as a few other possible sources of memory leaks.

We've noticed chrome + canvas is not as performant as firefox + canvas. As to GC occurring when you open chrome dev tools, well I'd guess you may have some code that nudges chrome in just the right way to do a GC. Do you have some sort of window resize handler? There might be something else that is doing something similar.

When in doubt bisect the code till it doesn't happen anymore.

发布评论

评论列表(0)

  1. 暂无评论