Monday, July 21st, 2008
Increase DOM Node Insertion Performance
John Resig continues his streak of compelling blog entries with "DOM DocumentFragments" where he shows that:
A method that is largely ignored in modern web development can provide some serious (2-3x) performance improvements to your DOM manipulation.
The technique shown is compatible across a large swath of modern browsers, including our friend IE6. Here's an example of using DocumentFragments:
-
-
var div = document.getElementsByTagName("div");
-
var fragment = document.createDocumentFragment();
-
for ( var e = 0; e <elems.length; e++ ) {
-
fragment.appendChild( elems[e] );
-
}
-
-
for ( var i = 0; i <div.length; i++ ) {
-
div[i].appendChild( fragment.cloneNode(true) );
-
}
-












More web performance tips (including using the DocumentFragment interface) can be found there:
http://www.slideshare.net/julien.lecomte/high-performance-ajax-applications
Cheers!
Indeed! :) documentFragment is my response to folks who commonly compare .innerHTML vs. appendChild(), where their examples include one .innerHTML update vs. document.body.appendChild(node) in a “for” loop or some such. (One would expect the latter will be slower of course, given the browser will be attempting to reflow the document with each loop iteration vs. once with a write to .innerHTML.)
I’m afraid this test is misleading.
This blog did however get me to run some quick tests. All done on FF3 – not real official or anything. Each test I created 1000 divs with a small amount of text:
docFrag: 76ms
appendChild: 64ms
innerHTML: 40ms
The difference is, I created a container div, and inserted 1000 children and then appended the container to the body. This is much faster than appending every single child to the body one at a time. Appending the container to the body first, then appending 1000 children is 83ms.
“createDocumentFragment” is useful if you need to insert multiple “loose” children directly into a node. However, I usally prepare my code with containers that can be replaced.
Prototype has recently had a patch re-submitted that uses documentFragment to increase the speed of Element#insert, Element#update, and Element#replace.
http://prototype.lighthouseapp.com/projects/8886/tickets/227-optimize-element-update-element-insert-and-element-replace-via-documentfragment .
The original ticket /w benchmarks http://dev.rubyonrails.org/ticket/11468 .
This offsers a huge performance boost to IE, taking delays of 60 seconds or more down to 1 second (equal to other browsers).
Hip Tip: If you cache the documentFragment you can use it over and over again without creating new ones.
- JDD
DocumentFragment are the way to go when developing web applications for limited devices and mobile phones. See [1,2]
Also notice that since the documentFragment is not in the document itself, CSS are not applied to its elements. This means that you won’t be able to fiddle with the getComputedStyle( aChildOfTheDocumentFragment ); and other style properties of the children of a documentFrament.
AnM8tR: But in a more realistic scenario you would have a deeper DOM (sub)tree with various text nodes and attributes to touch. On devices and mobile phones, using a documentFragment vs many appendChild directly in the document makes a real difference.
[1] Efficient Javascript @ dev.opera
[2] Cross device development techinques @ dev.opera
I think this is an interesting discovery, I myself wasn’t aware the browser supported DocumentFragment object. I would say, however, that the most important thing in DOM node construction is to append child nodes to a non-inserted parent node (such as a div).