Question

I am using google's 3 Snapshot method to find memory leaks on the page. Page is running on Knockout.js and Jquery Mobile UI. I have already narrowed down to one of memory leaking divs. Between each snapshot I am running this script to clear the memory leaking object.

$('.paddedContentContainer').children().each(function(index,item){
console.log(item); 
$(item).off(); 
ko.cleanNode($(item)); 
$(item).remove();
item = null;
});

.paddedContentContainer is parent of leaking object.
Now the interesting part is that I can still see object in retained object tree. In screenshot below you can see I am filtering on objects in Snapshot 3 that are retained from Snapshots 1 and 2, and by text it's visible that $0 from console in same object that is on the screen (Event Sales Order & ....). enter image description here

I am assuming that .off(); and .remove(); isin't enough for object to be collected.
How to destroy all references to this object for good?

Was it helpful?

Solution 3

Adding an answer for those who will be satisfied with knockout.js reference removal only. This removed <div> at hand from object tree.

 $('.paddedContentContainer').children().each(function(index,item){
     $(item).off(); 
     ko.removeNode(item);
     $(item).remove();
     item = null;
 });

OTHER TIPS

Have you looked at this post: How to destroy a DOM element with jQuery??

Luke's response seems interesting:

If you want to completely destroy the target, you have a couple of options. First you can remove the object from the DOM as described above...

console.log($target); // jQuery object $target.remove(); // remove target from the DOM console.log($target); // $target still exists Option 1 - Then replace target with an empty jQuery object (jQuery 1.4+)

$target = $(); console.log($target); // empty jQuery object Option 2 - Or delete the property entirely (will cause an error if you reference it elsewhere)

delete $target; console.log($target); // error: $target is not defined

Maybe you should to delete $(item) in the end.

.remove() just removes the element from the DOM, if anything is still referencing it (in your code) it will not be Garbage Collected.

Edit

Yes the .remove() is the correct way of detaching/removing it from the DOM, but it is still held in memory because other things are referencing it (knockout's internals in this example).

One way, and the way I do it, is to keep a collection of all the high-level DOM elements that I create in my controls, then have a destroy function that loops these and calls .remove() on them and assigns them to null

E.g (Note this is held within each control object (no leaky global stuff):

var elements = 
{
    'table' : $('#some_table'),
    'button' : $('#some_button')
};


function destroy()
{
    for(var key in elements)
    {
        elements[key].remove();
        elements[key] = null;
    }
}

You may be able to take this approach with knockout.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top