Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Chrome Profiler Javascript memory leak

I tried to write a javascript code with a memory leak in order to work with the profiler in Chrome. However, it seems the profiler isn't showing what it should be.

Here's my code :

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<button id="start_button">Start</button>
<button id="destroy_button">Destroy</button>

<script type="text/javascript" charset="utf-8">
var Leaker = function(){};

Leaker.prototype = {
                init:function(){
                        this._interval = null;
                        this.start();
                },
                start: function(){
                        var self = this;
                        this._interval = setInterval(function(){ self.onInterval(); }, 100);
                },
                onInterval: function(){ console.log("Interval"); }
};

$("#start_button").click(function(){
        if(leak !== null && leak !== undefined){
            return;
        }

        leak = new Leaker();
        leak.init();

});

$("#destroy_button").click(function(){
        leak = null;
});

var leak;

</script>

You can see when I click on start button a new object Leaker is created. And when I click on destroy, the object is set to null (NOTE: But it won't be garbage collected since the setInterval will be still working).

Problem: However, when I use the Google Chrome Profiler it doesn't show me any reference to my Leaker instance after I click on destroy (but it should show me such a reference, since as I noted above, the closure from setInterval is still holding onto it).

Profiler before clicking on destroy button Profiler before clicking on destroy button

Profiler after clicking on destroy button (you can see I can't find leaker instance anymore, whereas it should be there).

Profiler after clicking on destroy button

And here the console, the setInterval is still in action eventhough the profiler show us there is no more Leaker instances.

Console & setInterval

Am I missing something on the way garbage collecting works or the Chrome profiler ?

like image 416
kamel B Avatar asked Jul 28 '15 10:07

kamel B


1 Answers

The difference between the two profilers is that before you "destroy" leak, the Leaker variable is global and after it's not. So it's just the profiler (and the javascript engine) that doesn't work the way you describe it. Basically, you can see global variables, but not locally scoped variables. I guess it makes sense to allocate differently based on the scope. Until you set leak to null, it needs to be available to other scripts.

You can see with a minimal example how the profiler works differently based on the scope:

var Leaker = function() {};

var Leaker2 = function() {};

// this one is going to be in the profiler
var leak = new Leaker();

(function(){
    // this one is not in the profiler
    var leak2 = new Leaker2();
    setInterval(function(){console.log(leak2)}, 500);
})()

EDIT:

Just to clarify, the object is still in the profiler, and still allocated, but not the same way a global is. I was just creating a minimal example of how Chrome profiler works. When a variable is global, you'll see it in and can filter it in the class filter, but if not you can't.

Now, it is still somewhere, obviously. You can check in closures drop down, you'll see you have a Leaker there on both snapshots :

enter image description here

Maybe a duplicate is created when in a closure, so that context info can be allocated as well.

like image 76
Julien Grégoire Avatar answered Sep 19 '22 23:09

Julien Grégoire