innerHTML vs className and NodeValue (v2)

Revision 2 of this benchmark created by Luke Page on


Description

Test to compare making a dom update with innerHTML compared to changing a className and setting a text nodes nodeValue.

Preparation HTML

<div id="testcenter1"></div>
<div id="testcenter2"></div>
<script>
  var createStyles = function(selectorArray) {
   var i, j, cssText = "",
       char1 = 'a',
       char2 = 'a',
       colours = ["red", "green", "Blue", "violet"],
       currentClassName = "",
       selector = "",
       incrementClass = function() {},
       usedClasses = [];
  
   for (i = 0; i < selectorArray.length; i++) {
    for (j = 0; j < selectorArray[i].count; j++) {
     currentClassName = char1 + char2;
     if (char2 === 'z') {
      char1 = char1.addOne();
      char2 = 'a';
     } else {
      char2 = char2.addOne();
     }
     if (!selectorArray[i].unused) {
      usedClasses.push(currentClassName);
     }
     selector = selectorArray[i].selector.replace("{0}", currentClassName);
     cssText += selector + " {\n background: " + colours[Math.floor(Math.random() * 4)] + "; }\n\n";
    }
   }
  
   addStyleTag(cssText);
   return usedClasses;
  };
  
  String.prototype.addOne = function() {
   return String.fromCharCode(this.charCodeAt(0) + 1);
  };
  
  var addStyleTag = function(cssText) {
  
   var ss = document.createElement('style');
   ss.setAttribute("type", "text/css");
  
   if (ss.styleSheet) { // IE
    ss.styleSheet.cssText = cssText;
   } else {
    ss.appendChild(document.createTextNode(cssText));
   }
   var head = document.getElementsByTagName('head')[0];
   head.appendChild(ss);
  };
  
  
  var usedClasses1 = createStyles([{
   selector: ".tc1{0}",
   count: 25
  }]);
  
  var usedClasses2 = createStyles([{
   selector: "#testcenter2 div.testcontainer table span.{0}",
   count: 625
  }]);
  
  var testcenter1 = document.getElementById("testcenter1");
  var testcenter2 = document.getElementById("testcenter2");
  
  var createRowsUIH = function(testcontainer, classes, noOfSpans, classesPrefix) {
   var tbl = document.createElement("table"),
       tbody = document.createElement("tbody"),
       i, j, k, tr, td, dcTb = document.createElement("div"),
       tb, onClick = function() {
     alert("a");
       };
   noOfSpans = noOfSpans || 1;
   classesPrefix = classesPrefix || "";
  
   tbl.className = "tbl";
   tbl.id = "mytb";
   testcontainer.appendChild(tbl);
  
   tbl.appendChild(tbody);
  
   for (i = 0; i < 5; i++) {
    tr = "<table><tbody><tr>";
    for (j = 0; j < 5; j++) {
     td = "<td>";
     for (k = 0; k < noOfSpans; k++) {
      td += "<span class=\"" + classesPrefix + classes[Math.floor(Math.random() * classes.length)] + "\">_</span>";
     }
     td += "</td>";
     tr = tr + td;
    }
    tr = tr + "</tr></tbody></table>";
    dcTb.innerHTML = tr;
    tr = dcTb.childNodes[0].childNodes[0].childNodes[0];
  
    tbody.appendChild(tr);
   }
  };
  
  createRowsUIH(testcenter1, usedClasses1, 1, "tc1");
  createRowsUIH(testcenter2, usedClasses2);
  
  var cellTest1 = testcenter1.childNodes[0].childNodes[0].childNodes[3].childNodes[3];
  
  var cellTest2 = testcenter2.childNodes[0].childNodes[0].childNodes[3].childNodes[3];
  
  var alternate = false;
</script>

Test runner

Ready to run.

Testing in
TestOps/sec
change using innerHTML
if (alternate) {
 cellTest1.innerHTML = '<span class="tc1_ax">New Text</span>';
 cellTest2.innerHTML = '<span class="ax">New Text</span>';
} else {
 cellTest1.innerHTML = '<span class="tc1_ab">_</span>';
 cellTest2.innerHTML = '<span class="ab">_</span>';
}

alternate = !alternate;
ready
innerHTML and className
if (alternate) {
 cellTest1.childNodes[0].innerHTML = 'New Text';
 cellTest1.childNodes[0].className = 'tc1_ax';
 cellTest2.childNodes[0].innerHTML = 'New Text';
 cellTest2.childNodes[0].className = 'ax';
} else {
 cellTest1.childNodes[0].innerHTML = '_';
 cellTest1.childNodes[0].className = 'tc1_ab';
 cellTest2.childNodes[0].innerHTML = '_';
 cellTest2.childNodes[0].className = 'ab';
}

alternate = !alternate;
ready
nodeValue and className
if (alternate) {
 cellTest1.childNodes[0].childNodes[0].nodeValue = 'New Text';
 cellTest1.childNodes[0].className = 'tc1_ax';
 cellTest2.childNodes[0].childNodes[0].nodeValue = 'New Text';
 cellTest2.childNodes[0].className = 'ax';
} else {
 cellTest1.childNodes[0].childNodes[0].nodeValue = '_';
 cellTest1.childNodes[0].className = 'tc1_ab';
 cellTest2.childNodes[0].childNodes[0].nodeValue = '_';
 cellTest2.childNodes[0].className = 'ab';
}
ready

Revisions

You can edit these tests or add more tests to this page by appending /edit to the URL.

  • Revision 2: published by Luke Page on