Friday, March 14, 2014

Browser and JS memory model and their garbage collection

Recently I am working on single page application, which leads to have deep dive into browser's memory model and JS garbage collector. I am also looking at different tools to do memory profiling and heapdump on different browsers.

There are two kinds of garbage collection algorithms: reference counting and mark-and-sweep. As we know finding out unreachable objects is undecidable in computer science. Those two algorithms are not always perfect.

Reference counting is essentially by keeping tracking of number of references to the objects once the count reaches 0 then gc will be triggered. However there is well-knows issue with that: it doesn't clean up the two objects have references to each other but on other references to these two objects. It is called "cycle reference."

Modern JS engines use mark-and-sweep garbage collection, basically it goes down from root Object to "unmark" the each object which can be reached. Then marked objects are considered as gc'd.

However this gc model is not compitale with browser's component object model DOM object handling. For example, IE's Windows COM use reference counting so does FreFox's XPCOM.

There certain memory leak patterns which are well documented:

1. circular reference between DOM and JS objects, DOM<->JS, please note this only apply to IE browser versions older than IE8.

As stated before, JS garbage collector can identify the cycle reference by going down the object hierarchy but not for the cycle reference between DOM object and JS object. And since DOM and JS have different garbage collection algorithm, so the above creates memory leak.

- Solution: set dom element reference in JS to null on unload() event.

2. closure: functions nested inside function, gain access to the outer function's variables it is known as closure.

function(){
    var obj = domElement;
   domElement.onclick = function(){ // this create new object which reference to domElement and domElement has onclick property reference back to this function obj, cycle reference
   
   }
   // obj = null; //solution is to set obj to null when function returns
}

3. inline script, the internal scripting object. If you create dom element with inline script thousands of times the memory leak will happen.

4. DOM object insertion order.

Each insertion of dom element will inherit the scope of the parent object which effectively create new object. If Dom element creation and insert happens alone from the document object, then temporary object will be created and leak.

The solution is to append child to document object first.



No comments:

Post a Comment