How does setTimeout () create a memory leak in this code?

I looked at the slides in this presentation: http://slid.es/gruizdevilla/memory

and on one of the slides, this code is represented by the sentence that it creates a memory leak:

var buggyObject = { callAgain: function() { var ref = this; var val = setTimeout(function() { ref.callAgain(); }, 1000); } } buggyObject.callAgain(); buggyObject = null; 

Can someone explain the problem in more detail here? I could skip some of the subtleties here.

+4
source share
3 answers

This is definitely a memory leak. However, memory consumption is so small and cannot be measured. I made minor changes to the source code.

  • I put all the code inside the loop to create the same script 100,000 times
  • I increased the timer interval to about 16 minutes. This prevents browser crashes.

Here is the code:

 for (var i = 0; i < 100000; i++) { var buggyObject = { callAgain: function() { var ref = this; var val = setTimeout(function() { ref.callAgain(); }, 1000000); //16m } } buggyObject.callAgain(); buggyObject = null; } 

Memory leak in Chrome

My experiment:

I ran the code in Chrome version 34.0.1847.116 m and committed the memory changes using the \ Timeline developer tools.

As can be seen from the figure, about 32 MB of memory was used to run this code, and after a while it decreased to about 30 MB and remained unchanged (see No. 1). After several attempts to collect garbage using Chrome (see No. 2) and one manual garbage collection (see No. 3, No. 4), memory consumption remains unchanged. There is no longer buggyObject , and we can do nothing to free up memory. The only possible way is to close the browser.

What causes this?

The main reason for this behavior is the timer. A timer callback and its associated buggyObject will not be returned until a timeout occurs. In our case, the timer resets itself and starts forever, and therefore its memory space will never be collected, even if there is no reference to the original object.

+3
source

There is another question that describes what setTimeout () looks like since it has memory leaks but doesn’t actually do that.

However, I think that the author is trying to say, since buggyObject creates a setTimeout that calls itself even if you change buggyObject to null (saying that you are finished with the object and you can clear it), the object will not be garbage collected because setTimeout () has a link to it. This is technically a memory leak, because there is no longer a direct reference to the setTimeout function so that you can clear it later (e.g. zombie wait time if you do this).

+5
source

As stated earlier, the timer starts and adds even more data to the stack. There is a conceptual view of what is going on:

 var a = 123; // call the setTimeout.function var a = 123; // call the setTimeout.function var a = 123; // call the setTimeout.function var a = 123; // call the setTimeout.function var a = 123; // call the setTimeout.function var a = 123; // call the setTimeout.function var a = 123; // call the setTimeout.function var a = 123; // call the setTimeout.function var a = 123; ...etc... 

So, every time a new variable a is allocated on the stack, it grows forever.

However, it was not mentioned that you have the setInterval () function to do what you need to do: repeat the same function again and again. Now you still have a “memory leak”, but only a leak of initialization parameters (i.e., it will not grow every time the timer goes off.)

So, conceptually, the calls are flat and you avoid the leak:

 a = 123; // call the setTimeout.function // call the setTimeout.function // call the setTimeout.function // call the setTimeout.function // call the setTimeout.function // call the setTimeout.function // call the setTimeout.function ...etc... 
0
source

Source: https://habr.com/ru/post/1495595/


All Articles