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 // Tests looking for ids in different DOM trees full of div elements.
     32 function GetElementTest(size, appendStyle, treeStyle) {
     33     var me = this;
     34     this.size = size;
     35     this.appendStyle = appendStyle;
     36     this.ids = null;
     37     this.treeStyle = treeStyle;
     38     this.name = (this.Sizes.length > 1 ? (me.size + ", ") : "") + me.appendStyle + ", " + me.treeStyle;
     39 
     40     this.setupDOM = function() {
     41         var domTree = me.getDOMTree().cloneNode(true);
     42         this.suite.benchmarkContent.appendChild(domTree);
     43         me.nodesFound = 0;
     44         me.ids = me.getIds();
     45         return domTree;
     46     };
     47 
     48     this.setupHTML = function() {
     49         this.suite.benchmarkContent.innerHTML = me.getDOMTree().innerHTML;
     50         me.nodesFound = 0;
     51         me.ids = me.getIds();
     52     };
     53 
     54     if (this.appendStyle == "DOM")
     55         this.Setup = this.setupDOM;
     56     else
     57         this.Setup = this.setupHTML;
     58 
     59     this.Test = function(handle) {
     60         var kIterations = 1;
     61         for (var iterations = 0; iterations < kIterations; iterations++) {
     62             me.nodesFound = 0;
     63             for (var i = 0, len = me.ids.length; i < len; i++) {
     64                 var div = document.getElementById(me.ids[i]);
     65                 var nodeName = div.nodeName;
     66                 me.nodesFound++;
     67             }
     68         }
     69     };
     70 
     71     this.Cleanup = function(handle) {
     72         var expectedCount = me.ids.length;
     73         if (me.nodesFound != expectedCount)
     74             throw "Wrong number of nodes found: " + me.nodesFound + " expected: " + expectedCount;
     75     };
     76 
     77     this.GetBenchmark = function() {
     78         return new Benchmark(this.name, this.Test, this.Setup, this.Cleanup);
     79     };
     80 
     81     this.getIdsFromTree = function(parent, maxNumberOfNodes) {
     82         var allDivs = parent.getElementsByTagName("div");
     83         var len = allDivs.length;
     84         var skip;
     85         if (maxNumberOfNodes >= allDivs.length)
     86             skip = 0;
     87         else
     88             skip = Math.floor(allDivs.length / maxNumberOfNodes) - 1;
     89         var ids = [];
     90         var l = 0;
     91         for (var i = 0, len = allDivs.length; i < len && l < maxNumberOfNodes; i += (skip + 1)) {
     92             var div = allDivs[i];
     93             ids.push(div.id);
     94             l++;
     95         }
     96         return ids;
     97     };
     98 
     99     this.createTreeAndIds = function() {
    100         var maxNumberOfNodes = 20000;
    101         var domTree;
    102 
    103         if (me.treeStyle == "dups") {
    104             // We use four of the trees for the dups style,
    105             // so they get too big if you use the full size for the bigger trees
    106             switch (me.size) {
    107             case "small":
    108                 domTree = BenchmarkSuite.prototype.generateSmallTree();
    109                 break;
    110             case "medium":
    111                 domTree = BenchmarkSuite.prototype.generateDOMTree(15, 12, 4);
    112                 break;
    113             case "large":
    114                 domTree = BenchmarkSuite.prototype.generateDOMTree(26, 26, 1);
    115                 break;
    116             }
    117         } else {
    118             switch (me.size) {
    119             case "small":
    120                 domTree = BenchmarkSuite.prototype.generateSmallTree();
    121                 break;
    122             case "medium":
    123                 domTree = BenchmarkSuite.prototype.generateMediumTree();
    124                 break;
    125             case "large":
    126                 domTree = BenchmarkSuite.prototype.generateLargeTree();
    127                 break;
    128             }
    129         }
    130 
    131         var allDivs = domTree.getElementsByTagName("*");
    132         var len = allDivs.length;
    133         var modBy;
    134         if (maxNumberOfNodes >= allDivs.length)
    135             modBy = 1;
    136         else
    137             modBy = Math.floor(allDivs.length / maxNumberOfNodes);
    138         var ids = [];
    139         for (var i = 0, len = allDivs.length; i < len; i++) {
    140             var mod = i % modBy;
    141             var div = allDivs[i];
    142             if (mod == 0 && ids.length < maxNumberOfNodes) {
    143                 if (div.id && div.id != "")
    144                     ids.push(div.id);
    145             } else if (me.treeStyle == "sparse")
    146                 div.id = null;
    147         }
    148 
    149         if (me.treeStyle == "dups") {
    150             var newRoot = document.createElement("div");
    151             for (var i = 0; i < 5; i++)
    152                 newRoot.appendChild(domTree.cloneNode(true));
    153             domTree = newRoot;
    154         }
    155 
    156         var treeAndIds = {
    157             tree: domTree,
    158             ids: ids
    159         };
    160         return treeAndIds;
    161     };
    162 
    163     this.getTreeAndIds = function() {
    164         var treeAndIdsMap = me.TreeAndIds[me.size];
    165         if (!treeAndIdsMap) {
    166             treeAndIdsMap = {};
    167             me.TreeAndIds[me.size] = treeAndIdsMap;
    168         }
    169         var treeAndIds = treeAndIdsMap[me.treeStyle];
    170         if (!treeAndIds) {
    171             treeAndIds = me.createTreeAndIds();
    172             treeAndIdsMap[me.treeStyle] = treeAndIds;
    173         }
    174         return treeAndIds;
    175     };
    176 
    177     this.getDOMTree = function() {
    178         var treeAndIds = me.getTreeAndIds();
    179         return treeAndIds.tree;
    180     };
    181 
    182     this.getIds = function() {
    183         var treeAndIds = me.getTreeAndIds();
    184         return treeAndIds.ids;
    185     };
    186 }
    187 
    188 GetElementTest.prototype = {
    189     // Different sizes are possible, but we try to keep the runtime and memory
    190     // consumption reasonable.
    191     Sizes: ["medium"],
    192     TreeStyles: ["sparse", "dense", "dups"],
    193     TreeAndIds: {},
    194     AppendStyles: ["DOM", "HTML"]
    195 };
    196 
    197 // Generate the matrix of all benchmarks
    198 var benchmarks = [];
    199 GetElementTest.prototype.Sizes.forEach(function(size) {
    200     GetElementTest.prototype.AppendStyles.forEach(function(appendStyle) {
    201         GetElementTest.prototype.TreeStyles.forEach(function(treeStyle) {
    202             benchmarks.push(new GetElementTest(size, appendStyle, treeStyle).GetBenchmark());
    203         });
    204     });
    205 });
    206 
    207 var GetElementTest = new BenchmarkSuite("Get Elements", benchmarks);
    208