This is silly. You're creating a new anonymous function on every interval, so it will increasingly take up memory to hold these anon functions until the GC kicks in. It's doing exactly what it should do, because you don't want it doing GC every 50 ms.
That anonymous function is a literal, just like the number 50 (the next argument after it). In the same way the 50 doesn't get created each iteration, neither does the anonymous function.
My tenuous understanding of the ECMAScript spec would suggest that a new execution context and associated activation object + scope chain is created each time that function is invoked. Since this is a closure, the execution context and associated objects have to wait to be garbage collected.
So you're going to see an increase in memory with each function call until the garbage collector kicks in.
So while the function definition is a literal, the execution most definitely has a cost associated with it.
Yes. Firefox had terrible GC pauses until last year [1]. Chrome processes just a portion of the heap at a time to reduce pauses to a minimum [2].
You can minimize GC by being clever about re-using objects, avoiding waste. The top answer shows how GC happens less frequently when using a setTimeout loop instead of setInterval, I don't know the underlying reason but that was always recommended before requestAnimationFrame came along.
These days you should use requestAnimationFrame whenever available - it allows the browser to plan ahead for a smoother framerate, adjust rate to the device capabilities, and save resources when it's in the background.
From what I can tell the issue stems from the fact that Javascript puts stack frames on the heap, which means the heap will grow with every function call, which they're doing every 50 ms.
reply