[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 Arguments Tests</title> |
---|
| 6 | <script type="text/javascript" src="../../../dojo/dojo.js" data-dojo-config="isDebug: true"></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 | { |
---|
| 129 | name: "concatFor", |
---|
| 130 | test: function() { |
---|
| 131 | var s = ""; |
---|
| 132 | for(var i = 0; i < words.length; i++) { |
---|
| 133 | s = s.concat(words[i]); |
---|
| 134 | } |
---|
| 135 | return s; |
---|
| 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 | name: "concatOnce", |
---|
| 160 | test: function() { |
---|
| 161 | var s = ""; |
---|
| 162 | s = String.prototype.concat.apply(s, words); |
---|
| 163 | return s; |
---|
| 164 | } |
---|
| 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: "builderFor2Args", |
---|
| 179 | test: function() { |
---|
| 180 | var b = new dojox.string.Builder(), l=words.length, r=words.length%2; |
---|
| 181 | for(var i = 0; i < words.length; i+=2) { |
---|
| 182 | b.append(words[i], words[i+1]); |
---|
| 183 | } |
---|
| 184 | for(i=l-r; i<l; i++){ |
---|
| 185 | b.append(words[i]); |
---|
| 186 | } |
---|
| 187 | return b.toString(); |
---|
| 188 | } |
---|
| 189 | }, |
---|
| 190 | { |
---|
| 191 | name: "builderFor3Args", |
---|
| 192 | test: function() { |
---|
| 193 | var b = new dojox.string.Builder(), l=words.length, r=words.length%3; |
---|
| 194 | for(var i = 0; i < l-r; i+=3) { |
---|
| 195 | b.append(words[i], words[i+1], words[i+2]); |
---|
| 196 | } |
---|
| 197 | for(i=l-r; i<l; i++){ |
---|
| 198 | b.append(words[i]); |
---|
| 199 | } |
---|
| 200 | return b.toString(); |
---|
| 201 | } |
---|
| 202 | }, |
---|
| 203 | { |
---|
| 204 | name: "builderFor4Args", |
---|
| 205 | test: function() { |
---|
| 206 | var b = new dojox.string.Builder(), l=words.length, r=words.length%4; |
---|
| 207 | for(var i = 0; i < l-r; i+=4) { |
---|
| 208 | b.append(words[i], words[i+1], words[i+2], words[i+3]); |
---|
| 209 | } |
---|
| 210 | for(i=l-r; i<l; i++){ |
---|
| 211 | b.append(words[i]); |
---|
| 212 | } |
---|
| 213 | return b.toString(); |
---|
| 214 | } |
---|
| 215 | }, |
---|
| 216 | { |
---|
| 217 | name: "builderFor5Args", |
---|
| 218 | test: function() { |
---|
| 219 | var b = new dojox.string.Builder(), l=words.length, r=words.length%5; |
---|
| 220 | for(var i = 0; i < l-r; i+=5) { |
---|
| 221 | b.append(words[i], words[i+1], words[i+2], words[i+3], words[i+4]); |
---|
| 222 | } |
---|
| 223 | for(i=l-r; i<l; i++){ |
---|
| 224 | b.append(words[i]); |
---|
| 225 | } |
---|
| 226 | return b.toString(); |
---|
| 227 | } |
---|
| 228 | }, |
---|
| 229 | { |
---|
| 230 | name: "builderFor6Args", |
---|
| 231 | test: function() { |
---|
| 232 | var b = new dojox.string.Builder(), l=words.length, r=words.length%6; |
---|
| 233 | for(var i = 0; i < l-r; i+=6) { |
---|
| 234 | b.append(words[i], words[i+1], words[i+2], words[i+3], words[i+4], words[i+5]); |
---|
| 235 | } |
---|
| 236 | for(i=l-r; i<l; i++){ |
---|
| 237 | b.append(words[i]); |
---|
| 238 | } |
---|
| 239 | return b.toString(); |
---|
| 240 | } |
---|
| 241 | }, |
---|
| 242 | { |
---|
| 243 | name: "builderFor7Args", |
---|
| 244 | test: function() { |
---|
| 245 | var b = new dojox.string.Builder(), l=words.length, r=words.length%7; |
---|
| 246 | for(var i = 0; i < l-r; i+=7) { |
---|
| 247 | b.append(words[i], words[i+1], words[i+2], words[i+3], words[i+4], words[i+5], words[i+6]); |
---|
| 248 | } |
---|
| 249 | for(i=l-r; i<l; i++){ |
---|
| 250 | b.append(words[i]); |
---|
| 251 | } |
---|
| 252 | return b.toString(); |
---|
| 253 | } |
---|
| 254 | }, |
---|
| 255 | { |
---|
| 256 | name: "builderFor8Args", |
---|
| 257 | test: function() { |
---|
| 258 | var b = new dojox.string.Builder(), l=words.length, r=words.length%8; |
---|
| 259 | for(var i = 0; i < l-r; i+=8) { |
---|
| 260 | b.append(words[i], words[i+1], words[i+2], words[i+3], words[i+4], words[i+5], words[i+6], words[i+7]); |
---|
| 261 | } |
---|
| 262 | for(i=l-r; i<l; i++){ |
---|
| 263 | b.append(words[i]); |
---|
| 264 | } |
---|
| 265 | return b.toString(); |
---|
| 266 | } |
---|
| 267 | }, |
---|
| 268 | { |
---|
| 269 | name: "builderFor9Args", |
---|
| 270 | test: function() { |
---|
| 271 | var b = new dojox.string.Builder(), l=words.length, r=words.length%9; |
---|
| 272 | for(var i = 0; i < l-r; i+=9) { |
---|
| 273 | b.append(words[i], words[i+1], words[i+2], words[i+3], words[i+4], words[i+5], words[i+6], words[i+7], words[i+8]); |
---|
| 274 | } |
---|
| 275 | for(i=l-r; i<l; i++){ |
---|
| 276 | b.append(words[i]); |
---|
| 277 | } |
---|
| 278 | return b.toString(); |
---|
| 279 | } |
---|
| 280 | } /*, |
---|
| 281 | { |
---|
| 282 | name: "builderForEach", |
---|
| 283 | test: function() { |
---|
| 284 | var b = new dojox.string.Builder(); |
---|
| 285 | dojo.forEach(words, function(w) { |
---|
| 286 | b.append(w); |
---|
| 287 | }); |
---|
| 288 | return b.toString(); |
---|
| 289 | } |
---|
| 290 | }, |
---|
| 291 | |
---|
| 292 | { |
---|
| 293 | name: "builderReusedFor", |
---|
| 294 | test: function() { |
---|
| 295 | _builder.clear(); |
---|
| 296 | for(var i = 0; i < words.length; i++) { |
---|
| 297 | _builder.append(words[i]); |
---|
| 298 | } |
---|
| 299 | return _builder.toString(); |
---|
| 300 | } |
---|
| 301 | }, |
---|
| 302 | { |
---|
| 303 | name: "builderOnce", |
---|
| 304 | test: function() { |
---|
| 305 | var b = new dojox.string.Builder(); |
---|
| 306 | b.appendArray(words); |
---|
| 307 | return b.toString(); |
---|
| 308 | } |
---|
| 309 | }, |
---|
| 310 | { |
---|
| 311 | name: "builderReusedOnce", |
---|
| 312 | test: function() { |
---|
| 313 | _builder.clear(); |
---|
| 314 | _builder.appendArray(words); |
---|
| 315 | return _builder.toString(); |
---|
| 316 | } |
---|
| 317 | }, |
---|
| 318 | { |
---|
| 319 | name: "plusFor", |
---|
| 320 | test: function() { |
---|
| 321 | var s = ""; |
---|
| 322 | for(var i = 0; i < words.length; i++) { |
---|
| 323 | s += words[i]; |
---|
| 324 | } |
---|
| 325 | return s; |
---|
| 326 | } |
---|
| 327 | }, |
---|
| 328 | { |
---|
| 329 | name: "plusForAlias", |
---|
| 330 | test: function() { |
---|
| 331 | var s = "", w = words, l = w.length; |
---|
| 332 | for(var i = 0; i < l; i++) { |
---|
| 333 | s += w[i]; |
---|
| 334 | } |
---|
| 335 | return s; |
---|
| 336 | } |
---|
| 337 | }, |
---|
| 338 | { |
---|
| 339 | name: "plusForEach", |
---|
| 340 | test: function() { |
---|
| 341 | var s = ""; |
---|
| 342 | dojo.forEach(words, function(w) { s += w; }); |
---|
| 343 | return s; |
---|
| 344 | } |
---|
| 345 | }, |
---|
| 346 | { |
---|
| 347 | name: "joinOnce", |
---|
| 348 | test: function() { |
---|
| 349 | return words.join(""); |
---|
| 350 | } |
---|
| 351 | }, |
---|
| 352 | { |
---|
| 353 | name: "joinFor", |
---|
| 354 | test: function() { |
---|
| 355 | var a = []; |
---|
| 356 | for(var i = 0; i < words.length; i++) { |
---|
| 357 | a.push(words[i]); |
---|
| 358 | } |
---|
| 359 | return a.join(""); |
---|
| 360 | } |
---|
| 361 | }, |
---|
| 362 | { |
---|
| 363 | name: "joinForAlias", |
---|
| 364 | test: function() { |
---|
| 365 | var a = [], w = words, l = w.length; |
---|
| 366 | for(var i = 0; i <l; i++) { |
---|
| 367 | a.push(w[i]); |
---|
| 368 | } |
---|
| 369 | return a.join(""); |
---|
| 370 | } |
---|
| 371 | }, |
---|
| 372 | { |
---|
| 373 | name: "joinForEach", |
---|
| 374 | test: function() { |
---|
| 375 | var a = []; |
---|
| 376 | dojo.forEach(words, function(w) { a.push(w); }); |
---|
| 377 | return a.join(""); |
---|
| 378 | } |
---|
| 379 | } |
---|
| 380 | */ |
---|
| 381 | ], |
---|
| 382 | words: words, |
---|
| 383 | expected: expected, |
---|
| 384 | overhead: function() { |
---|
| 385 | var w = words; |
---|
| 386 | var l = w.length; |
---|
| 387 | for(var i=0; i < l; i++) { |
---|
| 388 | ident(w[i]); |
---|
| 389 | } |
---|
| 390 | } |
---|
| 391 | }; |
---|
| 392 | } |
---|
| 393 | |
---|
| 394 | function buildAndRunSet(words, dict, times) { |
---|
| 395 | runSet(buildTestSet(words, dict), times); |
---|
| 396 | } |
---|
| 397 | |
---|
| 398 | function runSuite() { |
---|
| 399 | var suite = [ |
---|
| 400 | { |
---|
| 401 | words: 2, |
---|
| 402 | times: 10000 |
---|
| 403 | }, |
---|
| 404 | { |
---|
| 405 | words: 4, |
---|
| 406 | times: 10000 |
---|
| 407 | }, |
---|
| 408 | { |
---|
| 409 | words: 8, |
---|
| 410 | times: 10000 |
---|
| 411 | }, |
---|
| 412 | { |
---|
| 413 | words: 16, |
---|
| 414 | times: 10000 |
---|
| 415 | }, |
---|
| 416 | { |
---|
| 417 | words: 32, |
---|
| 418 | times: 10000 |
---|
| 419 | }, |
---|
| 420 | { |
---|
| 421 | words: 64, |
---|
| 422 | times: 10000 |
---|
| 423 | }, |
---|
| 424 | { |
---|
| 425 | words: 128, |
---|
| 426 | times: 1000 |
---|
| 427 | }, |
---|
| 428 | { |
---|
| 429 | words: 256, |
---|
| 430 | times: 1000 |
---|
| 431 | }, |
---|
| 432 | { |
---|
| 433 | words: 512, |
---|
| 434 | times: 1000 |
---|
| 435 | }, |
---|
| 436 | { |
---|
| 437 | words: 1024, |
---|
| 438 | times: 1000 |
---|
| 439 | }, |
---|
| 440 | { |
---|
| 441 | words: 2048, |
---|
| 442 | times: 1000 |
---|
| 443 | }, |
---|
| 444 | { |
---|
| 445 | words: 4096, |
---|
| 446 | times: 100 |
---|
| 447 | }, |
---|
| 448 | { |
---|
| 449 | words: 8192, |
---|
| 450 | times: 100 |
---|
| 451 | } |
---|
| 452 | ]; |
---|
| 453 | |
---|
| 454 | var totalSuite = dojo.map(suite, function(s) { var n = {}; dojo.mixin(n,s); n.dict = lipsum; return n; }); |
---|
| 455 | totalSuite = totalSuite.concat(dojo.map(suite, function(s) { var n = {}; dojo.mixin(n,s); n.dict = lipsumLong; return n; })); |
---|
| 456 | console.log(totalSuite); |
---|
| 457 | |
---|
| 458 | var handle = dojo.subscribe("perf/run/done", _run); |
---|
| 459 | dojo.subscribe("perf/run/done", function(){ console.log("perf run done"); }); |
---|
| 460 | |
---|
| 461 | function _run() { |
---|
| 462 | var t = totalSuite.shift(); |
---|
| 463 | if(t) buildAndRunSet(t.words, t.dict, t.times); |
---|
| 464 | if(totalSuite.length == 0) dojo.unsubscribe(handle); |
---|
| 465 | } |
---|
| 466 | |
---|
| 467 | _run(); |
---|
| 468 | } |
---|
| 469 | |
---|
| 470 | function ident(i) { return i; } |
---|
| 471 | </script> |
---|
| 472 | <style type="text/css"> |
---|
| 473 | html { |
---|
| 474 | font-family: Lucida Grande, Tahoma; |
---|
| 475 | } |
---|
| 476 | div { margin-bottom: 1em; } |
---|
| 477 | #results { |
---|
| 478 | border: 1px solid #999; |
---|
| 479 | border-collapse: collapse; |
---|
| 480 | } |
---|
| 481 | #results caption { |
---|
| 482 | font-size: medium; |
---|
| 483 | font-weight: bold; |
---|
| 484 | } |
---|
| 485 | #results td, #results th { |
---|
| 486 | text-align: right; |
---|
| 487 | width: 10em; |
---|
| 488 | font-size: small; |
---|
| 489 | white-space: nowrap; |
---|
| 490 | } |
---|
| 491 | #wordsCol { background: yellow; } |
---|
| 492 | td.max { color: red; font-weight: bold; } |
---|
| 493 | td.min { color: green; font-weight: bold; } |
---|
| 494 | </style> |
---|
| 495 | </head> |
---|
| 496 | <body> |
---|
| 497 | <table> |
---|
| 498 | <tr><td><label for="numWords">Words</label></td><td><input type="text" id="numWords" value="100"/></td></tr> |
---|
| 499 | <tr><td><label for="numIters">Iterations</label></td><td><input type="text" id="numIters" value="1000"/></td></tr> |
---|
| 500 | <tr><td><label for="dict">Dictionary</label></td><td><input type="text" id="dict" value="lipsum"></td></tr> |
---|
| 501 | <tr><td></td><td><button id="run" disabled>Run Tests!</button></td></tr> |
---|
| 502 | </table> |
---|
| 503 | <div id="mess"></div> |
---|
| 504 | </body> |
---|
| 505 | </html> |
---|