www.webdeveloper.com
Page 1 of 2 12 LastLast
Results 1 to 15 of 25

Thread: bizarre memory leak... can anyone figure it out?

  1. #1
    Join Date
    Nov 2002
    Posts
    36

    Question bizarre memory leak... can anyone figure it out?

    The leak is classic: introduce a dynamic script DOM element, let the script execute, then remove the DOM node. Rinse. Repeat. The problem is the DOM element will not free and I cannot see any circular reference. I've tried all the tricks and can't solve it. The leak exists in both ie 6-8 and firefox.

    My kit does real time updates without requiring a page reload/refresh so the leak is bothersome and can grow quickly.

    I have tried moving the node to a garbage pool DIV and setting the innerHTML to "". I have tried the destroy() approach. I have stood on my head and walked with my ears.

    All you need are these two small files:

    File 1 leak.js:
    // all the file contains is this one comment line!

    File 2 leak.html:
    Code:
    <html>
    <SPAN id='leakid'><SCRIPT language='JavaScript'>
    
    // CALLED EVERY 500 ms FROM TIMER
    function getUpdate() {
        var mySpan = document.getElementById('leakid');
    
        // WHACK THE OLD ONE FROM LAST GO AROUND
        var oldNode = document.getElementById('myUpdater');
        if (oldNode) {
            oldNode.parentNode.removeChild(oldNode);
            oldNode = null;
        } 
        
        // LOAD A NEW ONE
        var newNode = document.createElement('script');
        newNode.type = 'text/javascript';
        newNode.src = 'leak.js';
        newNode.id = 'myUpdater';
        mySpan.appendChild(newNode);
        newNode = null;
        mySpan = null;
        return;
    }
    
    </SCRIPT></SPAN>
    <BODY bgcolor="#4682B4" leftmargin="2" marginheight="0" marginwidth="0" topmargin="2" onload="getUpdate(); timerInterval = setInterval('getUpdate()', 500);">
    </BODY></HTML>

  2. #2
    Join Date
    Dec 2003
    Location
    Bucharest, ROMANIA
    Posts
    15,428
    The SCRIPT element does not support the standard core HTML attributes (id, class, style, title). Neither do BASE, HEAD, HTML, META, PARAM, STYLE and TITLE elements.

    So, the SCRIPT element can not bear an id, so that there is nothing to be found using getElementById() method. As a result the SCRIPT element is not removed. Try to use getElementsByTagName() instead, and the index of the element within that collection.
    Last edited by Kor; 02-03-2011 at 04:28 AM.

  3. #3
    Join Date
    Nov 2002
    Posts
    36
    Thanks for the reply!

    Still leaks like mad. BTW it was finding the script using the getbyid. There has got to be a way to do this, right?

    My original code remembered the child node from the createelement directly:

    Code:
    var myScript = null;
    
    // CALLED EVERY 500 ms FROM TIMER
    function getUpdate() {
        var mySpan = document.getElementById('leakid');
    
        // WHACK THE OLD ONE FROM LAST GO AROUND
        if (myScript ) {
            myScript .parentNode.removeChild(myScript );
            myScript = null;
        } 
        
        // LOAD A NEW ONE
        myScript = document.createElement('script');
        myScript .type = 'text/javascript';
        myScript .src = 'leak.js';
        myScript .id = 'myUpdater';
        mySpan.appendChild(myScript );
        mySpan = null;
        return;
    }

  4. #4
    Join Date
    Dec 2005
    Posts
    2,984
    I have no idea, but did you try using global vars for the node objects so they are never 'held on to'....how do you know you're observing a memory leak? I couldn't observe anything (browser slowness, increased memory usage in the process) when I tested in firefox or IE on windows.
    I've switched careers...
    I'm NO LONGER a scientist,
    but now a web developer...
    awesome.

  5. #5
    Join Date
    Mar 2010
    Posts
    672
    http://www.softwareverify.com/javasc...ory/index.html

    Check out their javascript memory leak monitor. Its a bit of a learning curve for their app but it goes indepth and helps you find the source.

  6. #6
    Join Date
    Dec 2003
    Location
    Bucharest, ROMANIA
    Posts
    15,428
    About the id in SCRIPT tag:

    "The core standard HTML/XHTML attributes (class, id, style, title) are not valid in base, head, html, meta, param, script, style, and title elements."

    See also:
    http://www.w3schools.com/tags/ref_st...attributes.asp

  7. #7
    Join Date
    Mar 2009
    Posts
    495
    I can't say that this is the case, but I suspect that the problem is that you are removing the old script but you are not removing its children, who in essence become stranded, and are never removed.

    The code within the <script> tags consists of one or more textNodes. Destroying the parent doesn't necessarily mean that they will be destroyed. And since you are doing this every half second I can see why it consumes more and more memory.

  8. #8
    Join Date
    Nov 2002
    Posts
    36
    Thanks Kor,

    I believe you, but it leaks using any method I can see, that was just the most recent spin on things

    In my previous response I posted code that just remembers the node added using a varaible. That too leaks. So does finding by tag. FOr the elements by tag I created a little div to hold the script and deleted all script tag items from it (and for god measure set the div inner HTML to ""). Leaks.


    Quote Originally Posted by Kor View Post
    About the id in SCRIPT tag:

    "The core standard HTML/XHTML attributes (class, id, style, title) are not valid in base, head, html, meta, param, script, style, and title elements."

    See also:
    http://www.w3schools.com/tags/ref_st...attributes.asp

  9. #9
    Join Date
    Nov 2002
    Posts
    36
    I tried that in the following way: Make a div just to hold the script. Then on cleanup time, remove any children of the script node and any children of the div.

    but it still leaks. AAAARRRRGGGHHHH.

    Code:
    var myScript = null;
    
    // CALLED EVERY 500 ms FROM TIMER
    function getUpdate() {
        var mySpan = document.getElementById('leakid');
    
         if (scriptDiv== null) {
            scriptDiv= document.createElement('DIV');
            scriptDiv.id = 'scriptBucket';
            scriptDiv.style.display = 'none';
            document.body.appendChild(scriptDiv);
        }
    
        // WHACK THE OLD ONE FROM LAST GO AROUND
        if (myScript) {
            while (myScript.lastChild) {
                myScript.removeChild(scriptNode.myScript);
            }
            if (myScript.parentNode != null)
                myScript.parentNode.removeChild(myScript);
            delete myScript;
            myScript= null;
        }
        
        while (scriptDiv.lastChild) {
            scriptDiv.removeChild(scriptDiv.lastChild);
        }
        scriptDiv.innerHTML = "";
    
    
        // LOAD A NEW ONE
        myScript = document.createElement('script');
        myScript.type = 'text/javascript';
        myScript.src = 'leak.js';
        myScript.id = 'myUpdater';
        scriptDiv.appendChild(myScript );
        mySpan = null;
        return;
    }
    Quote Originally Posted by Tcobb View Post
    I can't say that this is the case, but I suspect that the problem is that you are removing the old script but you are not removing its children, who in essence become stranded, and are never removed.

    The code within the <script> tags consists of one or more textNodes. Destroying the parent doesn't necessarily mean that they will be destroyed. And since you are doing this every half second I can see why it consumes more and more memory.

  10. #10
    Join Date
    Nov 2002
    Posts
    36
    Quote Originally Posted by aj_nsc View Post
    I have no idea, but did you try using global vars for the node objects so they are never 'held on to'....how do you know you're observing a memory leak? I couldn't observe anything (browser slowness, increased memory usage in the process) when I tested in firefox or IE on windows.

    I had a typo in my second post in the thread, so I bet the javascript aborted.

    Note the extra spaces before the period (.):
    Code:
        
    myScript .type = 'text/javascript';
    myScript .src = 'leak.js';
    myScript .id = 'myUpdater';
    sorry about that.

  11. #11
    Join Date
    Mar 2009
    Posts
    495
    Just for cheap thrills, what if you tried it after commenting out the line:
    Code:
    myScript.src = 'leak.js';
    Thats the only thing I can think of, however unlikely, that could be interfering with the garbage collection process.

  12. #12
    Join Date
    Nov 2002
    Posts
    36
    Quote Originally Posted by Tcobb View Post
    Just for cheap thrills, what if you tried it after commenting out the line:
    Code:
    myScript.src = 'leak.js';
    Thats the only thing I can think of, however unlikely, that could be interfering with the garbage collection process.
    Interestingly enough it still leaks. Firefox leaks at a slower rate. Maybe IE does too but it doesn't look like it.

    So how do you folks add dynamic scripts wihtout leaking?

  13. #13
    Join Date
    Feb 2003
    Location
    Michigan, USA
    Posts
    5,773
    *** removed my original thoughts because I just realized leak.js only contains a JavaScript comment ***

    @Kor: While the HTML standard says the standard attributes don't apply to SCRIPT elements, you can still specify an Id and use getElementById to grab a reference to that node. That does work in browsers, even though it is technically invalid HTML.
    Last edited by toicontien; 02-03-2011 at 06:36 PM.

  14. #14
    Join Date
    Nov 2002
    Posts
    36
    [QUOTE=toicontien;1137274]The memory taken up by the script source of leak.js is probably not being garbage collected. Look at the code in that file, and see if any of that code is holding pointers to other objects in memory. That's probably the source of the "leak" and it's also probably the intended behavior of the browser. I'm not convinced the memory for the SCRIPT node is what's causing this behavior.
    QUOTE]


    Toicontien,

    thanks. I removed all javascript from leak.js until it was just a single comment to explicitly remove that concern. So the script loaded is literally just a single comment line. Now in the application of course its a relevant script but I am just stripping away to identify the leak.

  15. #15
    Join Date
    Feb 2003
    Location
    Michigan, USA
    Posts
    5,773
    I did just think of something. I banged my head against a memory leak for a LONG time once, and discovered it was actually a result of having Firebug or the Safari/Chome debug tools open. Try disabling them and performing your test.

Thread Information

Users Browsing this Thread

There are currently 1 users browsing this thread. (0 members and 1 guests)

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
HTML5 Development Center



Recent Articles