BuilderPerf.html 11 KB

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