Hello and welcome to our community! Is this your first visit?
Register
Enjoy an ad free experience by logging in. Not a member yet? Register.
Results 1 to 11 of 11
  1. #1
    Smokes a Lot
    Join Date
    Jul 2003
    Location
    CA, USA
    Posts
    1,594
    Thanks
    5
    Thanked 20 Times in 20 Posts

    DOM Insertion Order Leak Model

    If I understand this article correctly (refering to the last example on the page: Figure 3. DOM Insertion Order Leak Model)

    http://msdn.microsoft.com/library/en...k_patterns.asp

    If I wanted to create a table through the dom, each node's parent node must be appended to the document before the child node can be appended to it. (That's what I got out of it any way)

    So I couldn't do this:

    Code:
    var table=document.createElement('table');
    var thead=document.createElement('thead');
    
    table.appendChild('thead');
    document.documentElement.appendChild(table);
    That would create a memory leak in IE because it creates a temporary document element when you append the thead to the table? Is that what it's saying?

    I ask this because I do something like the above quite frequently. It seems much more difficult to traverse the dom to append to an element you just appended to the document. It basically means I have to give eveery created element an id, which means I'd only be able to use that element a single time once it's appended, or a name, which is still not very friendly. Or I can traverse the child nodes of the appended object, in any case these methods seem far less efficient. Is it really that bad to do it in the manner I listed in my example?

    Thanks,
    Basscyst
    Last edited by Basscyst; 02-06-2006 at 09:32 PM.
    Helping to build a bigger box. - Adam Matthews

  • #2
    Regular Coder
    Join Date
    Aug 2005
    Posts
    282
    Thanks
    0
    Thanked 0 Times in 0 Posts
    the part that gets me in
    Code:
            function CleanMemory()
            {
                var hostElement = document.getElementById("hostElement");
    
                // Do it a lot, look at Task Manager for memory response
    
                for(i = 0; i < 5000; i++)
                {
                    var parentDiv =
                        document.createElement("<div onClick='foo()'>");
                    var childDiv =
                        document.createElement("<div onClick='foo()'>");
    
                    // Changing the order is important, this won't leak
                    hostElement.appendChild(parentDiv);
                    parentDiv.appendChild(childDiv);
                    hostElement.removeChild(parentDiv);
                    parentDiv.removeChild(childDiv);
                    parentDiv = null;
                    childDiv = null;
                }
                hostElement = null;
            }
    is the line
    Code:
                    hostElement.removeChild(parentDiv);
                    parentDiv.removeChild(childDiv);
    I would think that parentDiv would be a null reference after you have removed it?
    But the primary focus is just in the way it is appended.
    because I can do this
    Code:
                    // Changing the order is important, this won't leak
                    hostElement.appendChild(parentDiv);
                    parentDiv.appendChild(childDiv);
                    hostElement.removeChild(parentDiv);
                    //parentDiv.removeChild(childDiv);
                    //parentDiv = null;
                    //childDiv = null;
    and memory is still cleaned up properly.
    Last edited by KC-Luck; 02-06-2006 at 09:53 PM.

  • #3
    Smokes a Lot
    Join Date
    Jul 2003
    Location
    CA, USA
    Posts
    1,594
    Thanks
    5
    Thanked 20 Times in 20 Posts
    So the example I posted would actually be fine if I had defined the document element as a variable first and appended to that variable?

    It just needs to be like this:
    Code:
    var baseobj=document.documentElement;
    var table=document.createElement('table');
    var thead=document.createElement('thead');
    
    baseobj.appendChild(table)
    table.appendChild('thead');
    
    etc . .
    Would I be correct in saying:

    All parent elements of an object must be appended to the document before any objects can be appended to the object?

    If that's the case I think I might be in pretty good shape with the exception of some places where I might be appending text nodes to tds before the td is attached to the tr.

    hostElement.removeChild(parentDiv);
    parentDiv.removeChild(childDiv);
    Yeah that is weird, I wouldn't logically write it in that order. . .I would assume though that the variable still references the object even though it is no longer attached to the document, because doesn't removeChild() return the object removed?

    Thanks,
    Basscyst
    Last edited by Basscyst; 02-06-2006 at 10:41 PM.
    Helping to build a bigger box. - Adam Matthews

  • #4
    Regular Coder
    Join Date
    Aug 2005
    Posts
    282
    Thanks
    0
    Thanked 0 Times in 0 Posts
    Quote Originally Posted by Basscyst
    So the example I posted would actually be fine if I had defined the document element as a variable first and appended to that variable?

    It just needs to be like this:
    Code:
    var baseobj=document.documentElement;
    var table=document.createElement('table');
    var thead=document.createElement('thead');
    
    baseobj.appendChild(table)
    table.appendChild('thead');
    
    etc . .
    You would not want to append directly to the documentElement.
    documentElement = HTMLElement (root)
    you would want to append to the document.getElementsByTagName("body").item(0);
    but, yes you are on the right track.
    Quote Originally Posted by Basscyst
    Would I be correct in saying:

    All parent elements of an object must be appended to the document before any objects can be appended to the object?

    If that's the case I think I might be in pretty good shape with the exception of some places where I might be appending text nodes to tds before the td is attached to the tr.
    Yes, that is how I have understood the article as well.
    Append the node to document, then append other children to it.
    Not the other way around. Don't work with the newly created element in memory, via appending children, before you actually "put" it in the DOM.

    And, yes removeChild(oldNode) does return a reference to the removed element. But, was just weird to then remove children of it, after it was removed? It seems that upon removal, the children of removed node would be gone already

    Just don't like to add extra "bloat" if not a truely needed line of code

  • #5
    Kor
    Kor is offline
    Red Devil Mod Kor's Avatar
    Join Date
    Apr 2003
    Location
    Bucharest, ROMANIA
    Posts
    8,478
    Thanks
    58
    Thanked 379 Times in 375 Posts
    You would not want to append directly to the documentElement.
    documentElement = HTMLElement (root)
    Absolutelly. Appending a table to the documentElement will append the table after the </body> tag, which, of course, you would not to...

    Speaking about leaks... I don't think that in this case the leak (and, sure, why am I wonder? This kinda leak is only in IE... ) is significant. Let's say you create a table (first temporary element) than a tbody(second), than a row (third) thane a cell(forth). Now append the cell (the appending will reduce the temporary objects to three, as the moment you append it, it is not a temporary one). Append the row (2 temporary remains: table and tbody)... and so on...

    I might be wrong, but this is the way I see things... Of course, if you append each element to it's parent the next moment after creating, that it will keep the temporary element to maximum 1, and only from time to time, which will certainly speen the process, but who, for God's sake, wants to create a table with 5000 cells in order to sense the difference?
    Last edited by Kor; 02-07-2006 at 09:53 AM.
    KOR
    Offshore programming
    -*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*

  • #6
    Regular Coder
    Join Date
    Aug 2005
    Posts
    282
    Thanks
    0
    Thanked 0 Times in 0 Posts
    keep in mind, if you change:
    Code:
    document.createElement("<div onClick='foo()'>");
    to
    Code:
    document.createElement("div");
    you will have no leak, either way you append them

  • #7
    Master Coder
    Join Date
    Feb 2003
    Location
    UmeŚ, Sweden
    Posts
    5,575
    Thanks
    0
    Thanked 83 Times in 74 Posts
    They're really not explaining the problem that well. It's got to do with the creation of a closure by creating that event handler.
    liorean <[lio@wg]>
    Articles: RegEx evolt wsabstract , Named Arguments
    Useful Threads: JavaScript Docs & Refs, FAQ - HTML & CSS Docs, FAQ - XML Doc & Refs
    Moz: JavaScript DOM Interfaces MSDN: JScript DHTML KDE: KJS KHTML Opera: Standards

  • #8
    Smokes a Lot
    Join Date
    Jul 2003
    Location
    CA, USA
    Posts
    1,594
    Thanks
    5
    Thanked 20 Times in 20 Posts
    Quote Originally Posted by KC-Luck
    keep in mind, if you change:
    Code:
    document.createElement("<div onClick='foo()'>");
    to
    Code:
    document.createElement("div");
    you will have no leak, either way you append them
    Oh. . .if that's the case it's rare that it's an issue, only when needing to set certain attributes in ie. In any case I understand.

    and yeah, I know i wouldn't append to the documentElement, I was working with an xml document when I wrote this and my brain leaked over.

    Thanks,
    Basscyst
    Last edited by Basscyst; 02-07-2006 at 09:36 PM.
    Helping to build a bigger box. - Adam Matthews

  • #9
    Regular Coder
    Join Date
    Aug 2005
    Posts
    282
    Thanks
    0
    Thanked 0 Times in 0 Posts
    Quote Originally Posted by liorean
    They're really not explaining the problem that well. It's got to do with the creation of a closure by creating that event handler.
    if they want the full explanation basscyst has offered up the URL at topic start.
    Quote Originally Posted by MSDN
    This leak deserves clarification, because our workaround goes against some best practices in IE. The key points to understand about the leak are that DOM elements are being created with scripts already attached. This is actually crucial to the leak, because if we create DOM elements that don't contain any script and attach them together in the same manner we don't have a leak problem. This gives rise to a second workaround that might be even better for larger subtrees (in the example we only have two elements, so building the tree off the primary DOM isn't a performance hit). The second workaround would be to create your elements with no scripts attached initially so that you can safely build your subtree. After you've attached your subtree to the primary DOM, go back and wire up any script events at that point. Remember to follow the principles for circular references and closures so you don't cause a different leak in your code as you hook up your events.
    yes, it is a rare case that such events are wired up as such, so I never give much second-thought to this type of memory leak, but a good one to know, and observe!

  • #10
    jkd
    jkd is offline
    Senior Coder jkd's Avatar
    Join Date
    May 2002
    Location
    metro DC
    Posts
    3,163
    Thanks
    1
    Thanked 18 Times in 18 Posts
    A somewhat-related note:

    Appending nodes to the live DOM (the document) will redraw the affected area, which takes some amount of CPU power. If you're creating many nodes, it is much faster to create the structure in memory, and then append the single parent node to the live DOM, instead of potentially thousands of additions (and thousands of redraws). Even if this way leaks a little in IE, the speed it makes up otherwise I would consider a worthy tradeoff.

  • #11
    Master Coder
    Join Date
    Feb 2003
    Location
    UmeŚ, Sweden
    Posts
    5,575
    Thanks
    0
    Thanked 83 Times in 74 Posts
    KC-Luck: Yeah, that's exactly what I was referring to. It's terribly inspecific. It doesn't in any degree explain what the environment that the closure closes over actually is (I'm pretty sure it's not a straight lexical closure, since you could null all locals to get rid of it in that case, and the code that leaks actually does just that.), nor do they explain that it is in fact just a hidden creation of a closure.

    Edit: Looking closer, I see that they actually do specify it, but not in those words. They explain the scope trickery just before the diagram.


    jkd: Nah, the problem really lies in that people are using the proprietary marked-up-tag syntax to attach the event instead of attaching the event separately. Using the standard DOM tagname-only syntax and attaching the event separately effectively removes this odd kind of closure creation, giving you just a single kind of closures to deal with.
    Last edited by liorean; 02-08-2006 at 01:01 AM.
    liorean <[lio@wg]>
    Articles: RegEx evolt wsabstract , Named Arguments
    Useful Threads: JavaScript Docs & Refs, FAQ - HTML & CSS Docs, FAQ - XML Doc & Refs
    Moz: JavaScript DOM Interfaces MSDN: JScript DHTML KDE: KJS KHTML Opera: Standards


  •  

    Posting Permissions

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