Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Empty requestAnimationFrame loop leaking memory?

I have a clean HTML file with requestAnimationFrame loop that does absolutely no processing. However, if I look at memory consumption on Chrome DevTools I see that used memory constantly increases and garbage collector runs every few seconds to collect around 1 megabyte of garbage data.

So where does this memory leak comes from?

That's how my memory usage looks like:

Chrome DevTools memory usage data

And here's my code:

<!DOCTYPE html>
<html>
<head lang="en">
    <title></title>
    <script>

        function update() {

            window.requestAnimationFrame(update);

        }

        update();

    </script>
</head>
<body>

</body>
</html>
like image 392
GiedriusT Avatar asked Oct 15 '15 08:10

GiedriusT


1 Answers

I investigated this too. I came here because I noticed Chrome is tracking where calls come from.

show devtools showing call chain

And I noticed it was going all the way back to the original call

devtools traced back to original call

So, I left it running for an hour checking on it every few minutes. It did allocate memory for a while but eventually seemed to release some.

I'm pretty sure it does this to make debugging other async code easier since it's helpful to know where some async request started. Without that path all you get is that your event/callback got called, not where it was created.

That said I understand your pain. It's well known that 24fps has problems and movie directors tend to avoid the types of scenes that show those issues. When "The Hobbit" came out and was shot at 48fps the director tried adding some of the types of scenes back in that fail at 24fps.

It's also well known in video games that 30fps is not enough for any 2d scrolling game. For into the screen games it's passable (whole generations of games shipped at 30fps on PS1, PS2, N64) but for 2d scrolling games the entire screen appears to shutter at 30fps where as it appears smooth at 60fps

In any case I don't have a solution to suggest. It's just the way the browser works. Every time you create an event, which is what requestAnimationFrame does, some small object has to be allocated and put on the list of events to be executed at some point in the future and that in itself takes memory. For requestAnimationFrame in particular maybe the browser could special case having only a pre-allocated queue of a few events and trying to recycle them rather then use the generic system they use for all other events (mouse, keyboard, images loading, XHR requests finishing etc) but that would likely be hard to implement given that when the events actually execute they probably need to be in the same queue.

And even then, JavaScript itself is all about allocating memory. It's nearly impossible not to. Calling a function allocates the arguments since they end up being part of that function's closure context (JS engines might optimize that but from language perspective they allocate).

Now that browsers are starting to target WebVR which requires 90fps maybe they'll come up with a new way. Or maybe we'll all switch to WebAssembly?

¯\_(ツ)_/¯

like image 117
gman Avatar answered Nov 16 '22 00:11

gman