Javascript HTML Construction Benchmark

DOM vs. innerHTML

A while ago I did some experiments on creating an XML document by constructing a string versus creating it by using the DOM methods, and I found that the latter was faster than the former. QuirksMode by Peter Paul Koch has a Javascript benchmark for creating HTML however, which claims that using innerHTML is 35 times as fast compared to using the DOM (although I can’t reproduce that number in Internet Explorer 8 (IE 7 mode), it is ‘only’ 22 times faster here).

People keep mentioning performance as an argument for using innerHTML, citing that article, so I thought I’d go and see what the reason was for the difference between his and my findings. It turns out that the benchmark has some flaws that skew the results very much in favour of innerHTML, which I’ll point out.

What the benchmark does is, it creates a 50×50 table with a ‘*’ in each cell using different approaches. Basically, there are two tests of importance here, which are:

  1. String construction (using arrays and array.join('')) and parsing the result with innerHTML
  2. Construction using the DOM methods such as document.createElement('div')

1. Content is never escaped

First of all, QuirksMode’s innerHTML tests append strings as follows:

string.push('<td>*</td>');

However, realistically the value of a cell will not be a fixed value, but the value of some variable, which also needs to be escaped to prevent parsing errors. This leads to the following modification:

string.push('<td>');
string.push(escapeHTML('*'));
string.push('</td>');

The escapeHTML function looks like this:

function escapeHTML(str) {
    return str.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;');
}

This change makes the strings + innerHTML version roughly twice as slow, but more representative of how it is actually used. The DOM methods already do this implicitly, so there is no change in performance there.

2. Selective HTML usage

Secondly, the QuirksMode test makes use of HTML table elements. This also skews the test results a lot, because when changing them to divs, the test performs 4 times better in IE! This is what the changed code looks like:

var x = oDocument.createElement('div');
    var y = x.appendChild(oDocument.createElement('div'));
    for (var i=0;i<50;i++)
    {
        var z = y.appendChild(oDocument.createElement('div'));
        for (var j=0;j<50;j++)
        {
            var a = z.appendChild(oDocument.createElement('div'));

I wonder if there is some workaround or flag you can set to make it perform more like IE 5.5 in this regard (which is much faster, according to QuirksMode).

Also note that this test only tests element creation — in practise you will also be setting attributes, and when expanding the test with tests for adding attributes using string construction versus the (simple) setAttribute() method, the relative performance of the DOM version might show further improvements (I didn’t test this though).

3. XML is much faster than HTML

Finally, the HTML DOM is much, much slower than the XML DOM. When using the XML DOM, it turns out to be faster than constructing a string. The following creates and serializes a document in a cross-browser way:

if (document.all) {
    var oDocument = new ActiveXObject('Microsoft.XMLDOM');
    oDocument.async = false;
    oDocument.preserveWhiteSpace = true;
    oDocument.validateOnParse = false;
    oDocument.resolveExternals = false;
    oDocument.loadXML('<root/>');
} else {
    var oDocument = new DOMParser().parseFromString('<root/>', 'application/xml');
}

if (document.all) {
    document.getElementById('writeroot').innerHTML = oDocument.xml;
} else {
    document.getElementById('writeroot').innerHTML = new XMLSerializer().serializeToString(oDocument);
}

So, to summarize, when using XML there is really no excuse for constructing a string instead of using the DOM. When using HTML, constructing a string is indeed faster, however innerHTML is inherently less robust than using DOM operations, and the difference is not so big as sketched by QuirksMode. Additionally, if your application is really performance-critical, it would be even faster to construct the document in XML, and then serialising/reparsing or transforming it to HTML.

The final test results are:

Internet Explorer 8 (IE 7 mode) results
Method Running time Relative performance
DOM, using table elements (in original test) 978 ms 2274
DOM, using divs 233 ms 542
DOM, using XML 43 ms 100
Strings, using innerHTML, not escaped (in original test) 47 ms 109
Strings, using innerHTML, escaped 63 ms 147
Firefox 3.0 RC1 results
Method Running time Relative performance
DOM, using table elements (in original test) 119 ms 188
DOM, using divs 110 ms 174
DOM, using XML 63 ms 100
Strings, using innerHTML, not escaped (in original test) 32 ms 51
Strings, using innerHTML, escaped 71 ms 113

Note that the results with ‘in original test’ in parenthesis are results from running the original benchmark.

Update: Caching the regular expressions for escaping HTML strings made IE perform a little faster; updated the measurements.