[483] | 1 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" |
---|
| 2 | "http://www.w3.org/TR/html4/strict.dtd"> |
---|
| 3 | <html> |
---|
| 4 | <head> |
---|
| 5 | <title>Builder Perf Tests</title> |
---|
| 6 | <script type="text/javascript" src="../../../dojo/dojo.js"></script> |
---|
| 7 | <script type="text/javascript" src="../Builder.js"></script> |
---|
| 8 | <script type="text/javascript" src="lipsum.js"></script> |
---|
| 9 | <script type="text/javascript"> |
---|
| 10 | |
---|
| 11 | dojo.addOnLoad(function(){ |
---|
| 12 | dojo.byId("run").disabled=""; |
---|
| 13 | dojo.connect(dojo.byId("run"), |
---|
| 14 | "onclick", |
---|
| 15 | function(evt) { |
---|
| 16 | setTimeout(function() { |
---|
| 17 | var words = parseInt(dojo.byId("numWords").value) || 10; |
---|
| 18 | var iters = parseInt(dojo.byId("numIters").value) || 1000; |
---|
| 19 | var dict = eval(dojo.byId("dict").value); |
---|
| 20 | buildAndRunSet(words, dict, iters); |
---|
| 21 | }, 0); |
---|
| 22 | }); |
---|
| 23 | }); |
---|
| 24 | |
---|
| 25 | function element(tag, textOrChildOrArray) { |
---|
| 26 | var e = document.createElement(tag); |
---|
| 27 | function append(n) { |
---|
| 28 | if(dojo.isString(n)){ |
---|
| 29 | n = document.createTextNode(n); |
---|
| 30 | } |
---|
| 31 | e.appendChild(n); |
---|
| 32 | } |
---|
| 33 | if(dojo.isArray(textOrChildOrArray)) { |
---|
| 34 | dojo.forEach(textOrChildOrArray, append); |
---|
| 35 | }else{ |
---|
| 36 | append(textOrChildOrArray); |
---|
| 37 | } |
---|
| 38 | return e; |
---|
| 39 | } |
---|
| 40 | |
---|
| 41 | function log(t) { |
---|
| 42 | dojo.byId("mess").innerHTML = t; |
---|
| 43 | console.log(t); |
---|
| 44 | } |
---|
| 45 | |
---|
| 46 | function reportRun(results){ |
---|
| 47 | var runs = results.runs |
---|
| 48 | var report = element("dl", |
---|
| 49 | element("dt", |
---|
| 50 | "Run with " + results.words + " words, " + |
---|
| 51 | results.iterations + " iterations, for loop overhead of " + |
---|
| 52 | results.overhead + ", average phrase of " + |
---|
| 53 | results.wordSize + " characters")); |
---|
| 54 | |
---|
| 55 | runs.sort(function(a,b) { return a.time - b.time; }); |
---|
| 56 | dojo.forEach(runs, function(r) { |
---|
| 57 | report.appendChild(element("dd", r.time + " - " + r.name)); |
---|
| 58 | }); |
---|
| 59 | |
---|
| 60 | dojo.body().appendChild(report); |
---|
| 61 | } |
---|
| 62 | |
---|
| 63 | function runTest(test, iterations, expected) { |
---|
| 64 | var i; |
---|
| 65 | if(expected != test()) throw new Error("Test failed expecting " + expected + ", got " + test()); |
---|
| 66 | var start = new Date().getTime(), end; |
---|
| 67 | for(i=0; i < iterations; i++){ |
---|
| 68 | test(); |
---|
| 69 | } |
---|
| 70 | end = new Date().getTime(); |
---|
| 71 | return end-start; |
---|
| 72 | } |
---|
| 73 | |
---|
| 74 | function runSet(set, iterations){ |
---|
| 75 | |
---|
| 76 | function averagePhraseLen(words) { |
---|
| 77 | var sizes = dojo.map(words, function(w) { return w.length; }); |
---|
| 78 | var total = 0; |
---|
| 79 | dojo.forEach(sizes, function(s) { total += s; }); |
---|
| 80 | return total / sizes.length; |
---|
| 81 | } |
---|
| 82 | |
---|
| 83 | var tests = set.tests.concat(); //copy tests |
---|
| 84 | var resultSet = {}; |
---|
| 85 | resultSet.words = set.words.length; |
---|
| 86 | resultSet.overhead = runTest(set.overhead, iterations); |
---|
| 87 | resultSet.iterations = iterations; |
---|
| 88 | resultSet.wordSize = averagePhraseLen(set.words); |
---|
| 89 | var runs = []; |
---|
| 90 | |
---|
| 91 | function _run() { |
---|
| 92 | var t = tests.pop(); |
---|
| 93 | try { |
---|
| 94 | log("Running " + t.name); |
---|
| 95 | if(t) runs.push({ name: t.name, time: runTest(t.test, iterations, set.expected)}); |
---|
| 96 | } catch(e) { |
---|
| 97 | console.error("Error running " + t.name); |
---|
| 98 | console.error(e); |
---|
| 99 | } |
---|
| 100 | if(tests.length > 0) { |
---|
| 101 | setTimeout(_run, 0); |
---|
| 102 | } |
---|
| 103 | else { |
---|
| 104 | log("Done!"); |
---|
| 105 | resultSet.runs = runs; |
---|
| 106 | reportRun(resultSet); |
---|
| 107 | dojo.publish("perf/run/done"); |
---|
| 108 | } |
---|
| 109 | } |
---|
| 110 | setTimeout(_run, 25); |
---|
| 111 | } |
---|
| 112 | |
---|
| 113 | function buildTestSet(numWords, dict) { |
---|
| 114 | var words = [], i, dl = dict.length; |
---|
| 115 | for(i = numWords; i > 0; i-=dl) { |
---|
| 116 | if(i >= dl) { words = words.concat(dict); } |
---|
| 117 | else { words = words.concat(dict.slice(-i)); } |
---|
| 118 | } |
---|
| 119 | if(words.length != numWords) throw new Error("wrong number of words, got " + words.length + ", expected " + numWords); |
---|
| 120 | |
---|
| 121 | var expected = words.join(""); |
---|
| 122 | |
---|
| 123 | var _builder = new dojox.string.Builder(); |
---|
| 124 | |
---|
| 125 | return { |
---|
| 126 | tests: [ |
---|
| 127 | { |
---|
| 128 | name: "concatFor", |
---|
| 129 | test: function() { |
---|
| 130 | var s = ""; |
---|
| 131 | for(var i = 0; i < words.length; i++) { |
---|
| 132 | s = s.concat(words[i]); |
---|
| 133 | } |
---|
| 134 | return s; |
---|
| 135 | } |
---|
| 136 | }, |
---|
| 137 | /* |
---|
| 138 | { |
---|
| 139 | name: "concatForAlias", |
---|
| 140 | test: function() { |
---|
| 141 | var s = "", w = words, l = w.length; |
---|
| 142 | for(var i = 0; i < l; i++) { |
---|
| 143 | s = s.concat(w[i]); |
---|
| 144 | } |
---|
| 145 | return s; |
---|
| 146 | } |
---|
| 147 | }, |
---|
| 148 | { |
---|
| 149 | name: "concatForEach", |
---|
| 150 | test: function() { |
---|
| 151 | var s = ""; |
---|
| 152 | dojo.forEach(words, function(w) { |
---|
| 153 | s = s.concat(w); |
---|
| 154 | }); |
---|
| 155 | return s; |
---|
| 156 | } |
---|
| 157 | }, |
---|
| 158 | */ |
---|
| 159 | { |
---|
| 160 | name: "concatOnce", |
---|
| 161 | test: function() { |
---|
| 162 | var s = ""; |
---|
| 163 | s = String.prototype.concat.apply(s, words); |
---|
| 164 | return s; |
---|
| 165 | } |
---|
| 166 | }, |
---|
| 167 | { |
---|
| 168 | name: "builderFor", |
---|
| 169 | test: function() { |
---|
| 170 | var b = new dojox.string.Builder(); |
---|
| 171 | for(var i = 0; i < words.length; i++) { |
---|
| 172 | b.append(words[i]); |
---|
| 173 | } |
---|
| 174 | return b.toString(); |
---|
| 175 | } |
---|
| 176 | }, |
---|
| 177 | { |
---|
| 178 | name: "builderForMulti", |
---|
| 179 | test: function() { |
---|
| 180 | var b = new dojox.string.Builder(); |
---|
| 181 | for(var i = 0; i < words.length; i+=2) { |
---|
| 182 | b.append(words[i], words[i+1]); |
---|
| 183 | } |
---|
| 184 | return b.toString(); |
---|
| 185 | } |
---|
| 186 | }, |
---|
| 187 | /* |
---|
| 188 | { |
---|
| 189 | name: "builderForEach", |
---|
| 190 | test: function() { |
---|
| 191 | var b = new dojox.string.Builder(); |
---|
| 192 | dojo.forEach(words, function(w) { |
---|
| 193 | b.append(w); |
---|
| 194 | }); |
---|
| 195 | return b.toString(); |
---|
| 196 | } |
---|
| 197 | }, |
---|
| 198 | */ |
---|
| 199 | { |
---|
| 200 | name: "builderReusedFor", |
---|
| 201 | test: function() { |
---|
| 202 | _builder.clear(); |
---|
| 203 | for(var i = 0; i < words.length; i++) { |
---|
| 204 | _builder.append(words[i]); |
---|
| 205 | } |
---|
| 206 | return _builder.toString(); |
---|
| 207 | } |
---|
| 208 | }, |
---|
| 209 | { |
---|
| 210 | name: "builderOnce", |
---|
| 211 | test: function() { |
---|
| 212 | var b = new dojox.string.Builder(); |
---|
| 213 | b.appendArray(words); |
---|
| 214 | return b.toString(); |
---|
| 215 | } |
---|
| 216 | }, |
---|
| 217 | { |
---|
| 218 | name: "builderReusedOnce", |
---|
| 219 | test: function() { |
---|
| 220 | _builder.clear(); |
---|
| 221 | _builder.appendArray(words); |
---|
| 222 | return _builder.toString(); |
---|
| 223 | } |
---|
| 224 | }, |
---|
| 225 | { |
---|
| 226 | name: "plusFor", |
---|
| 227 | test: function() { |
---|
| 228 | var s = ""; |
---|
| 229 | for(var i = 0; i < words.length; i++) { |
---|
| 230 | s += words[i]; |
---|
| 231 | } |
---|
| 232 | return s; |
---|
| 233 | } |
---|
| 234 | }, |
---|
| 235 | /* |
---|
| 236 | { |
---|
| 237 | name: "plusForAlias", |
---|
| 238 | test: function() { |
---|
| 239 | var s = "", w = words, l = w.length; |
---|
| 240 | for(var i = 0; i < l; i++) { |
---|
| 241 | s += w[i]; |
---|
| 242 | } |
---|
| 243 | return s; |
---|
| 244 | } |
---|
| 245 | }, |
---|
| 246 | { |
---|
| 247 | name: "plusForEach", |
---|
| 248 | test: function() { |
---|
| 249 | var s = ""; |
---|
| 250 | dojo.forEach(words, function(w) { s += w; }); |
---|
| 251 | return s; |
---|
| 252 | } |
---|
| 253 | },*/ |
---|
| 254 | { |
---|
| 255 | name: "joinOnce", |
---|
| 256 | test: function() { |
---|
| 257 | return words.join(""); |
---|
| 258 | } |
---|
| 259 | }, |
---|
| 260 | { |
---|
| 261 | name: "joinFor", |
---|
| 262 | test: function() { |
---|
| 263 | var a = []; |
---|
| 264 | for(var i = 0; i < words.length; i++) { |
---|
| 265 | a.push(words[i]); |
---|
| 266 | } |
---|
| 267 | return a.join(""); |
---|
| 268 | } |
---|
| 269 | }/*, |
---|
| 270 | { |
---|
| 271 | name: "joinForAlias", |
---|
| 272 | test: function() { |
---|
| 273 | var a = [], w = words, l = w.length; |
---|
| 274 | for(var i = 0; i <l; i++) { |
---|
| 275 | a.push(w[i]); |
---|
| 276 | } |
---|
| 277 | return a.join(""); |
---|
| 278 | } |
---|
| 279 | }, |
---|
| 280 | { |
---|
| 281 | name: "joinForEach", |
---|
| 282 | test: function() { |
---|
| 283 | var a = []; |
---|
| 284 | dojo.forEach(words, function(w) { a.push(w); }); |
---|
| 285 | return a.join(""); |
---|
| 286 | } |
---|
| 287 | } |
---|
| 288 | */ |
---|
| 289 | ], |
---|
| 290 | words: words, |
---|
| 291 | expected: expected, |
---|
| 292 | overhead: function() { |
---|
| 293 | var w = words; |
---|
| 294 | var l = w.length; |
---|
| 295 | for(var i=0; i < l; i++) { |
---|
| 296 | ident(w[i]); |
---|
| 297 | } |
---|
| 298 | } |
---|
| 299 | }; |
---|
| 300 | } |
---|
| 301 | |
---|
| 302 | function buildAndRunSet(words, dict, times) { |
---|
| 303 | runSet(buildTestSet(words, dict), times); |
---|
| 304 | } |
---|
| 305 | |
---|
| 306 | function runSuite() { |
---|
| 307 | var suite = [ |
---|
| 308 | { |
---|
| 309 | words: 2, |
---|
| 310 | times: 10000 |
---|
| 311 | }, |
---|
| 312 | { |
---|
| 313 | words: 4, |
---|
| 314 | times: 10000 |
---|
| 315 | }, |
---|
| 316 | { |
---|
| 317 | words: 8, |
---|
| 318 | times: 10000 |
---|
| 319 | }, |
---|
| 320 | { |
---|
| 321 | words: 16, |
---|
| 322 | times: 10000 |
---|
| 323 | }, |
---|
| 324 | { |
---|
| 325 | words: 32, |
---|
| 326 | times: 10000 |
---|
| 327 | }, |
---|
| 328 | { |
---|
| 329 | words: 64, |
---|
| 330 | times: 10000 |
---|
| 331 | }, |
---|
| 332 | { |
---|
| 333 | words: 128, |
---|
| 334 | times: 1000 |
---|
| 335 | }, |
---|
| 336 | { |
---|
| 337 | words: 256, |
---|
| 338 | times: 1000 |
---|
| 339 | }, |
---|
| 340 | { |
---|
| 341 | words: 512, |
---|
| 342 | times: 1000 |
---|
| 343 | }, |
---|
| 344 | { |
---|
| 345 | words: 1024, |
---|
| 346 | times: 1000 |
---|
| 347 | }, |
---|
| 348 | { |
---|
| 349 | words: 2048, |
---|
| 350 | times: 1000 |
---|
| 351 | }, |
---|
| 352 | { |
---|
| 353 | words: 4096, |
---|
| 354 | times: 100 |
---|
| 355 | }, |
---|
| 356 | { |
---|
| 357 | words: 8192, |
---|
| 358 | times: 100 |
---|
| 359 | } |
---|
| 360 | ]; |
---|
| 361 | |
---|
| 362 | var totalSuite = dojo.map(suite, function(s) { var n = {}; dojo.mixin(n,s); n.dict = lipsum; return n; }); |
---|
| 363 | totalSuite = totalSuite.concat(dojo.map(suite, function(s) { var n = {}; dojo.mixin(n,s); n.dict = lipsumLong; return n; })); |
---|
| 364 | console.log(totalSuite); |
---|
| 365 | |
---|
| 366 | var handle = dojo.subscribe("perf/run/done", _run); |
---|
| 367 | dojo.subscribe("perf/run/done", function(){ console.log("perf run done"); }); |
---|
| 368 | |
---|
| 369 | function _run() { |
---|
| 370 | var t = totalSuite.shift(); |
---|
| 371 | if(t) buildAndRunSet(t.words, t.dict, t.times); |
---|
| 372 | if(totalSuite.length == 0) dojo.unsubscribe(handle); |
---|
| 373 | } |
---|
| 374 | |
---|
| 375 | _run(); |
---|
| 376 | } |
---|
| 377 | |
---|
| 378 | function ident(i) { return i; } |
---|
| 379 | </script> |
---|
| 380 | <style type="text/css"> |
---|
| 381 | html { |
---|
| 382 | font-family: Lucida Grande, Tahoma; |
---|
| 383 | } |
---|
| 384 | div { margin-bottom: 1em; } |
---|
| 385 | #results { |
---|
| 386 | border: 1px solid #999; |
---|
| 387 | border-collapse: collapse; |
---|
| 388 | } |
---|
| 389 | #results caption { |
---|
| 390 | font-size: medium; |
---|
| 391 | font-weight: bold; |
---|
| 392 | } |
---|
| 393 | #results td, #results th { |
---|
| 394 | text-align: right; |
---|
| 395 | width: 10em; |
---|
| 396 | font-size: small; |
---|
| 397 | white-space: nowrap; |
---|
| 398 | } |
---|
| 399 | #wordsCol { background: yellow; } |
---|
| 400 | td.max { color: red; font-weight: bold; } |
---|
| 401 | td.min { color: green; font-weight: bold; } |
---|
| 402 | </style> |
---|
| 403 | </head> |
---|
| 404 | <body> |
---|
| 405 | <table> |
---|
| 406 | <tr><td><label for="numWords">Words</label></td><td><input type="text" id="numWords" value="100"/></td></tr> |
---|
| 407 | <tr><td><label for="numIters">Iterations</label></td><td><input type="text" id="numIters" value="1000"/></td></tr> |
---|
| 408 | <tr><td><label for="dict">Dictionary</label></td><td><input type="text" id="dict" value="lipsum"></td></tr> |
---|
| 409 | <tr><td></td><td><button id="run" disabled>Run Tests!</button></td></tr> |
---|
| 410 | </table> |
---|
| 411 | <div id="mess"></div> |
---|
| 412 | </body> |
---|
| 413 | </html> |
---|