Home > HTML, Internet Explorer, JavaScript, Tips & Tricks, UI, jQuery > IE Memory Leak – jQuery Fix

IE Memory Leak – jQuery Fix

I suppose all of you have suffered all those terrible memory leaks in Internet Explorer.
Sometimes it’s bearable, but most of the time it’s not. I say enough is enough !

A couple of days ago, I had to create some web application with a very rich client side UI.
It worked like a charm in Google Chrome, Firefox… but IE7, after few dozens of nyroModal popups it just went dead.

Most of the styles are gone, JavaScript functions began to throw exceptions till it just stoped working, decided it can’t tolerate this kind of abuse any more and closed it self without any warning.

The first thing i did is to open Performance Monitor and what I see… every nyroModal popup i open cost me about 5Mb, so after a few clicks my IE7 virtual memory was about 789Mb. Terrifying, isn’t it ?

IE7 Memory Leak

I’ve searched a bit and found the source of this problem was in one (of many) memory leaks IE7 proudly has – cleaning memory for removed HTML elements.

And now the fix.

1). Open your jQuery.js and find the next lines of code

    jQuery.extend({
        cache: {},

and add new function “discardElement”

    jQuery.extend({
        cache: {},

        discardElement: function(element) {
            var jqGCID = 'jqGarbageCollector';
            var jqGC = document.getElementById(jqGCID);
            if (!jqGC) {
                jqGC = document.createElement('div');
                jqGC.id = jqGCID;
                jqGC.style.display = 'none';
                document.body.appendChild(jqGC);
            }

            // place the element to the Garbage Collector
            // and clear it's HTML contents
            jqGC.appendChild(element);
            jqGC.innerHTML = '';
        },

2). Find the next lines of code in the opened jquery.js

	remove: function( selector ) {
		if ( !selector || jQuery.filter( selector, [ this ] ).length ) {
			// Prevent memory leaks
			jQuery( "*", this ).add([this]).each(function(){
				jQuery.event.remove(this);
				jQuery.removeData(this);
			});
			if (this.parentNode)
				this.parentNode.removeChild( this );
		}
	},

and replace “this.parentNode.removeChild( this );”
with “jQuery.discardElement(this);”

	remove: function( selector ) {
		if ( !selector || jQuery.filter( selector, [ this ] ).length ) {
			// Prevent memory leaks
			jQuery( "*", this ).add([this]).each(function(){
				jQuery.event.remove(this);
				jQuery.removeData(this);
			});
			if (this.parentNode)
				// this.parentNode.removeChild( this );
				jQuery.discardElement(this);
		}
	},

That’s it, now you (and every plugin) can do $(‘element’).remove() without being worry IE will eat all of your memory.

VN:F [1.7.7_1013]
Rating: 4.4/5 (12 votes cast)
IE Memory Leak - jQuery Fix4.4512

A few posts you might find interesting:

  1. jTemplates – jQuery Template Engine
  2. Javascript function context, “apply” method and lost “this” object
  3. Javascript pseudo protocol (is EVIL)
  4. Script as blocking element and dynamic script loading using document.write
  5. IETester – Multiple Internet Explorer versions on the same PC

  1. July 12th, 2009 at 22:18 | #1

    One problem, this won’t work in an XHTML environment because there is no such thing as a <DIV/> tag, only a <div/> tag. Please learn to use lowercase letters when using document.createElement.

    UN:F [1.7.7_1013]
    Rating: 3.4/5 (8 votes cast)
  2. July 12th, 2009 at 22:27 | #2

    @Elijah Grey
    My bad, fixed it to lowercase “div”
    Thanks for noticing that

    UA:F [1.7.7_1013]
    Rating: 4.0/5 (3 votes cast)
  3. David
    July 12th, 2009 at 22:29 | #3

    @Elijah Grey

    l***r

    UN:F [1.7.7_1013]
    Rating: 1.4/5 (9 votes cast)
    • July 12th, 2009 at 22:37 | #4

      We sincerely appreciate your taking time to provide your comments and feedback, but Bad words will get filtered, and offensive comments will be removed.

      UA:F [1.7.7_1013]
      Rating: 0.0/5 (0 votes cast)
  4. July 12th, 2009 at 22:37 | #5

    I don’t think it matters at all. It will work with both DIV and div just fine.
    By the way, if you check tagName property you will always get DIV

    UN:F [1.7.7_1013]
    Rating: 5.0/5 (4 votes cast)
  5. July 12th, 2009 at 22:43 | #6

    @maksik
    You are probably right, but Elijah has a good point about XHTML and lowercase in general, though for JavaScript it makes no difference at all.

    UA:F [1.7.7_1013]
    Rating: 5.0/5 (3 votes cast)
  6. July 13th, 2009 at 01:30 | #7

    Excellent work on the plugin! I actually wrote a post about this very issue but thought it wasn’t a memory leak but rather IE lacked the ability to remove any dynamically generated DOM elements. I should have taken the time to write a plugin for this, but now it seems I can borrow on the mind of another brilliant mind!

    A link to my post on this topic if you are interested – post a link to your post!
    http://www.desmoinesmashups.com/blog/archive/2009/04/21/Cleanup-for-dynamically-generated-DOM-elements-in-IE.html

    UN:F [1.7.7_1013]
    Rating: 5.0/5 (1 vote cast)
  7. mathiev
    July 14th, 2009 at 00:55 | #8

    Hi, I have created a website, which uses jquery to update different parts on a webpage. everything is tabular data. I refresh parts of my webpage (tabs) without leaving the page dynamically (every 2 sec). if i keep it open for a long time in IE6/7/8 it grows around 1.4GB in main memory. I have modifed my js files as you said here. but I dont know how to call/use $(’element’).remove() when when to call. can you show me an simple example?
    waiting for reply…
    Thanks a lot
    -Mathiev

    UN:F [1.7.7_1013]
    Rating: 0.0/5 (0 votes cast)
  8. mathiev
    July 14th, 2009 at 00:58 | #9

    Just an update for above Question, I ask server to send me xml files which i supply to jquery grids.

    jQuery(“#Log”).jqGrid({
    url: ‘LogFile.xml’,
    datatype: ‘xml’,
    mtype: ‘GET’,
    xmlReader: {
    root: “Rows”,
    row: “Row”,
    repeatitems: false,
    id: “asin”
    },

    colNames: ['Log Entries'],
    colModel: [{ name: "LogEntry", index: 'LogEntry', width: 1300, sortable: false}],
    imgpath: ‘jsFiles/theme/basicGrid/images’,
    loadui: ‘disable’,
    height: ‘100%’,
    caption: ‘Log View’
    });

    UN:F [1.7.7_1013]
    Rating: 0.0/5 (0 votes cast)
  9. July 14th, 2009 at 02:17 | #10

    Is this problem fixed in IE8?

    UN:F [1.7.7_1013]
    Rating: 0.0/5 (0 votes cast)
  10. Jesse
    July 14th, 2009 at 02:27 | #11

    @Elijah Grey Please learn to use lowercase letters when using document.createElement?

    Please learn that where to put the slash in the closing tags.

    UN:F [1.7.7_1013]
    Rating: 3.0/5 (2 votes cast)
  11. July 14th, 2009 at 07:12 | #12

    @Keith Petersen
    When i tested it (on beta) the bug was still there.

    UA:F [1.7.7_1013]
    Rating: 0.0/5 (0 votes cast)
  12. July 14th, 2009 at 07:17 | #13

    @mathiev
    Actually i don’t think jqGrid is using $(‘element’).remove() before updating the content. Try to find the exact place where the plugin updating the content and just use :
    var jqGridContainer = document.getElementById(‘#yourjqGridContainerID’);
    jqGridContainer .innerHTML = ”;

    UA:F [1.7.7_1013]
    Rating: 0.0/5 (0 votes cast)
  13. mathiev
    July 14th, 2009 at 20:12 | #14

    This is the place in my code where I am reloading the grid data.

    var l;
    var ltimeout = 2000;
    function RefreshLogGrid()
    {
    jQuery(“#Log”).trigger(“reloadGrid”);
    jQuery(“#Log”).setGridHeight(‘auto’);

    l = setTimeout(“RefreshLogGrid()”, ltimeout);
    }

    where ltimeout (2sec) is refresh time and this is grid location with ID is as follows

    it is updating data correctly. but where should i use

    var jqGridContainer = document.getElementById(“log123″);
    jqGridContainer .innerHTML = ”;

    if i use like this

    var l;
    var ltimeout = 2000;
    function RefreshLogGrid()
    {

    var jqGridContainer = document.getElementById(“log123″);
    jqGridContainer .innerHTML = ”;

    jQuery(“#Log”).trigger(“reloadGrid”);
    jQuery(“#Log”).setGridHeight(‘auto’);

    l = setTimeout(“RefreshLogGrid()”, ltimeout);
    }

    I dont see any entry in my jqGrid :-(
    any idea? how to fix this memory leak bug.

    - Mathiev.

    UN:F [1.7.7_1013]
    Rating: 0.0/5 (0 votes cast)
  14. July 14th, 2009 at 20:47 | #15

    @mathiev
    What is “log123″, i see that the container’s ID is ‘Log’ (“#Log”)
    What exactly the code of “reloadGrid” ?

    UA:F [1.7.7_1013]
    Rating: 0.0/5 (0 votes cast)
  15. mathiev
    July 15th, 2009 at 00:58 | #16

    log123 is id, where #Log is grid_id.
    and jQuery(”#Log”).trigger(”reloadGrid”);
    uses standard lib downloaded from JQ
    jquery-1.3.2.min.js

    UN:F [1.7.7_1013]
    Rating: 0.0/5 (0 votes cast)
  16. mathiev
    July 15th, 2009 at 00:58 | #17

    log123 is div id

    UN:F [1.7.7_1013]
    Rating: 0.0/5 (0 votes cast)
    • July 15th, 2009 at 01:02 | #18

      From what i understand you are cleaning the ‘log123′ which contains the grid.
      Clean the grid (‘#log’) instead, otherwise you are removing the ‘#Log’ element.

      UA:F [1.7.7_1013]
      Rating: 0.0/5 (0 votes cast)
  17. mathiev
    July 15th, 2009 at 01:01 | #19

    Hi Xander,
    Actually I was looking for the solution and I found 1 webpage

    http://dev.jquery.com/ticket/1233

    which explains same problem as me. but I am not sure how to call

    “GarbageCollect?(); ” from my jscript which will release all IE memory (like clicking refresh button)

    UN:F [1.7.7_1013]
    Rating: 0.0/5 (0 votes cast)
  18. July 15th, 2009 at 01:06 | #20

    @mathiev
    Look at my previous reply, as i mentioned – you are probably cleaning the wrong div

    UA:F [1.7.7_1013]
    Rating: 0.0/5 (0 votes cast)
  19. mathiev
    July 15th, 2009 at 18:01 | #21

    Its not working either. If I do that I am getting following error message

    this.parentNode is null

    UN:F [1.7.7_1013]
    Rating: 0.0/5 (0 votes cast)
  20. July 15th, 2009 at 18:08 | #22

    @mathiev
    It’s a bit tricky to solve a problem without seeing the whole picture.
    this.parentNode will throw exception if you are passing an empty (or non-existent) selector.
    Just Debug the code and check what is passed to the function

    UA:F [1.7.7_1013]
    Rating: 0.0/5 (0 votes cast)
  21. July 20th, 2009 at 19:46 | #23

    Hi Xander,

    Thanks very much for this post, it is quite helpful. Have you discussed any of this with the jQ devs? Is a fix destined for “stock” jQ?

    Thanks,
    Jim

    UN:F [1.7.7_1013]
    Rating: 0.0/5 (0 votes cast)
  22. July 20th, 2009 at 20:01 | #24

    @Jim
    I’m glad to hear you find it useful and helpful.

    No, I didn’t discussed about it with jQuery Team, but you right – I should and will.

    UA:F [1.7.7_1013]
    Rating: 0.0/5 (0 votes cast)
  23. July 20th, 2009 at 20:16 | #25

    @Jim
    Opened a new ticket at jQuery Bug Tracker.
    Ticket #4929

    UA:F [1.7.7_1013]
    Rating: 5.0/5 (1 vote cast)
  24. July 20th, 2009 at 20:20 | #26

    Thanks Xander

    UN:F [1.7.7_1013]
    Rating: 0.0/5 (0 votes cast)
  25. July 21st, 2009 at 15:55 | #27

    Xander,

    I’ve applied your patch to some jQuery which is using jQuery UI’s dialog and leaks memory in IE7. Opening a dialog raises the memory usage, and closing it never returns that memory. So after several dialogs are opened and closed, IE is killing the machine again. Sadly, your patch made no difference. I looked at the source of the dialog code and it does use .remove(). Have you used your patch successfully with UI’s dialog?

    I’ll keep poking around.

    Thanks,
    Jim

    UN:F [1.7.7_1013]
    Rating: 0.0/5 (0 votes cast)
  26. July 21st, 2009 at 16:02 | #28

    @Jim
    No, not with UI, but as long it uses jQuery .remove() it should work.
    Please make sure you are referencing the modified jQuery.js and not the minified or packed version.

    UA:F [1.7.7_1013]
    Rating: 0.0/5 (0 votes cast)
  27. July 21st, 2009 at 16:07 | #29

    Thanks for the fast reply. I am definitely referencing the proper file as I adding debugging into it when I saw it wasn’t working. The methods are being entered, but IE is still chomping memory.

    We’ll keep digging on our end as perhaps it’s something which we’re putting into the dialog which is exacerbating the issue.

    Jim

    UN:F [1.7.7_1013]
    Rating: 0.0/5 (0 votes cast)
  28. July 21st, 2009 at 23:00 | #30

    Hello Xander,

    At the risk of being a pest, I’d like to show you a test a came up with for pure jQuery UI dialogs.

    At http://jaaulde.com/test_bed/ie_mem_leak/ you’ll see a ‘patched’ and ‘unpatched’ directory. They contain the same code, except that one is pointing at a version of jQuery with your fix patched in, the other is not.

    As far as I can tell, in both versions, IE is never letting go of even the small amount of memory which a very simple dialog requires. However, I am not the best at measuring performance like this, so maybe I am missing something. With that in mind, do you mind taking a look at my link and seeing if you think it is working?

    Thanks very much,
    Jim

    UN:F [1.7.7_1013]
    Rating: 0.0/5 (0 votes cast)
  29. July 22nd, 2009 at 01:23 | #31

    @Jim
    Hi, i’ve checked your files and it seems that the memory leak you are dealing with is not related to the one i’m trying to solve.
    This one leaks even in Google Chrome…

    As i mentioned before this is a solution for one (of many) memory leaks IE7 proudly has..

    I think the cause for this specific leak is what called circular references (in jQuery UI) and i’m sorry but i can’t help you with this one…

    UA:F [1.7.7_1013]
    Rating: 0.0/5 (0 votes cast)
  30. July 22nd, 2009 at 01:34 | #32

    Thanks very much, Xander. I appreciate your time.

    UN:F [1.7.7_1013]
    Rating: 0.0/5 (0 votes cast)
  31. July 30th, 2009 at 18:06 | #33

    Great article that aggregates fixes to all the various jQuery memory leaks dealing with UpdatePanel refreshes at http://www.quattrosource.com/2009/07/fixing-jquery-memory-leaks-in-asp-net/

    UN:F [1.7.7_1013]
    Rating: 0.0/5 (0 votes cast)
  32. August 4th, 2009 at 16:32 | #34

    Thanks. Great article.
    We’re finding we get memory leaks simply by setting elements via the $(“#id#).text() function so hopefully that’ll help us out!

    UN:F [1.7.7_1013]
    Rating: 0.0/5 (0 votes cast)
  33. Soumen
    September 14th, 2009 at 09:22 | #35

    Hi Xander,
    I appreciate your post as over net I browsed and have not found any fix. Everyone talks about the bug but only few talk about the fix.
    My request to you is that, since for my web application I am not using JQuery so could you please provide me or give me idea how to implement the same GC logic in plain JavaScript so that I can out it to my webpage(s) and get rid on IE memory leak problem.

    Regards,
    Soumen
    India-Hyderabad

    UN:F [1.7.7_1013]
    Rating: 0.0/5 (0 votes cast)
  34. September 14th, 2009 at 20:29 | #36

    @Soumen
    The “discardElement” function is not using jQuery, so just replace the “discardElement: function(element)” with “function discardElement(element)” if you want it to be standalone.

    UA:F [1.7.7_1013]
    Rating: 5.0/5 (1 vote cast)
  35. February 22nd, 2010 at 15:18 | #37

    Has this issue been taken care of in jquery 1.4? …something like a patch (similar to yours) to that effect

    UN:F [1.7.7_1013]
    Rating: 0.0/5 (0 votes cast)
  1. July 14th, 2009 at 03:31 | #1
  2. July 15th, 2009 at 16:37 | #2
  3. July 16th, 2009 at 09:31 | #3
  4. July 21st, 2009 at 23:08 | #4

Subscribe without commenting

SEO Powered by Platinum SEO from Techblissonline