Telerik blogs

This post is number three in a three part series about memory consumption for web applications. Links to Part 1 and Part 2.

Memory Consumption - Best Practices

To be perfectly honest there is only one issue with memory consumption, i.e. using too much of it. Size does matter. Therefore every web developer should try and minimize the impact on the usage of memory, especially when the application tends to become huge.

Web applications are becoming more and more client-side oriented and staying on one and the same page for hours should not be an exception. Therefore careful creation of new objects, managing the used objects and properly disposing those, that are unneeded, is crucial.

Avoid closures in the initialization of JS objects

Here is the code sample that we will investigate:

function HungryClass()
{
       this.specialHandler = function()
       {
              foo()
       };
}
 
function PrototypeClass() { }
PrototypeClass.prototype =
{
       specialHandler: function()
       {
              foo()
       }
}
 

The HungryClass initializes its method member specialHandler inline, within the initialize phase. The bad thing about this is that every time a new object is created, a new Function object is created and assigned to the specialHandler. To avoid this one may use the pattern for the second class – PrototypeClass, i.e. defining the object specific members in the prototype object. Thus every class will have the same functionality, but the specialHandler member will always be one and the same.

Avoid unnecessary references to DOM elements

This advice is more a prevention pattern against possible memory leaks. However in many cases referencing DOM elements is not only beneficial, but also crucial. Such a case was demonstrated in the memory leak example – “Dynamically created DOM elements and JavaScript objects”, where the reference to the button was the only way to be able to properly call the $removeHandler in the dispose method. In such cases make sure that the references are destroyed once it is not needed anymore.

Make sure DOM elements are removed properly

In Internet Explorer 8 and below there is a specific issue, when trying to remove DOM elements through the removeChild method. The elements are removed from the DOM tree, but are not released from the memory. They haven’t leaked actually, but are eating out memory. In order to fully get rid of them there, additional procedures need to be done, i.e. append the removed elements to an empty container and set the innerHTML of the container to an empty string. Here is a sample code that implements the pseudo-leak free removal of DOM elements:

bbbbbb.msie8andBelow = /msie [1-8]\./i.test(navigator.userAgent)
function removeElementSafe(node)
{
       node.parentNode.removeChild(node);
       if(bbbbbb.msie8andBelow)
              discardElement(node);
}
function discardElement(el)
{
       var bin=document.getElementById("IELeakGarbageBin");
       if(!bin)
       {
              bin=document.createElement("DIV");
              bin.id="IELeakGarbageBin";
              bin.style.display="none";
              document.body.appendChild(bin);
       }
       bin.appendChild(el);
       bin.innerHTML="";
}
 

Another option is to use the remove methods of various JS libraries that have implemented this fix.

Avoid custom properties to DOM elements

This will help avoiding any sort of circular references between DOM elements and JS objects. Otherwise memory leak patterns may arise. Still one should not give up the option of associating JS data to DOM objects. The solution is to use, for example, the jQuery Data API. Other libraries have implemented similar APIs as well. The idea is instead of storing JS objects as properties on DOM elements, to create one custom property on the DOM node, which is an index to a global hash-table. Here is an example from the jQuery world:

$("#showData").click(function()
{
       alert($(this).data("customData").a);
});
$("#showData").data("customData", {a:1, b:2, c:3});
 

Conclusion

After this journey through the mists of memory leaks and memory consumption, I hope that you have understood the relationship between the two terms and the differences between them as well. I sincerely hope that from now one you will be more confident in the topic of memory management in browsers and be able to spot and eliminate the most common memory leaks in web applications.

Have a leak-free and fun development.


About the Author

Nikodim Lazarov

is a Senior Software Developer in the Telerik's ASP.NET AJAX devision. He has years of experience building web applications of various scales. Niko is a strong advocate of Web standards, TDD, Agile and basically anything that makes every developer a true craftsman. Outside of office he usually rides his bike, goes kayaking or is simply out with friends.

Related Posts

Comments

Comments are disabled in preview mode.