Add presentation layer to present the results.

This commit is contained in:
Timmy Willison 2012-09-07 01:19:59 -04:00
parent 4b21d29c0d
commit 0f5c326e0b
6 changed files with 439 additions and 27 deletions

View File

@ -3,6 +3,7 @@
<head>
<meta charset="utf-8">
<title>Sizzle Performance Suite HTML</title>
<link rel="shortcut icon" href="../images/favicon.ico">
</head>
<body>
<!-- HTML taken from http://www.w3.org/TR/selectors/ -->
@ -3314,7 +3315,9 @@
})();
</script>
<script>
window.parent.iframeCallbacks[ suite ][ callback ].call( window, document );
if ( suite != null && callback != null ) {
window.parent.iframeCallbacks[ suite ][ callback ].call( window, document );
}
</script>
</body>
</html>

BIN
speed/images/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

BIN
speed/images/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.7 KiB

View File

@ -3,13 +3,28 @@
<head>
<meta charset="utf-8">
<title>Sizzle Performance Suite</title>
<link rel="shortcut icon" href="images/favicon.ico">
<link rel="stylesheet" media="screen" href="speed.css">
</head>
<body>
<table>
<thead id="perf-table-headers"></thead>
<tbody id="perf-table-body"></tbody>
</table>
<header>
<img id="logo" src="images/logo.png" alt="Sizzle">
<h4>Sizzle Performance Suite built with <a href="http://benchmarkjs.com">benchmarkjs</a> and <a href="http://requirejs.org">requirejs</a></h4>
<ul>
<li>Every selector engine gets its own iframe</li>
<li>iframes are destroyed and reset after <i>each</i> selector, so no selector can affect another</li>
<li>Tests are run against <a href="data/selector.html">this page</a></li>
</ul>
</header>
<article id="main" role="main" class="clear">
<table class="table table-bordered">
<thead id="perf-table-headers"></thead>
<tbody id="perf-table-body"></tbody>
</table>
</article>
<footer>
<small>Copyright &copy; 2012 jQuery Foundation</small>
</footer>
<script src="require.js" data-main="speed"></script>
</body>
</html>

View File

