Home | History | Annotate | Download | only in dom-perf
      1 /*
      2  * Copyright (C) 2009 Google Inc. All rights reserved.
      3  *
      4  * Redistribution and use in source and binary forms, with or without
      5  * modification, are permitted provided that the following conditions are
      6  * met:
      7  *
      8  *     * Redistributions of source code must retain the above copyright
      9  * notice, this list of conditions and the following disclaimer.
     10  *     * Redistributions in binary form must reproduce the above
     11  * copyright notice, this list of conditions and the following disclaimer
     12  * in the documentation and/or other materials provided with the
     13  * distribution.
     14  *     * Neither the name of Google Inc. nor the names of its
     15  * contributors may be used to endorse or promote products derived from
     16  * this software without specific prior written permission.
     17  *
     18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     22  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     29  */
     30 
     31 // DOMWalk - a benchmark for walking the DOM
     32 //
     33 // This benchmark tests different mechanisms for touching every element
     34 // in a section of the DOM. The elements are created from JavaScript causing
     35 // them to be pre-wrapped.
     36 //
     37 // Tests small iterations and large iterations to see if there is a difference.
     38 
     39 
     40 // We use two mechanisms to walk the DOM, and then
     41 // verify that both yield the same result.
     42 var __num_nodes = 0;
     43 
     44 // We create a table to iterate as part of this test.
     45 // For now it's just a big table with lots of elements.
     46 function DOMWalk_CreateTable(height, width) {
     47     var table = document.getElementById("fake_dom");
     48     if (table) {
     49         // clear out existing table
     50         while (table.rows.length > 0)
     51             table.deleteRow(0);
     52     } else {
     53         var doc = document;
     54         table = doc.createElement("table");
     55         table.id = "fake_dom";
     56         table.border = 1;
     57 
     58         for (var row = 0; row < height; row++) {
     59             var row_object = doc.createElement("tr");
     60             for (var column = 0; column < width; column++) {
     61                 var col_object = doc.createElement("td");
     62                 var text = document.createTextNode(row.toString() + "." + column.toString());
     63                 col_object.appendChild(text);
     64                 row_object.appendChild(col_object);
     65             }
     66             table.appendChild(row_object);
     67         }
     68         var content = document.getElementById("benchmark_content");
     69         content.appendChild(table);
     70         var html = content.innerHTML;
     71         var width = content.clientWidth;
     72     }
     73     return table;
     74 }
     75 
     76 function DOMWalk_SetupSmall() {
     77     // Creates a table with 100 nodes.
     78     DOMWalk_CreateTable(10, 10);
     79 }
     80 
     81 function DOMWalk_SetupLarge() {
     82     // Creates a table with 4000 nodes.
     83     DOMWalk_CreateTable(200, 200);
     84 }
     85 
     86 // Walks the DOM via getElementsByTagName.
     87 function DOMWalk_ByTagName(table) {
     88     var items = table.getElementsByTagName("*");
     89     var item;
     90     var length = items.length;
     91     for (var index = 0; index < length; index++)
     92         item = items[index];
     93 
     94     // Return the number of nodes seen.
     95     return items.length;
     96 }
     97 
     98 function DOMWalk_ByTagNameDriver(loops) {
     99     var table = document.getElementById("benchmark_content");
    100     for (var loop = 0; loop < loops; loop++)
    101         __num_nodes = DOMWalk_ByTagName(table);
    102 }
    103 
    104 function DOMWalk_ByTagNameSmall() {
    105     // This test runs in a short time.  We loop a few times in order to avoid small time measurements.
    106     DOMWalk_ByTagNameDriver(1000);
    107 }
    108 
    109 function DOMWalk_ByTagNameLarge() {
    110     DOMWalk_ByTagNameDriver(1);
    111 }
    112 
    113 function DOMWalk_Recursive(node) {
    114     // Count Element Nodes only.
    115     // IE does not define the Node constants.
    116     var count = (node.nodeType == /* Node.ELEMENT_NODE */ 1) ? 1 : 0;
    117 
    118     var child = node.firstChild;
    119     while (child !== null) {
    120         count += DOMWalk_Recursive(child);
    121         child = child.nextSibling;
    122     }
    123 
    124     return count;
    125 }
    126 
    127 // Walks the DOM via a recursive walk
    128 function DOMWalk_RecursiveDriver(loops) {
    129     var table = document.getElementById("benchmark_content");
    130     for (var loop = 0; loop < loops; loop++) {
    131         var count = DOMWalk_Recursive(table) - 1;  // don't count the root node.
    132         if (count != __num_nodes || count === 0)
    133             throw "DOMWalk failed!  Expected " + __num_nodes + " nodes but found " + count + ".";
    134     }
    135 }
    136 
    137 function DOMWalk_RecursiveSmall() {
    138     // This test runs in a short time.  We loop a few times in order to avoid small time measurements.
    139     DOMWalk_RecursiveDriver(200);
    140 }
    141 
    142 function DOMWalk_RecursiveLarge() {
    143     // Only iterate once over the large DOM structures.
    144     DOMWalk_RecursiveDriver(1);
    145 }
    146 
    147 
    148 var DOMWalkTest = new BenchmarkSuite('DOMWalk', [
    149     new Benchmark("DOMWalkByTag (100 nodes)", DOMWalk_ByTagNameSmall, DOMWalk_SetupSmall),
    150     new Benchmark("DOMWalkRecursive (100 nodes)", DOMWalk_RecursiveSmall, DOMWalk_SetupSmall),
    151     new Benchmark("DOMWalkByTag (4000 nodes)", DOMWalk_ByTagNameLarge, DOMWalk_SetupLarge),
    152     new Benchmark("DOMWalkRecursive (4000 nodes)", DOMWalk_RecursiveLarge, DOMWalk_SetupLarge)
    153 ]);
    154