You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
413 lines
11 KiB
413 lines
11 KiB
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" |
|
"http://www.w3.org/TR/html4/strict.dtd"> |
|
<html> |
|
<head> |
|
<title>Builder Perf Tests</title> |
|
<script type="text/javascript" src="../../../dojo/dojo.js"></script> |
|
<script type="text/javascript" src="../Builder.js"></script> |
|
<script type="text/javascript" src="lipsum.js"></script> |
|
<script type="text/javascript"> |
|
|
|
dojo.addOnLoad(function(){ |
|
dojo.byId("run").disabled=""; |
|
dojo.connect(dojo.byId("run"), |
|
"onclick", |
|
function(evt) { |
|
setTimeout(function() { |
|
var words = parseInt(dojo.byId("numWords").value) || 10; |
|
var iters = parseInt(dojo.byId("numIters").value) || 1000; |
|
var dict = eval(dojo.byId("dict").value); |
|
buildAndRunSet(words, dict, iters); |
|
}, 0); |
|
}); |
|
}); |
|
|
|
function element(tag, textOrChildOrArray) { |
|
var e = document.createElement(tag); |
|
function append(n) { |
|
if(dojo.isString(n)){ |
|
n = document.createTextNode(n); |
|
} |
|
e.appendChild(n); |
|
} |
|
if(dojo.isArray(textOrChildOrArray)) { |
|
dojo.forEach(textOrChildOrArray, append); |
|
}else{ |
|
append(textOrChildOrArray); |
|
} |
|
return e; |
|
} |
|
|
|
function log(t) { |
|
dojo.byId("mess").innerHTML = t; |
|
console.log(t); |
|
} |
|
|
|
function reportRun(results){ |
|
var runs = results.runs |
|
var report = element("dl", |
|
element("dt", |
|
"Run with " + results.words + " words, " + |
|
results.iterations + " iterations, for loop overhead of " + |
|
results.overhead + ", average phrase of " + |
|
results.wordSize + " characters")); |
|
|
|
runs.sort(function(a,b) { return a.time - b.time; }); |
|
dojo.forEach(runs, function(r) { |
|
report.appendChild(element("dd", r.time + " - " + r.name)); |
|
}); |
|
|
|
dojo.body().appendChild(report); |
|
} |
|
|
|
function runTest(test, iterations, expected) { |
|
var i; |
|
if(expected != test()) throw new Error("Test failed expecting " + expected + ", got " + test()); |
|
var start = new Date().getTime(), end; |
|
for(i=0; i < iterations; i++){ |
|
test(); |
|
} |
|
end = new Date().getTime(); |
|
return end-start; |
|
} |
|
|
|
function runSet(set, iterations){ |
|
|
|
function averagePhraseLen(words) { |
|
var sizes = dojo.map(words, function(w) { return w.length; }); |
|
var total = 0; |
|
dojo.forEach(sizes, function(s) { total += s; }); |
|
return total / sizes.length; |
|
} |
|
|
|
var tests = set.tests.concat(); //copy tests |
|
var resultSet = {}; |
|
resultSet.words = set.words.length; |
|
resultSet.overhead = runTest(set.overhead, iterations); |
|
resultSet.iterations = iterations; |
|
resultSet.wordSize = averagePhraseLen(set.words); |
|
var runs = []; |
|
|
|
function _run() { |
|
var t = tests.pop(); |
|
try { |
|
log("Running " + t.name); |
|
if(t) runs.push({ name: t.name, time: runTest(t.test, iterations, set.expected)}); |
|
} catch(e) { |
|
console.error("Error running " + t.name); |
|
console.error(e); |
|
} |
|
if(tests.length > 0) { |
|
setTimeout(_run, 0); |
|
} |
|
else { |
|
log("Done!"); |
|
resultSet.runs = runs; |
|
reportRun(resultSet); |
|
dojo.publish("perf/run/done"); |
|
} |
|
} |
|
setTimeout(_run, 25); |
|
} |
|
|
|
function buildTestSet(numWords, dict) { |
|
var words = [], i, dl = dict.length; |
|
for(i = numWords; i > 0; i-=dl) { |
|
if(i >= dl) { words = words.concat(dict); } |
|
else { words = words.concat(dict.slice(-i)); } |
|
} |
|
if(words.length != numWords) throw new Error("wrong number of words, got " + words.length + ", expected " + numWords); |
|
|
|
var expected = words.join(""); |
|
|
|
var _builder = new dojox.string.Builder(); |
|
|
|
return { |
|
tests: [ |
|
{ |
|
name: "concatFor", |
|
test: function() { |
|
var s = ""; |
|
for(var i = 0; i < words.length; i++) { |
|
s = s.concat(words[i]); |
|
} |
|
return s; |
|
} |
|
}, |
|
/* |
|
{ |
|
name: "concatForAlias", |
|
test: function() { |
|
var s = "", w = words, l = w.length; |
|
for(var i = 0; i < l; i++) { |
|
s = s.concat(w[i]); |
|
} |
|
return s; |
|
} |
|
}, |
|
{ |
|
name: "concatForEach", |
|
test: function() { |
|
var s = ""; |
|
dojo.forEach(words, function(w) { |
|
s = s.concat(w); |
|
}); |
|
return s; |
|
} |
|
}, |
|
*/ |
|
{ |
|
name: "concatOnce", |
|
test: function() { |
|
var s = ""; |
|
s = String.prototype.concat.apply(s, words); |
|
return s; |
|
} |
|
}, |
|
{ |
|
name: "builderFor", |
|
test: function() { |
|
var b = new dojox.string.Builder(); |
|
for(var i = 0; i < words.length; i++) { |
|
b.append(words[i]); |
|
} |
|
return b.toString(); |
|
} |
|
}, |
|
{ |
|
name: "builderForMulti", |
|
test: function() { |
|
var b = new dojox.string.Builder(); |
|
for(var i = 0; i < words.length; i+=2) { |
|
b.append(words[i], words[i+1]); |
|
} |
|
return b.toString(); |
|
} |
|
}, |
|
/* |
|
{ |
|
name: "builderForEach", |
|
test: function() { |
|
var b = new dojox.string.Builder(); |
|
dojo.forEach(words, function(w) { |
|
b.append(w); |
|
}); |
|
return b.toString(); |
|
} |
|
}, |
|
*/ |
|
{ |
|
name: "builderReusedFor", |
|
test: function() { |
|
_builder.clear(); |
|
for(var i = 0; i < words.length; i++) { |
|
_builder.append(words[i]); |
|
} |
|
return _builder.toString(); |
|
} |
|
}, |
|
{ |
|
name: "builderOnce", |
|
test: function() { |
|
var b = new dojox.string.Builder(); |
|
b.appendArray(words); |
|
return b.toString(); |
|
} |
|
}, |
|
{ |
|
name: "builderReusedOnce", |
|
test: function() { |
|
_builder.clear(); |
|
_builder.appendArray(words); |
|
return _builder.toString(); |
|
} |
|
}, |
|
{ |
|
name: "plusFor", |
|
test: function() { |
|
var s = ""; |
|
for(var i = 0; i < words.length; i++) { |
|
s += words[i]; |
|
} |
|
return s; |
|
} |
|
}, |
|
/* |
|
{ |
|
name: "plusForAlias", |
|
test: function() { |
|
var s = "", w = words, l = w.length; |
|
for(var i = 0; i < l; i++) { |
|
s += w[i]; |
|
} |
|
return s; |
|
} |
|
}, |
|
{ |
|
name: "plusForEach", |
|
test: function() { |
|
var s = ""; |
|
dojo.forEach(words, function(w) { s += w; }); |
|
return s; |
|
} |
|
},*/ |
|
{ |
|
name: "joinOnce", |
|
test: function() { |
|
return words.join(""); |
|
} |
|
}, |
|
{ |
|
name: "joinFor", |
|
test: function() { |
|
var a = []; |
|
for(var i = 0; i < words.length; i++) { |
|
a.push(words[i]); |
|
} |
|
return a.join(""); |
|
} |
|
}/*, |
|
{ |
|
name: "joinForAlias", |
|
test: function() { |
|
var a = [], w = words, l = w.length; |
|
for(var i = 0; i <l; i++) { |
|
a.push(w[i]); |
|
} |
|
return a.join(""); |
|
} |
|
}, |
|
{ |
|
name: "joinForEach", |
|
test: function() { |
|
var a = []; |
|
dojo.forEach(words, function(w) { a.push(w); }); |
|
return a.join(""); |
|
} |
|
} |
|
*/ |
|
], |
|
words: words, |
|
expected: expected, |
|
overhead: function() { |
|
var w = words; |
|
var l = w.length; |
|
for(var i=0; i < l; i++) { |
|
ident(w[i]); |
|
} |
|
} |
|
}; |
|
} |
|
|
|
function buildAndRunSet(words, dict, times) { |
|
runSet(buildTestSet(words, dict), times); |
|
} |
|
|
|
function runSuite() { |
|
var suite = [ |
|
{ |
|
words: 2, |
|
times: 10000 |
|
}, |
|
{ |
|
words: 4, |
|
times: 10000 |
|
}, |
|
{ |
|
words: 8, |
|
times: 10000 |
|
}, |
|
{ |
|
words: 16, |
|
times: 10000 |
|
}, |
|
{ |
|
words: 32, |
|
times: 10000 |
|
}, |
|
{ |
|
words: 64, |
|
times: 10000 |
|
}, |
|
{ |
|
words: 128, |
|
times: 1000 |
|
}, |
|
{ |
|
words: 256, |
|
times: 1000 |
|
}, |
|
{ |
|
words: 512, |
|
times: 1000 |
|
}, |
|
{ |
|
words: 1024, |
|
times: 1000 |
|
}, |
|
{ |
|
words: 2048, |
|
times: 1000 |
|
}, |
|
{ |
|
words: 4096, |
|
times: 100 |
|
}, |
|
{ |
|
words: 8192, |
|
times: 100 |
|
} |
|
]; |
|
|
|
var totalSuite = dojo.map(suite, function(s) { var n = {}; dojo.mixin(n,s); n.dict = lipsum; return n; }); |
|
totalSuite = totalSuite.concat(dojo.map(suite, function(s) { var n = {}; dojo.mixin(n,s); n.dict = lipsumLong; return n; })); |
|
console.log(totalSuite); |
|
|
|
var handle = dojo.subscribe("perf/run/done", _run); |
|
dojo.subscribe("perf/run/done", function(){ console.log("perf run done"); }); |
|
|
|
function _run() { |
|
var t = totalSuite.shift(); |
|
if(t) buildAndRunSet(t.words, t.dict, t.times); |
|
if(totalSuite.length == 0) dojo.unsubscribe(handle); |
|
} |
|
|
|
_run(); |
|
} |
|
|
|
function ident(i) { return i; } |
|
</script> |
|
<style type="text/css"> |
|
html { |
|
font-family: Lucida Grande, Tahoma; |
|
} |
|
div { margin-bottom: 1em; } |
|
#results { |
|
border: 1px solid #999; |
|
border-collapse: collapse; |
|
} |
|
#results caption { |
|
font-size: medium; |
|
font-weight: bold; |
|
} |
|
#results td, #results th { |
|
text-align: right; |
|
width: 10em; |
|
font-size: small; |
|
white-space: nowrap; |
|
} |
|
#wordsCol { background: yellow; } |
|
td.max { color: red; font-weight: bold; } |
|
td.min { color: green; font-weight: bold; } |
|
</style> |
|
</head> |
|
<body> |
|
<table> |
|
<tr><td><label for="numWords">Words</label></td><td><input type="text" id="numWords" value="100"/></td></tr> |
|
<tr><td><label for="numIters">Iterations</label></td><td><input type="text" id="numIters" value="1000"/></td></tr> |
|
<tr><td><label for="dict">Dictionary</label></td><td><input type="text" id="dict" value="lipsum"></td></tr> |
|
<tr><td></td><td><button id="run" disabled>Run Tests!</button></td></tr> |
|
</table> |
|
<div id="mess"></div> |
|
</body> |
|
</html>
|
|
|