Javascript, the DOM, and memory leaks

May 29, 2008 – 8:21 pm

Having recently starting implementing more Ajax into my web applications I discovered a new issue today that I’ve never considered or encountered before in my 10+ years of using Javascript; namely memory management and memory leaks. This is actually an issue involving both Javascript and the DOM.

The scenario: I have a web application for the management and booking of meeting rooms. The application displays a “day view” grid of Meeting Rooms vs. Time. Users can change the day that is displayed via either a date picker or clicking [Next] and [Previous] buttons. To avoid full page reloads each time the “day” is changed, I chose to use a client-side rendering approach in conjunction with Ajax. The HTML page loads, my Javascript code makes some Ajax calls to get the meeting room and booking data from the server, and then renders a nice grid using dHTML / DOM. Each time the user selects a different “day” to display, the Javascript code simply makes another Ajax call to get the new data and then re-renders the grid.

Lots of complicated Javascript code and a few Ajax calls later this is working great until I fire up Task Manager and notice that each time a new day is loaded the memory usage is jumping about 2MB each time. (I’m using IE7 by the way). “Ok, this is not good” I think despairingly to myself.

The search: Initial investigation showed that the large memory increase was occurring each time I removed the old booking DIV layers from the DOM and created new booking DIV layers. I was using objDiv.removeNode(true); to remove the DIV’s. Through google I read that removeChild() was not good and would not infact remove the node from memory. I wondered whether removeNode had the same problem? I altered my code to use removeChild and implemented the anti-memory leak solutions I had found on google. Result: no change.

The solution: Then I found some other articles suggesting that if you remove elements from the DOM that have events attached to them, that this “link” between the DOM element and Javascript will prevent the node being removed from memory properly. Now, my Javascript code was attaching 3 events (click, mouseover, mouseout) to each booking DIV layer. Therefore, when I was removing these elements using objDiv.removeNode(true), they were not being cleared from memory properly due to the attached events.

With this thought in mind I modified my Javascript code to maintain an array containing details of each event that I added. Then, when a user selected to view a different “day”, I would loop through this array and detach each event before removing the booking DIV layers. Hey, presto! Problem solved!!!

Some code I hope is useful. (This is IE only I’m afraid so you’ll need to add some browser sniffing and extra code to handle non IE events)

// Get reference to some DOM element in your page...
var objDiv = document.getElementById('my_div');

// To attach an event programmatically (IE only)...
objDiv.attachEvent('onclick', someJavascriptFunction);

// To detach an event programmatically (IE only)...
objDiv.detachEvent('onclick', someJavascriptFunction);

With the increasing use of Ajax and client-side dynamic HTML generation these kind of issues will become more important. Anyone else have any similar issues?

If you use Gmail - which uses a lot of Ajax and client-side HTML generation - you may have noticed you have to restart your web browser every now and then as it gets kind of slow. Have a look at the memory usage of iexplore.exe in Task Manager while using Gmail and you’ll understand why. I went from 50MB to 80MB in about 10 minutes simply by checking for new mail, viewing mail, etc.

Your Ad Here

Post a Comment