blob: 6664de7b2d34a24bd3bd38624fd1aea9ed02f4d9 [file] [log] [blame]
<!DOCTYPE HTML>
<html>
<head>
<title>Performance Tests (2)</title>
<style>
body { font-family: Tahoma, Serif; font-size: 9pt; }
.left { text-align: left; }
.right { text-align: right; }
.center { text-align: center; }
table.resultTable
{
border: 1px solid black;
border-collapse: collapse;
empty-cells: show;
width: 100%;
}
table.resultTable td
{
padding: 2px 4px;
border: 1px solid black;
}
table.resultTable > thead > tr
{
font-weight: bold;
background: lightblue;
}
table.resultTable > tbody > tr:nth-child(odd)
{
background: white;
}
table.resultTable > tbody > tr:nth-child(even)
{
background: lightgray;
}
.hide { display: none; }
</style>
</head>
<body bgcolor="white">
<h1>Performance Tests (2)</h1>
<form id="sForm" onsubmit="runTestSuite();return false">
<table>
<tr>
<td colspan="2">Settings:</td>
</tr>
<tr>
<td class="right">Iterations:</td>
<td><input id="sIterations" type="text" value="1000" required pattern="[0-9]+" /></td>
</tr>
<tr>
<td class="right">Samples:</td>
<td><input id="sSamples" type="text" value="100" required pattern="[0-9]+" /></td>
</tr>
<tr>
<td class="right">Mode:</td>
<td><input id="sAsync" name="sMode" type="radio" value="async" checked>Asynchronous</input>
<input id="sSync" name="sMode" type="radio" value="sync">Synchronous</input>
</td>
</tr>
<tr>
<td colspan="2"><button type="submit" id="sRun" autofocus>Run!</button></td>
</tr>
</table>
</form>
<div><span id="statusBox"></span> <progress id="progressBox" value="0" style="display:none"></progress></div>
<div style="padding-top:10px; padding-bottom:10px">
<table id="resultTable" class="resultTable">
<thead>
<tr>
<td class="center" style="width:1%">Enabled</td>
<td class="center" style="width:10%">Name</td>
<td class="center" style="width:5%">Samples x Iterations</td>
<td class="center" style="width:5%">Min,&nbsp;ms</td>
<td class="center" style="width:5%">Avg,&nbsp;ms</td>
<td class="center" style="width:5%">Max,&nbsp;ms</td>
<td class="center" style="width:5%">Average calls/sec</td>
<td class="center" style="width:5%">Measuring Inacurracy</td>
<td class="center hide" style="width:5%">Memory, MB</td>
<td class="center hide" style="width:5%">Memory delta, MB</td>
<td class="center" style="width:55%">Description</td>
</tr>
</thead>
<tbody>
<!-- result rows here -->
</tbody>
</table>
</div>
<script type="text/javascript">
(function () {
function getPrivateWorkingSet() {
return 0; // TODO: window.PerfTestGetPrivateWorkingSet();
}
var disableWarmUp = true;
var asyncExecution = true;
var testIterations = 1000;
var totalSamples = 100;
var sampleDelay = 0;
var collectSamples = false;
var tests = [];
var testIndex = -1;
function execTestFunc(test) {
try {
var begin = new Date();
test.func(test.totalIterations);
var end = new Date();
return (end - begin);
} catch (e) {
test.error = e.toString();
return 0;
}
}
function execTest(test) {
if (disableWarmUp) { test.warmedUp = true; }
function nextStep() {
if (asyncExecution) {
setTimeout(function () { execTest(test); }, sampleDelay);
} else {
execTest(test);
}
}
function nextTest() {
updateStatus(test);
appendResult(test);
return execNextTest();
}
updateStatus(test);
if (!test.warmedUp) {
execTestFunc(test);
if (!test.error) {
test.warmedUp = true;
test.beginMemory = getPrivateWorkingSet();
return nextStep();
} else {
return nextTest();
}
}
if (test.sample >= test.totalSamples) {
test.avg = test.total / test.totalSamples;
test.endMemory = getPrivateWorkingSet();
return nextTest();
}
if (test.skipped) return nextTest();
var elapsed = execTestFunc(test);
if (!test.error) {
test.total += elapsed;
if (!test.min) test.min = elapsed;
else if (test.min > elapsed) test.min = elapsed;
if (!test.max) test.max = elapsed;
else if (test.max < elapsed) test.max = elapsed;
if (collectSamples) {
test.results.push(elapsed);
}
test.sample++;
return nextStep();
} else {
return nextTest();
}
}
function updateStatus(test) {
var statusBox = document.getElementById("statusBox");
var progressBox = document.getElementById("progressBox");
if (test.skipped || test.error || test.sample >= test.totalSamples) {
statusBox.innerText = "";
progressBox.style.display = "none";
} else {
statusBox.innerText = (testIndex + 1) + "/" + tests.length + ": " + test.name + " (" + test.sample + "/" + test.totalSamples + ")";
progressBox.value = (test.sample / test.totalSamples);
progressBox.style.display = "inline";
}
}
function appendResult(test) {
if (test.name == "warmup") return;
var id = "testResultRow_" + test.index;
var nearBound = (test.max - test.avg) < (test.avg - test.min) ? test.max : test.min;
var memoryDelta = test.endMemory - test.beginMemory;
if (memoryDelta < 0) memoryDelta = "-" + Math.abs(memoryDelta).toFixed(2);
else memoryDelta = "+" + Math.abs(memoryDelta).toFixed(2);
var markup = ["<tr id='" + id + "'>",
"<td class='left'><input type='checkbox' id='test_enabled_", test.index ,"' ", (!test.skipped ? "checked" : "") ," /></td>",
"<td class='left'>", test.name, "</td>",
"<td class='right'>", test.totalSamples, "x", test.totalIterations, "</td>",
"<td class='right'>", test.skipped || test.error || !test.prepared ? "-" : test.min.toFixed(2), "</td>",
"<td class='right'>", test.skipped || test.error || !test.prepared ? "-" : test.avg.toFixed(2), "</td>",
"<td class='right'>", test.skipped || test.error || !test.prepared ? "-" : test.max.toFixed(2), "</td>",
"<td class='right'>", test.skipped || test.error || !test.prepared ? "-" : (test.totalIterations * 1000 / test.avg).toFixed(2), "</td>",
"<td class='right'>", test.skipped || test.error || !test.prepared ? "-" : ("&#x00B1; " + (Math.abs(test.avg - nearBound) / (test.avg) * (100)).toFixed(2) + "%"), "</td>",
"<td class='right hide'>", test.skipped || test.error || !test.prepared ? "-" : test.endMemory.toFixed(2), "</td>",
"<td class='right hide'>", test.skipped || test.error || !test.prepared ? "-" : memoryDelta, "</td>",
"<td class='left'>", test.description, test.error ? (test.description ? "<br/>" : "") + "<span style='color:red'>" + test.error + "</span>" : "", "</td>",
"</tr>"
].join("");
// test.results.join(", "), "<br/>",
var row = document.getElementById(id);
if (row) {
row.outerHTML = markup;
} else {
var tbody = document.getElementById("resultTable").tBodies[0];
tbody.insertAdjacentHTML("beforeEnd", markup);
}
}
function prepareQueuedTests() {
testIndex = -1;
for (var i = 0; i < tests.length; i++) {
var test = tests[i];
test.index = i;
test.prepared = false;
test.warmedUp = false;
test.sample = 0;
test.total = 0;
test.results = [];
test.error = false;
test.min = null;
test.avg = null;
test.max = null;
test.beginMemory = null;
test.endMemory = null;
test.totalIterations = parseInt(testIterations / test.complex);
test.totalSamples = parseInt(totalSamples / test.complex);
var skipElement = document.getElementById('test_enabled_' + test.index);
test.skipped = skipElement ? !skipElement.checked : (test.skipped || false);
if (test.totalIterations <= 0) test.totalIterations = 1;
if (test.totalSamples <= 0) test.totalSamples = 1;
appendResult(test);
test.prepared = true;
}
}
function queueTest(func, name, description) {
var test;
if (typeof func === "function") {
test = {
name: name,
func: func,
description: description
};
} else {
test = func;
}
test.warmedUp = false;
test.complex = test.complex || 1;
tests.push(test);
}
function execNextTest() {
testIndex++;
if (tests.length <= testIndex) {
return testSuiteFinished();
} else {
return execTest(tests[testIndex]);
}
}
function execQueuedTests() {
prepareQueuedTests();
execNextTest();
}
function setSettingsState(disabled) {
document.getElementById('sIterations').disabled = disabled;
document.getElementById('sSamples').disabled = disabled;
document.getElementById('sAsync').disabled = disabled;
document.getElementById('sSync').disabled = disabled;
document.getElementById('sRun').disabled = disabled;
}
function testSuiteFinished() {
setSettingsState(false);
}
window.runTestSuite = function () {
setSettingsState(true);
testIterations = parseInt(document.getElementById('sIterations').value);
totalSamples = parseInt(document.getElementById('sSamples').value);
asyncExecution = document.getElementById('sAsync').checked;
setTimeout(execQueuedTests, 0);
}
setTimeout(prepareQueuedTests, 0);
// Test queue.
queueTest({
name: "PerfTestReturnValue Default",
func: function (count) {
for (var i = 0; i < count; i++) {
window.PerfTestReturnValue();
}
},
description: "No arguments, returns int32 value.",
skipped: true,
});
queueTest({
name: "PerfTestReturnValue (0, Undefined)",
func: function (count) {
for (var i = 0; i < count; i++) {
window.PerfTestReturnValue(0);
}
},
description: "Int argument, returns undefined value."
});
queueTest({
name: "PerfTestReturnValue (1, Null)",
func: function (count) {
for (var i = 0; i < count; i++) {
window.PerfTestReturnValue(1);
}
},
description: "Int argument, returns null value."
});
queueTest({
name: "PerfTestReturnValue (2, Bool)",
func: function (count) {
for (var i = 0; i < count; i++) {
window.PerfTestReturnValue(2);
}
},
description: "Int argument, returns bool value."
});
queueTest({
name: "PerfTestReturnValue (3, Int)",
func: function (count) {
for (var i = 0; i < count; i++) {
window.PerfTestReturnValue(3);
}
},
description: "Int argument, returns int value."
});
queueTest({
name: "PerfTestReturnValue (4, UInt)",
func: function (count) {
for (var i = 0; i < count; i++) {
window.PerfTestReturnValue(4);
}
},
description: "Int argument, returns uint value."
});
queueTest({
name: "PerfTestReturnValue (5, Double)",
func: function (count) {
for (var i = 0; i < count; i++) {
window.PerfTestReturnValue(5);
}
},
description: "Int argument, returns double value."
});
queueTest({
name: "PerfTestReturnValue (6, Date)",
func: function (count) {
for (var i = 0; i < count; i++) {
window.PerfTestReturnValue(6);
}
},
description: "Int argument, returns date value.",
skipped: true,
});
queueTest({
name: "PerfTestReturnValue (7, String)",
func: function (count) {
for (var i = 0; i < count; i++) {
window.PerfTestReturnValue(7);
}
},
description: "Int argument, returns string value."
});
queueTest({
name: "PerfTestReturnValue (8, Object)",
func: function (count) {
for (var i = 0; i < count; i++) {
window.PerfTestReturnValue(8);
}
},
description: "Int argument, returns object value."
});
queueTest({
name: "PerfTestReturnValue (9, Array)",
func: function (count) {
for (var i = 0; i < count; i++) {
window.PerfTestReturnValue(9);
}
},
description: "Int argument, returns array value."
});
queueTest({
name: "PerfTestReturnValue (10, Function)",
func: function (count) {
for (var i = 0; i < count; i++) {
window.PerfTestReturnValue(10);
}
},
description: "Int argument, returns function value.",
skipped: true,
});
// add more tests to queueTest
})();
</script>
</body>
</html>