Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-type" content="text/html;charset=UTF-8">
<title>New Supercalls Performance Test Page</title>
<style type='text/css'>
#log p {
margin: 0;
padding: 0;
}
.good {
color: green;
}
.bad {
color: red;
}
</style>
<script type='text/javascript' src='prototype.js'></script>
<script type='text/javascript'>
// **** Versions using the old mechanism
var OldParent = Class.create((function(){
function nifty(arg1) {
return "OP(" + arg1 + ")";
}
return {nifty: nifty};
})());
var OldChild = Class.create(OldParent, (function(){
function nifty($super, arg1) {
return $super(arg1) + " < OC";
}
return {nifty: nifty};
})());
var OldGrandChild = Class.create(OldChild, (function(){
function nifty($super, arg1) {
return $super(arg1) + " < OGC";
}
return {nifty: nifty};
})());
// **** Versions using the new mechanism
var NewParent = Class.create((function() {
function nifty(arg1) {
return "NP(" + arg1 + ")";
}
return {nifty: nifty};
})());
var NewChild = Class.create(NewParent, (function() {
function nifty(arg1) {
return nifty.$super.call(this, arg1) + " < NC";
//Use this to see how slow arguments.callee is!
// return arguments.callee.$super.call(this, arg1) + " < NC";
}
return {nifty: nifty};
})());
var NewGrandChild = Class.create(NewChild, (function() {
function nifty(arg1) {
return nifty.$super.call(this, arg1) + " < NGC";
//Use this to see how slow arguments.callee is!
// return arguments.callee.$super.call(this, arg1) + " < NGC";
}
return {nifty: nifty};
})());
document.observe("dom:loaded", function() {
$('btnClearLog').observe('click', clearLog);
$('btnTestFunctionality').observe('click', function() {
runTests({functionality: true});
});
$('btnTestPerformance').observe('click', function() {
runTests({performance: true});
});
});
function runTests(tests, stage) {
stage = stage || 0;
switch (stage) {
case 0:
$$('input').invoke('disable');
break;
case 1:
try {
testWorker(tests);
}
catch (e) {
write("Exception: " + e, false);
}
break;
case 2:
$$('input').invoke('enable');
break;
}
if (stage < 2) {
runTests.delay(0.2, tests, stage + 1);
}
}
function testWorker(tests) {
var count, countPerLoop, change, otime, ntime, s, failures,
oParent, oChild, oGrandChild,
nParent, nChild, nGrandChild;
// Get instances
oParent = new OldParent();
oChild = new OldChild();
oGrandChild = new OldGrandChild();
nParent = new NewParent();
nChild = new NewChild();
nGrandChild = new NewGrandChild();
// **** Functionality first
if (tests.functionality) {
failures = 0;
// The basics
if (!assertEqual(oParent.nifty('hi'), "OP(hi)") ) ++failures;
if (!assertEqual(oChild.nifty('hi'), "OP(hi) < OC") ) ++failures;
if (!assertEqual(oGrandChild.nifty('hi'), "OP(hi) < OC < OGC")) ++failures;
if (!assertEqual(nParent.nifty('hi'), "NP(hi)") ) ++failures;
if (!assertEqual(nChild.nifty('hi'), "NP(hi) < NC") ) ++failures;
if (!assertEqual(nGrandChild.nifty('hi'), "NP(hi) < NC < NGC")) ++failures;
// Replacing a method
OldChild.addMethods((function(){
function nifty($super, arg1) {
return $super(arg1) + " < OC!";
}
return {nifty: nifty};
})());
NewChild.addMethods((function(){
function nifty(arg1) {
return nifty.$super.call(this, arg1) + " < NC!";
}
return {nifty: nifty};
})());
if (!assertEqual(oGrandChild.nifty('hi'), "OP(hi) < OC! < OGC")) ++failures;
if (!assertEqual(nGrandChild.nifty('hi'), "NP(hi) < NC! < NGC")) ++failures;
if (failures > 0) {
write("Functionality tests failures: " + failures, false);
}
else {
write("All functionality tests passed", true);
}
write("<hr>");
}
// **** Performance
if (tests.performance) {
// Warm up
test(oGrandChild, 100);
test(nGrandChild, 100);
// Four tests interwoven to even out environment concerns
count = $F('txtCount');
if (isNaN(count) || count < 0) {
count = 2000;
$('txtCount').setValue(count);
}
countPerLoop = Math.round(count / 4);
otime = ntime = 0;
for (n = 4; n > 0; --n) {
otime += test(oGrandChild, countPerLoop);
ntime += test(nGrandChild, countPerLoop);
}
write("test loops: " + count);
write("Old mechanism time: " + otime + "ms", otime <= ntime);
write("New mechanism time: " + ntime + "ms", ntime <= otime);
if (otime + ntime < 15000) {
write("*** The test was a bit short, the timing data may be suspect; try more loops.");
}
change = (ntime - otime) / otime;
write("Improvement: " + round(-change * 100, 2) + "%, e.g., old takes " + round(otime / ntime, 2) + " times as long as new.");
write("<hr>");
}
}
function now() {
return new Date().getTime();
}
function round(value, places) {
var tenx;
tenx = Math.pow(10, places);
return Math.round(value * tenx) / tenx;
}
function test(obj, count) {
var s, start, n;
s = "";
start = now();
for (n = count; n > 0; --n)
{
s += obj.nifty('hi');
}
return now() - start;
}
function assertEqual(a, b) {
var flag;
if (a == b) {
flag = true;
write("GOOD: " + a.escapeHTML(), flag);
}
else {
flag = false;
write("Expected '" + b.escapeHTML() + "', got '" + a.escapeHTML() + "'", flag);
}
return flag;
}
function write(msg, flag) {
var opentag;
if (typeof flag != 'undefined') {
opentag = "<p class='" + (flag ? "good" : "bad") + "'>";
}
else {
opentag = "<p>";
}
$('log').innerHTML += opentag + msg + "</" + "p>";
return flag;
}
function clearLog() {
$('log').innerHTML = "";
}
</script>
</head>
<body><div>
<input type='button' id='btnClearLog' value='Clear Log'>
<input type='button' id='btnTestFunctionality' value='Test Functionality'>
<input type='button' id='btnTestPerformance' value='Test Performance'>
Test loops: <input type='text' id='txtCount' value='5000'>
(suggest about 5,000 for IE, 200,000 for Chrome, 100,000 for Firefox or Safari)
<hr>
<div id='log'></div>
</div></body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment