Increasing appendChild Performance with DOM Tricks
Tuesday, July 22nd, 2008A recent blog post by John Resig has outlined a performance sensitive method of appending many elements to your document. His suggestion, using DocumentFragment as the container object to which to append all child nodes, is backed by some pretty impressive benchmarks. The most drastic performance improvements by using this method of appending objects to the document are witnessed by Internet Explorer and Safari, IE6 improved by 65%, IE7 by 73% and Safari by 71%.
In looking at his code used to test this, some users argued that his test cases were slightly skewed as the container object was handled in two different manners. In the case using appendChild for each childNode, the container object was looked up on the gathered div array using the loops index to point to the value. Why not store it they asked? This led to accusations that in the case that switches to using the DocumentFragment, the benefit may be derived from the idea that the container object is accessed as a stored value inside the loop. This also lead to questioning that, in his second case, the majority of the content was being appended to an object not yet living in the DOM.
This begs the questions– Does the perceived performance increase being witnessed in this case come from the fact that the container object is detached from the DOM while being appended? I decided to dive in…
The Procedure
To do this, I set up three cases and tested in both Firefox 2 and Internet Explorer 7. Knowing that the original idea, looping through the divs and accessing the container as div[i], was the least desirable, I decided to toss that out the window from the get go.
For my first case, "Appending to Attached Div", I stuck with the structure of John's control case, in which the nodes are appended directly to an element still active in the DOM. The one tweak I did make, was to store a reference to the container div rather than using div[i]. This was as simple as setting var container = div[i] inside the first loop. This resulted in:
var div = document.getElementsByTagName("div");
for ( var i = 0; i < div.length; i++ ) {
var container = div[i];
for ( var e = 0; e < elems.length; e++ ) {
container.appendChild( elems[e].cloneNode(true) );
}
}
Case 2 involved using John's DocumentFragment method verbatim. This presented an element of control to my test in relation to his.
In the 3rd case, I decided to use the method just like in case 2, however rather than using createDocumentFragment() I created a table element with createElement("table"). This was stored as the container to which to append the children elements.
var div = document.getElementsByTagName("div");
var container = document.createElement("table");
for ( var e = 0; e < elems.length; e++ ) {
container.appendChild( elems[e] );
}
for ( var i = 0; i < div.length; i++ ) {
div[i].appendChild( container.cloneNode(true) );
}
My Results
The results are as follow, with time to execute represented (in seconds).
| Appending to Attached Div | Appending to Document Fragment | Appending to Table | |
| FF2 | 2.046 | .430 | .481 |
| IE7 | 4.134 | 3.256 | 3.715 |
In Conclusion
After going through this test, I decided that John was definitely onto something. He found the most optimized way to approach this method. Between the two cases in which I appended the content to an object that was not yet in the DOM (for the elems array), the DocumentFragment method proved to be more efficient by about 10%. The one thing I would like to add–that I feel my test proved–is that when you are doing the majority of your appending, you should be doing it to an object that is not currently contained within the DOM. You can then later append that object to its destination container.
P.S. On a humorous note, the original case that John was using in his test took far too long for me to run with the sheer volume of div's I was trying to populate. In fact, it caused Firefox to prompt me to stop the script and Internet Explorer just locked up… Definitely make sure you use one of these presented solutions for appending nodes to improve your performance!

