Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Javascript how to create an allocation free animation loop to avoid garbage collector?

I'm trying to build a smooth 60fps animation browser javascript loop. I've noticed that the garbage collector kicks in and adds variable non-zero time to animation frames. I started by tracking down allocations in my code and then isolated the loop its self. I was using requestAnimationFrame and discovered that on a supposedly 'empty' loop It still causes allocations each iteration and triggers the garbage collector. Frustratingly this seems to happen in other looping mechanisms setInterval and setTimeout as well.

Below I've put together some jsfiddles and screenshots demonstrating the sample 'empty loops'. All the samples are from ~5 second timelines.

At this point, I'm looking for the best solution to minimize garbage collection. From the samples below it looks like requestAnimationFrame is the worst option in this regard.

requestAnimationFrame

https://jsfiddle.net/kevzettler/e8stfjx9/

var frame = function(){
    window.requestAnimationFrame(frame);
};

window.requestAnimationFrame(frame);

enter image description here

setInterval

https://jsfiddle.net/kevzettler/p5LbL1am/

var frame = function(){
   //literally nothing
};

window.setInterval(frame, 0);

enter image description here

setTimeout

https://jsfiddle.net/kevzettler/9gcs6gqp/

var frame = function(){
    window.setTimeout(frame, 0);
}

window.setTimeout(frame, 0);

enter image description here

like image 322
kevzettler Avatar asked Mar 10 '16 04:03

kevzettler


People also ask

Can JavaScript user avoid GC?

Garbage collection is performed automatically. We cannot force or prevent it. Objects are retained in memory while they are reachable. Being referenced is not the same as being reachable (from a root): a pack of interlinked objects can become unreachable as a whole, as we've seen in the example above.

How does JavaScript handle garbage collection?

Some high-level languages, such as JavaScript, utilize a form of automatic memory management known as garbage collection (GC). The purpose of a garbage collector is to monitor memory allocation and determine when a block of allocated memory is no longer needed and reclaim it.

What is garbage collection and how is it performed in JavaScript apps?

When it comes to programming, Garbage Collection means cleaning the memory spaces which don't contain useful data and then reallocating those cleared memory to some other data which is both active and useful. That is the basic process of Garbage Collection in pretty much all the programming languages in the world.

What is heap in JavaScript?

Heap: It is used to store objects and functions in JavaScript. The engine doesn't allocate a fixed amount of memory. Instead, it allocates more space as required.


2 Answers

I'm not actually certain, but I seem to remember that web workers have their own garbage collectors, and so the GC hit wouldn't affect FPS in the main thread (though it would still affect updates' ability to be sent to the main thread)

like image 126
John Haugeland Avatar answered Oct 05 '22 23:10

John Haugeland


I'm no expert, but from what I've been reading. I too came across the same bug report that you mentioned in your comments:

As suggested, allocating the Number object on each call, would tally with garbage being collected.

https://bugs.chromium.org/p/chromium/issues/detail?id=120186#c20

It also suggested that simply having the debugger open recording the stack traces could cause problems. I wonder if this is the same case when doing remote debugging?

This answer suggests flip flopping between animation frames, to reduce the garbage collection: https://stackoverflow.com/a/23129638/141022

Judging by the depth of question you have asked, I'm sure what I'm about to say is obvious to you, but it might be interest to refocus towards your goal in general (albeit perhaps doesn't help with your interesting observation of Chrome).

One thing we need to remember is that we're not aiming to avoid garbage collection completely as it's so fundamental to JS. Instead we are looking to reduce it as much as possible to fit into rendering our frames with 16ms (to get 60fps).

One of VelocityJs's approaches is to have a single global "tick" that handles all animation...

Timers are created when setInterval(), setTimeout(), and requestAnimationFrame() are used. There are two performance issues with timer creation: 1) too many timers firing at once reduces frame rates due to the browser’s overhead of maintaining them, and 2) improperly marking the time at which your animation begins results in dropped frames.

Velocity’s solution to the first problem is maintaining a single global tick loop that cycles through all active Velocity animations at once. Individual timers are not created for each Velocity animation. In short, Velocity prioritizes scheduling over interruption.

http://www.sitepoint.com/incredibly-fast-ui-animation-using-velocity-js/

This along with general practices on reducing garbage collection such as creating a recycling cache to reuse objects or even rewriting methods such as array slice to avoid garbage.

https://www.scirra.com/blog/76/how-to-write-low-garbage-real-time-javascript

like image 45
Alex KeySmith Avatar answered Oct 06 '22 01:10

Alex KeySmith