Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does JavaScript setInterval() method cause memory leak?

Currently developing a JavaScript based animation project.

I have noticed that, proper use of setInterval(), setTimeout() and even requestAnimationFrame allocates memory without my request, and causes frequent garbage collection calls. More GC calls = flickers :-(

For instance; when I execute the following simple code by calling init() in Google Chrome, memory allocation + garbage collection is fine for the first 20-30 seconds...

function init() {     var ref = window.setInterval(function() { draw(); }, 50); }  function draw() {     return true } 

Somehow, within a minute or so, starts a strange increase in allocated memory! Since init() is called only for once, what is the reason for the increase in allocated memory size?

(Edit: chrome screenshot uploaded)

chrome screenshot

NOTE #1: Yes, I have tried calling clearInterval() before the next setInterval(). Problem remains the same!

NOTE #2: In order to isolate the problem, I'm keeping the above code simple and stupid.

like image 891
matahari Avatar asked Dec 25 '12 21:12

matahari


People also ask

Can setInterval cause memory leak?

Timers & Events: The use of setTimeout, setInterval, Observers and event listeners can cause memory leaks when heavy object references are kept in their callbacks without proper handling.

Is it safe to use setInterval in JavaScript?

In order to understand why setInterval is evil we need to keep in mind a fact that javascript is essentially single threaded, meaning it will not perform more than one operation at a time.

What causes memory leak in JavaScript?

The main cause of memory leaks in an application is due to unwanted references. The garbage collector finds the memory that is no longer in use by the program and releases it back to the operating system for further allocation.

Can you leak memory using JavaScript?

Memory leaks can and do happen in garbage collected languages such as JavaScript. These can go unnoticed for some time, and eventually they will wreak havoc. For this reason, memory profiling tools are essential for finding memory leaks.


Video Answer


2 Answers

EDIT: Yury's answer is better.


tl;dr IMO there is no memory leak. The positive slope is simply the effect of setInterval and setTimeout. The garbage is collected, as seen by sawtooth patterns, meaning by definition there is no memory leak. (I think).

I'm not sure there is a way to work around this so-called "memory leak." In this case, "memory leak" is referring to each call to the setInterval function increasing the memory usage, as seen by the positive slopes in the memory profiler.

The reality is that there is no actual memory leak: the garbage collector is still able to collect the memory. Memory leak by definition "occurs when a computer program acquires memory but fails to release it back to the operating system."

As shown by the memory profiles below, memory leak is not occurring. The memory usage is increasing with each function call. The OP expects that because this is the same function being called over and over, there should be no memory increase. However, this is not the case. Memory is consumed with each function call. Eventually, the garbage is collected, creating the sawtooth pattern.

I've explored several ways of rearranging the intervals, and they all lead to the same sawtooth pattern (although some attempts lead to garbage collection never happening as references were retained).

function doIt() {     console.log("hai") }  function a() {     doIt();     setTimeout(b, 50); } function b() {     doIt();     setTimeout(a, 50); }  a(); 

http://fiddle.jshell.net/QNRSK/14/

function b() {     var a = setInterval(function() {         console.log("Hello");         clearInterval(a);         b();                     }, 50); } b(); 

http://fiddle.jshell.net/QNRSK/17/

function init() {     var ref = window.setInterval(function() { draw(); }, 50); } function draw() {     console.log('Hello'); } init(); 

http://fiddle.jshell.net/QNRSK/20/

function init() {     window.ref = window.setInterval(function() { draw(); }, 50); } function draw() {     console.log('Hello');     clearInterval(window.ref);     init(); } init();​ 

http://fiddle.jshell.net/QNRSK/21/

Apparently setTimeout and setInterval are not officially parts of Javascript (hence they are not a part of v8). The implementation is left up to the implementer. I suggest you take a look at the implementation of setInterval and such in node.js

like image 182
Luqmaan Avatar answered Nov 04 '22 02:11

Luqmaan


The problem here is not in the code itself, it doesn't leak. It is because of the way Timeline panel is implemented. When Timeline records events we collect JavaScript stack traces on each invocation of setInterval callback. The stack trace is first allocated in JS heap and then copied into native data structures, after the stack trace is copied into the native event it becomes garbage in the JS heap. This is reflected on the graph. Disabling the following call http://trac.webkit.org/browser/trunk/Source/WebCore/inspector/TimelineRecordFactory.cpp#L55 makes the memory graph flat.

There is a bug related to this issue: https://code.google.com/p/chromium/issues/detail?id=120186

like image 29
Yury Semikhatsky Avatar answered Nov 04 '22 01:11

Yury Semikhatsky