As a newbie blogger perhaps I should have started with a brief info on who I am and should have continued with a post extending my best wishes for Xmas and Year 2006. Nonetheless, I thought it's a better idea to post some technical content that might be of use to our community. Perhaps the info will benefit some of you and will let you spend Xmas Eve with your family, rather than sit in the office trying to fix problems for which our team has found solutions.
Ever been shocked with how much your memory usage grows on every refresh of your page? I was recently battling with the issue of memory leaks in Internet and thought it would be a good idea to share some of my findings. This article covers problems that were reported long ago and which should have been fixed long ago by the IE team. It turned out, however, that the issue with memory leaks became an evergreen - memory leaks are consistently appearing through the whole IE browser family and we are not seeing the end of it. I’m not picking on IE - I don’t have a crash on this one. It’s just that the other browsers simply have much better garbage collector implementations than IE and don’t leave us with junked memory behind.
There are three widely recognized memory leak patterns in Internet Explorer (more information can be found at http://msdn.microsoft.com/library/default.asp?url=/library/en-us/IETechCol/dnwebgen/ie_leak_patterns.asp): the so called circular references, the closures, the cross-page leaks and the pseudo-leaks.
The biggest “memory eaters” are the circular references, especially those that enclose in a circular reference Native and Host objects.
For the unacquainted, a circular reference is a case when two or more objects refer each other (keep references of any kind) in a way that can be followed and which leads back to the starting point. That is exactly what the garbage collector in IE does - it keeps lists of objects and object references, constantly checking them, and if an object remains in memory but is not referenced by any other object, it gets disposed.
The usual suspects for many memory leak problems are the Native and Host objects. By Native ECMAScript recognizes any objects that belong to the language (there is a sub-category of native objects called "Built-in Object" also)). By Host objects ECMAScript recognizes any objects provided by the environment, like the document object and its descendants, in other words the DOM structures.
The biggest leaks come from “Native to Host” or “Host to Native” object references because of the difference of their nature - native objects have scope in the means of the execution context only and the Host objects are only represented there, while being COM objects in nature.
If the closure embraces only Native objects, it might be recognized as such and be available for disposal (example: object1 -> object2 -> object3 -> objectN -> object1), But if one of the objects happens to be a Host (or DOM) object, the garbage collector is unable to test/verify that the circular relationship between them is isolated from the rest of the current execution context and to free the resources used. Instead, they all stay in memory until the whole application/browser is closed.
Here is a diagram I “borrowed” from the MSDN site to demonstrate clearly the relation:
That leads us directly to the other participant in our small “memory leak contest” - the closures. I will talk about closures next week in Part Two of this topic.
As a wrap-up of Part I, here’s my advice: try to keep the references to the DOM(Host) objects to the minimum, else you guarantee memory leaks. And do remember that the best way is to release explicitly all of the DOM resources at the end (onunload event).