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