@ -1,4 +1,262 @@
/*
* Styles for the performance suite
/**
* speed.css
*
* Styles for SizzleSpeed
*/
/*! normalize.css v1.0.1 | MIT License | git.io/normalize */
article,aside,details,figcaption,figure,footer,header,hgroup,nav,section,summary { display: block; }
audio,canvas,video { display: inline-block; *display: inline; *zoom: 1; }
audio:not([controls]) { display: none; height: 0; }
[hidden] { display: none; }
html { font-size: 100%; /* 1 */ -webkit-text-size-adjust: 100%; /* 2 */ -ms-text-size-adjust: 100%; /* 2 */ }
html,button,input,select,textarea { font-family: sans-serif; }
body { margin: 0; }
a:focus { outline: thin dotted; }
a:active,a:hover { outline: 0; }
h1 { font-size: 2em; margin: 0.67em 0; }
h2 { font-size: 1.5em; margin: 0.83em 0; }
h3 { font-size: 1.17em; margin: 1em 0; }
h4 { font-size: 1em; margin: 1.33em 0; }
h5 { font-size: 0.83em; margin: 1.67em 0; }
h6 { font-size: 0.75em; margin: 2.33em 0; }
abbr[title] { border-bottom: 1px dotted; }
b,strong { font-weight: bold; }
blockquote { margin: 1em 40px; }
dfn { font-style: italic; }
mark { background: #ff0; color: #000; }
p,pre { margin: 1em 0; }
code,kbd,pre,samp { font-family: monospace, serif; _font-family: 'courier new', monospace; font-size: 1em; }
pre { white-space: pre; white-space: pre-wrap; word-wrap: break-word; }
q { quotes: none; }
q:before,q:after { content: ''; content: none; }
small { font-size: 80%; }
sub,sup { font-size: 75%; line-height: 0; position: relative; vertical-align: baseline; }
sup { top: -0.5em; }
sub { bottom: -0.25em; }
dl,menu,ol,ul { margin: 1em 0;}
dd { margin: 0 0 0 40px; }
menu,ol,ul { padding: 0 0 0 40px; }
nav ul,nav ol { list-style: none; list-style-image: none; }
img { border: 0; /* 1 */ -ms-interpolation-mode: bicubic; /* 2 */ }
svg:not(:root) { overflow: hidden; }
figure { margin: 0; }
form { margin: 0; }
fieldset { border: 1px solid #c0c0c0; margin: 0 2px; padding: 0.35em 0.625em 0.75em; }
legend { border: 0; /* 1 */ padding: 0; white-space: normal; /* 2 */ *margin-left: -7px; /* 3 */ }
button,input,select,textarea { font-size: 100%; /* 1 */ margin: 0; /* 2 */ vertical-align: baseline; /* 3 */ *vertical-align: middle; /* 3 */ }
button,input { line-height: normal; }
button,html input[type="button"], /* 1 */input[type="reset"],input[type="submit"] { -webkit-appearance: button; /* 2 */ cursor: pointer; /* 3 */ *overflow: visible; /* 4 */ }
button[disabled],input[disabled] { cursor: default; }
input[type="checkbox"],input[type="radio"] { box-sizing: border-box; /* 1 */ padding: 0; /* 2 */ *height: 13px; /* 3 */ *width: 13px; /* 3 */ }
input[type="search"] { -webkit-appearance: textfield; /* 1 */ -moz-box-sizing: content-box; -webkit-box-sizing: content-box; /* 2 */ box-sizing: content-box; }
input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration { -webkit-appearance: none; }
button::-moz-focus-inner,input::-moz-focus-inner { border: 0; padding: 0; }
textarea { overflow: auto; /* 1 */ vertical-align: top; /* 2 */ }
table { border-collapse: collapse; border-spacing: 0; }
/* ==|== animations ======================================== */
@-webkit-keyframes shake {
from { -webkit-transform: translate3d(0, 0, 0); }
40% { -webkit-transform: translate3d(0, 0, 0); }
50% { -webkit-transform: translate3d(-4px, 0, 0); }
75% { -webkit-transform: translate3d(4px, 0, 0); }
90% { -webkit-transform: translate3d(-2px, 0, 0); }
95% { -webkit-transform: translate3d(1px, 0, 0); }
to { -webkit-transform: translate3d(0, 0, 0); }
}
@-moz-keyframes shake {
from { -moz-transform: translate(0, 0); }
40% { -moz-transform: translate(0, 0); }
50% { -moz-transform: translate(-4px, 0); }
75% { -moz-transform: translate(4px, 0); }
90% { -moz-transform: translate(-2px, 0); }
95% { -moz-transform: translate(1px, 0); }
to { -moz-transform: translate(0, 0); }
}
@-o-keyframes shake {
from { -o-transform: translate(0, 0); }
40% { -o-transform: translate(0, 0); }
50% { -o-transform: translate(-4px, 0); }
75% { -o-transform: translate(4px, 0); }
90% { -o-transform: translate(-2px, 0); }
95% { -o-transform: translate(1px, 0); }
to { -o-transform: translate(0, 0); }
}
@-ms-keyframes shake {
from { -ms-transform: translate(0, 0); }
40% { -ms-transform: translate(0, 0); }
50% { -ms-transform: translate(-4px, 0); }
75% { -ms-transform: translate(4px, 0); }
90% { -ms-transform: translate(-2px, 0); }
95% { -ms-transform: translate(1px, 0); }
to { -ms-transform: translate(0, 0); }
}
@keyframes shake {
from { transform: translate(0, 0); }
40% { transform: translate(0, 0); }
50% { transform: translate(-4px, 0); }
75% { transform: translate(4px, 0); }
90% { transform: translate(-2px, 0); }
95% { transform: translate(1px, 0); }
to { transform: translate(0, 0); }
}
.pending span {
display: inline-block; *display: inline;
-webkit-animation-name: shake;
-moz-animation-name: shake;
-o-animation-name: shake;
-ms-animation-name: shake;
animation-name: shake;
-webkit-animation-duration: 0.7s;
-moz-animation-duration: 0.7s;
-o-animation-duration: 0.7s;
-ms-animation-duration: 0.7s;
animation-duration: 0.7s;
-webkit-animation-iteration-count: infinite;
-moz-animation-iteration-count: infinite;
-o-animation-iteration-count: infinite;
-ms-animation-iteration-count: infinite;
animation-iteration-count: infinite;
}
/* ==|== Performance suite styles ======================================== */
body { padding: 40px; font: 14px/1.4 "Helvetica Neue", Helvetica, Arial, sans-serif; }
small, .small { font-size: 0.85em; }
a { color: #730E00; }
a:hover { color: #EE1E00; }
a:active { color: black; }
#logo {
padding: 10px; display: block; margin-bottom: 10px;
background: #8C0000;
-moz-box-shadow: rgba(0, 0, 0, 0.5) 0px 3px 3px;
-webkit-box-shadow: rgba(0, 0, 0, 0.5) 0px 3px 3px;
box-shadow: rgba(0, 0, 0, 0.5) 0px 3px 3px;
-webkit-border-radius: 10px;
-moz-border-radius: 10px;
border-radius: 10px;
}
/* ==|== table styles ======================================== */
.table {
width: 100%;
margin: 2.5em 0;
}
.table th,
.table td {
padding: 5px 10px;
width: 150px;
line-height: 1.4;
text-align: left;
vertical-align: middle;
}
.table th.text-right,
.table td.text-right {
text-align: right;
}
.table th {
color: #9F0000;
text-shadow: rgba(0, 0, 0, 0.2) 0 1px;
background: rgb(240, 240, 240);
font-weight: 600;
}
.table thead th {
vertical-align: bottom;
}
.table caption + thead tr:first-child th,
.table caption + thead tr:first-child td,
.table colgroup + thead tr:first-child th,
.table colgroup + thead tr:first-child td,
.table thead:first-child tr:first-child th,
.table thead:first-child tr:first-child td {
border-top: 0;
}
.table tbody + tbody {
border-top: 2px solid #dddddd;
}
.table-dark td {
color: #31373c;
}
.table-condensed th,
.table-condensed td {
padding: 4px 5px;
}
.table-semi-bordered td {
border-right: 1px solid #dddddd;
border-top: 1px solid #dddddd;
}
.table-semi-bordered td:first-child {
border-left: 1px solid #dddddd;
}
.table-bordered {
border: 2px solid #dddddd;
border-bottom: 0;
border-collapse: separate;
*border-collapse: collapse;
border-left: 0;
-webkit-border-radius: 4px;
-moz-border-radius: 4px;
border-radius: 4px;
}
.table-bordered th,
.table-bordered td {
border-left: 2px solid #dddddd;
border-bottom: 2px solid #dddddd;
}
.table-bordered caption + thead tr:first-child th,
.table-bordered caption + tbody tr:first-child th,
.table-bordered caption + tbody tr:first-child td,
.table-bordered colgroup + thead tr:first-child th,
.table-bordered colgroup + tbody tr:first-child th,
.table-bordered colgroup + tbody tr:first-child td,
.table-bordered thead:first-child tr:first-child th,
.table-bordered tbody:first-child tr:first-child th,
.table-bordered tbody:first-child tr:first-child td {
border-top: 0;
}
.table-bordered thead:first-child tr:first-child th:first-child,
.table-bordered tbody:first-child tr:first-child td:first-child {
-webkit-border-top-left-radius: 4px;
-moz-border-radius-topleft: 4px;
border-top-left-radius: 4px;
}
.table-bordered thead:first-child tr:first-child th:last-child,
.table-bordered tbody:first-child tr:first-child td:last-child {
-webkit-border-top-right-radius: 4px;
-moz-border-radius-topright: 4px;
border-top-right-radius: 4px;
}
.table-bordered thead:last-child tr:last-child th:first-child,
.table-bordered tbody:last-child tr:last-child td:first-child {
-webkit-border-radius: 0 0 0 4px;
-moz-border-radius: 0 0 0 4px;
border-radius: 0 0 0 4px;
}
.table-bordered thead:last-child tr:last-child th:last-child,
.table-bordered tbody:last-child tr:last-child td:last-child {
-webkit-border-bottom-right-radius: 4px;
-moz-border-radius-bottomright: 4px;
border-bottom-right-radius: 4px;
}
.table-striped tbody tr:nth-child(even) td,
.table-striped tbody tr:nth-child(even) th {
background-color: #f9f9f9;
}
.table tbody tr:hover td,
.table tbody tr:hover th,
.table tbody tr .table-hover-background {
background-color: #f0f6fa;
}
.table tbody tr td.green { background: #19EB4B; }
.table tbody tr td.red { background: #FF5E5E; }
.selector { background: hsl(215, 100%, 95%); }
/* ==|== helper classes ======================================== */
.clear { clear: both; }

View File

@ -8,11 +8,39 @@ function( require, Benchmark, document, selectors ) {
// Convert selectors to an array
selectors = selectors.split("\n");
var // Test HTML file name in the data folder
var // Class manipulation
// IE doesn't match non-breaking spaces with \s
rtrim = /\S/.test("\xA0") ? (/^[\s\xA0]+|[\s\xA0]+$/g) : /^\s+|\s+$/g,
rspaces = /\s+/,
ptrim = String.prototype.trim,
// Test HTML file name in the data folder
testHtml = "selector",
// Construct search parameters object
urlParams = (function() {
var parts, value,
params = {},
search = location.search.substring(1).split("&"),
i = 0,
len = search.length;
for ( ; i < len; i++ ) {
parts = search[i].split("=");
value = parts[1];
// Cast booleans and treat no value as true
params[ decodeURIComponent(parts[0]) ] =
value && value !== "true" ?
value === "false" ? false :
decodeURIComponent( value ) :
true;
}
return params;
})(),
// Whether to allow the use of QSA by the selector engines
useQSA = false,
useQSA = urlParams.qsa || false,
// Queue for benchmark suites
suites = [],
@ -33,10 +61,10 @@ function( require, Benchmark, document, selectors ) {
"sizzle": "Sizzle( s )"
},
// Just cause I'm lazy
numEngines = (function() {
var engine,
count = 0;
for ( engine in engines ) {
if ( engines.hasOwnProperty(engine) ) {
count++;
@ -50,6 +78,80 @@ function( require, Benchmark, document, selectors ) {
// Expose iframeCallbacks
window.iframeCallbacks = {};
/**
* Trim leading and trailing whitespace
*
* @param {String} str The string to trim
*/
var trim = ptrim ?
function( str ) {
return ptrim.call( str );
} :
function( str ) {
return str.replace( rtrim, "" );
};
/**
* Returns whether the element has the given class
*
* @param {Element} elem The element to check
* @param {String} classStr The className property is scanned for this class
*/
function hasClass( elem, classStr ) {
return elem && classStr &&
(" " + elem.className + " ").indexOf( " " + classStr + " " ) > -1;
}
/**
* Adds the given class to the element if it does not exist
*
* @param {Element} elem The element on which to add the class
* @param {String} classStr The class to add
*/
function addClass( elem, classStr ) {
classStr = classStr.split( rspaces );
var c,
cls = " " + elem.className + " ",
i = 0,
len = classStr.length;
for ( ; i < len; ++i ) {
c = classStr[ i ];
if ( c && cls.indexOf(" " + c + " ") < 0 ) {
cls += c + " ";
}
}
elem.className = trim( cls );
}
/**
* Removes a given class on the element
*
* @param {Element} elem The element from which to remove the class
* @param {String} classStr The class to remove
*/
function removeClass( elem, classStr ) {
var cls, len, i;
if ( classStr !== undefined ) {
classStr = classStr.split( rspaces );
cls = " " + elem.className + " ";
i = 0;
len = classStr.length;
for ( ; i < len; ++i ) {
cls = cls.replace(" " + classStr[ i ] + " ", " ");
}
cls = trim( cls );
} else {
// Remove all classes
cls = "";
}
if ( elem.className !== cls ) {
elem.className = cls;
}
}
/**
* Add random number to the url to stop caching
*
@ -184,37 +286,43 @@ function( require, Benchmark, document, selectors ) {
Benchmark.options.async = true;
Benchmark.options.onError = function( error ) {
debugger;
console.error( error );
};
/* Benchmark Suite Options
---------------------------------------------------------------------- */
Benchmark.Suite.options.onStart = function() {
console.log( this.name + ":" );
var selectorElem = document.getElementById("selector" + selectorIndex);
addClass( selectorElem, "pending" );
};
Benchmark.Suite.options.onCycle = function( event ) {
console.log( event.target );
var tableBody = document.getElementById("perf-table-body"),
tds = tableBody.getElementsByTagName("td");
tds[ event.target.id + selectorIndex ].innerHTML = Benchmark.formatNumber( event.target.hz.toFixed(2) );
};
Benchmark.Suite.options.onComplete = function() {
var formatNumber = Benchmark.formatNumber,
var i, len,
selectorElem = document.getElementById("selector" + selectorIndex),
tableBody = document.getElementById("perf-table-body"),
tds = tableBody.getElementsByTagName("td"),
fastest = this.filter("fastest"),
fastestHz = getHz(fastest[0]),
slowest = this.filter("slowest"),
slowestHz = getHz(slowest[0]),
i = 0,
len = iframes[ this.name ].length;
slowest = this.filter("slowest");
var percent = ( (fastestHz / slowestHz) - 1 ) * 100;
removeClass( selectorElem, "pending" );
console.log(
fastest[0].name + " is " +
formatNumber( percent < 1 ? percent.toFixed(2) : Math.round(percent) ) +
"% faster."
);
// Highlight fastest green
for ( i = 0, len = fastest.length; i < len; i++ ) {
addClass( tds[ fastest[i].id + selectorIndex ], "green" );
}
// Highlight slowest red
for ( i = 0, len = slowest.length; i < len; i++ ) {
addClass( tds[ slowest[i].id + selectorIndex ], "red" );
}
// Remove all added iframes for this suite
for ( ; i < len; i++ ) {
for ( i = 0, len = iframes[ this.name ].length; i < len; i++ ) {
document.body.removeChild( iframes[ this.name ].pop() );
}
delete iframes[ this.name ];
@ -231,7 +339,35 @@ function( require, Benchmark, document, selectors ) {
}
};
// GOOOOO
/**
* Adds all of the necessary headers and rows
* for all selector engines
*/
function buildTable() {
var engine,
i = 0,
len = selectors.length,
headers = "<th class='small selector'>selectors</th>",
emptyColumns = "",
rows = "";
// Build out headers
for ( engine in engines ) {
headers += "<th class='text-right'>" + engine + "</th>";
emptyColumns += "<td class='text-right'>&nbsp;</td>";
}
// Build out initial rows
for ( ; i < len; i++ ) {
rows += "<tr><td id='selector" + i + "' class='small selector'><span>" + selectors[i] + "</span></td>" + emptyColumns + "</tr>";
}
document.getElementById("perf-table-headers").innerHTML = headers;
document.getElementById("perf-table-body").innerHTML = rows;
}
// Kick it off
buildTable();
testSelector( selectors[selectorIndex] );
});