Fixing jQuery memory leaks in ASP.NET

July 17, 2009 by admin Leave a reply »

When it comes to javascript toolkits there seem to be a plethora of options but in my opinion by far the two that stand out tall amongst others are jQuery and Prototype. Although Prototype is an aged toolkit that has proven itself and extends the existing DOM functionality acting as a proxy for the available DOM objects, I am a bigger fan of jQuery due to it’s simplicity, small footprint, and it’s powerful DOM parser.

In this write-up, I assume you are using jQuery in an ASP.NET web application and have heard some Prototype enthusiasts bash it by saying it has memory leaks and are looking for an explanation of what those are and how to fix them. I will list the two that I have come across by doing various research on the web and the solutions I found that I integrated into my applications.

Both of these memory leaks are a result of asynchronous refreshes using UpdatePanel.  When an UpdatePanel refreshes, it makes a regular request to your ASPX page and refreshes only a part of the loaded page in the browser.  During this refresh and the process of throwing away existing DOM elements is when we run into these memory leaks with jQuery.

IE Garbage Collection

I found this issue at a very thorough write-up on CodeProject which explained exactly what was going on.  To give you a summary, this is what happens.  You might have jQuery scripts that parse your DOM and attach events to various elements throughout your page.  Some of these elements are likely the ones that get thrown away when an UpdatePanel refresh happens.

The problem in IE is that it has two garbage collectors that run periodically and clean out the orphaned element objects from memory but if any of those objects have events attached to them, neither garbage collector can dispose of those objects.  Given that, if you have a page with an UpdatePanel that is constantly being refreshed with elements with events attached, the memory consumption of that IE process will keep growing.

Fortunately, before an UpdatePanel refresh happens and the old DOM elements are thrown away, the ASP.NET client side library checks each element for a dispose method and invokes that for the element to clean away any resources.  jQuery also bind to the window.unload event providing for doing clean up before the user leaves a page.  However, since jQuery doesn’t know anything about the UpdatePanel we have to make that connection between the two by taking advantage of jQuery’s plugin support and ASP.NET PageRequestManager class’ events.

Here is the jQuery plugin code:

(function($) {
    $.fn.disposable = function(cln) {
        return this.each(function() {
            var el = this;
            if (!el.dispose) {
                el.dispose = cleanup;
                $(window).bind("unload", cleanup);
            }
            function cleanup() {
                if (!el) return;
                $(el).unbind();
                $(window).unbind("unload", cleanup);
                el.dispose = null;
                el = null;
            };
        });
    };
})(jQuery);

Now, anytime you retrieve jQuery elements in your scripts and plan to attach events to them, simply call disposable on them so that they are wired up to be properly disposed as follows:

$(':submit').click(function() {
    // do something here
}).disposable();

jQuery.Data()

jQuery has a very neat feature for you to be able to store metadata on an element using the data(key, value) method on an element instance.  The problem is that if you clear contents of a DIV by doing .innerHTML = “” that contains elements that have data associated with them, the data will be orphaned and live in memory eventually causing memory leaks.

It also just so happens that when an UpdatePanel refresh happens, the new content is replaced with the old content by setting the innerHTML property of the UpdatePanel element.  This becomes tricky now because UpdatePanel doesn’t know about jQuery or it’s support for setting data on DOM elements.

Thanks to a blog by Malnotna one workaround that is clean and is abstract is as follows:

1.  Save the following as a .js file:

jQuery(function(){
    if (Sys && Sys.WebForms && !Sys.WebForms.PageRequestManager.jQueryDestroyTreeOverriden) {
        Sys.WebForms.PageRequestManager.jQueryDestroyTreeOverriden = true;
        var oldFn = Sys.WebForms.PageRequestManager.prototype._destroyTree;
        var depth = 0;
        Sys.WebForms.PageRequestManager.prototype._destroyTree = function(element) {
            depth++;
            oldFn.apply(this, [element]);
            if (--depth == 0) {
                jQuery(element).empty();
            }
        }
    }
});

2. Load it on your pages after the jQuery library.

<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="MSAjaxWebFormsJQueryData.js"></script>

I hope you guys find this article helpful and keep a lookout for more posts about other jQuery/MS Ajax functionality here.

14 Responses

  1. dhiraj says:

    This is pretty good article Huzaifa. Great job! I like the way the information is structured. Very valuable

  2. Jo Gatlin says:

    This article is actually the best on this worthy topic. I absolutely feel the same way with your points of view and will eagerly look forward to your approaching updates. Just saying thanks will not just be sufficient, for the wonderful lucidity in your writing. I will immediately grab your rss feed to stay in the loop of any updates. Marvelous work and best of luck in your website promotion!

  3. cash advance says:

    I want to thank the blogger very much not only for this post but also for his all previous efforts. I found http://www.quattrosource.com to be extremely interesting. I will be coming back to http://www.quattrosource.com for more information.

  4. nakedgoat says:

    Not bad article, but I really miss that you didn’t express your opinion, but ok you just have different approach

  5. tezza says:

    I would appreciate more visual materials, to make your blog more attractive, but your writing style really compensates it. But there is always place for improvement

  6. Shamisen says:

    I read a article under the same title some time ago, but this articles quality is much, much better. How you do this?

  7. Thanks for the great insight on that, never really thought about it. bookmarked your site! rl circuit

  8. Leann Ulses says:

    Just wanted to pop in and say THANKS! It’s a great script, it was easy to install (once my hosting company solved the 500 error), and it can be customized very well.

  9. Bookmarked your site. Thank you for sharing. Definitely worth the time away from the books.

  10. Movie Title says:

    Super post – and great domain by the way:-)

Trackbacks/
Pingbacks

  1. Corner Television Stands Home
  2. HUGH
  3. http://webdesign-boston.com/
  4. SHOP ELECTRONICS!!!

Leave a Reply