Monday, July 21st, 2008

Increase DOM Node Insertion Performance

Category: JavaScript, 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) ); } [/javascript]

Posted by Ben Galbraith at 9:00 am
6 Comments

++++-
4.1 rating from 34 votes

6 Comments »

Comments feed TrackBack URI

More web performance tips (including using the DocumentFragment interface) can be found there:

http://www.slideshare.net/julien.lecomte/high-performance-ajax-applications

Cheers!

Comment by jlecomte — July 21, 2008

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.)

Comment by Schill — July 21, 2008

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.

Comment by AnM8tR — July 21, 2008

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

Comment by jdalton — July 21, 2008

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

Comment by p01 — July 21, 2008

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).

Comment by matanlurey — July 22, 2008

Leave a comment

You must be logged in to post a comment.