mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-24 13:21:05 +00:00
Bug 1481037 - Update StyleBench. r=jmaher
Pick upstream changes. Differential Revision: https://phabricator.services.mozilla.com/D2757 --HG-- extra : moz-landing-system : lando
This commit is contained in:
parent
6480962188
commit
0f460b1379
@ -378,13 +378,43 @@ class Output(object):
|
||||
"""
|
||||
correctionFactor = 3
|
||||
results = [i for i, j in val_list]
|
||||
# stylebench has 4 tests, each of these are made of up 12 subtests
|
||||
# and a sum of the 12 values. We receive 52 values, and want to use
|
||||
# the 4 test values, not the sub test values.
|
||||
if len(results) != 52:
|
||||
raise Exception("StyleBench has 52 subtests, found: %s instead" % len(results))
|
||||
|
||||
results = results[12::13]
|
||||
# stylebench has 5 tests, each of these are made of up 5 subtests
|
||||
#
|
||||
# * Adding classes.
|
||||
# * Removing classes.
|
||||
# * Mutating attributes.
|
||||
# * Adding leaf elements.
|
||||
# * Removing leaf elements.
|
||||
#
|
||||
# which are made of two subtests each (sync/async) and repeated 5 times
|
||||
# each, thus, the list here looks like:
|
||||
#
|
||||
# [Test name/Adding classes - 0/ Sync; <x>]
|
||||
# [Test name/Adding classes - 0/ Async; <y>]
|
||||
# [Test name/Adding classes - 0; <x> + <y>]
|
||||
# [Test name/Removing classes - 0/ Sync; <x>]
|
||||
# [Test name/Removing classes - 0/ Async; <y>]
|
||||
# [Test name/Removing classes - 0; <x> + <y>]
|
||||
# ...
|
||||
# [Test name/Adding classes - 1 / Sync; <x>]
|
||||
# [Test name/Adding classes - 1 / Async; <y>]
|
||||
# [Test name/Adding classes - 1 ; <x> + <y>]
|
||||
# ...
|
||||
# [Test name/Removing leaf elements - 4; <x> + <y>]
|
||||
# [Test name; <sum>] <- This is what we want.
|
||||
#
|
||||
# So, 5 (subtests) *
|
||||
# 5 (repetitions) *
|
||||
# 3 (entries per repetition (sync/async/sum)) =
|
||||
# 75 entries for test before the sum.
|
||||
#
|
||||
# We receive 76 entries per test, which ads up to 380. We want to use
|
||||
# the 5 test entries, not the rest.
|
||||
if len(results) != 380:
|
||||
raise Exception("StyleBench has 380 entries, found: %s instead" % len(results))
|
||||
|
||||
results = results[75::76]
|
||||
score = 60 * 1000 / filter.geometric_mean(results) / correctionFactor
|
||||
return score
|
||||
|
||||
|
@ -270,13 +270,43 @@ class Output(object):
|
||||
"""
|
||||
correctionFactor = 3
|
||||
results = [i for i, j in val_list]
|
||||
# stylebench has 4 tests, each of these are made of up 12 subtests
|
||||
# and a sum of the 12 values. We receive 52 values, and want to use
|
||||
# the 4 test values, not the sub test values.
|
||||
if len(results) != 52:
|
||||
raise Exception("StyleBench has 52 subtests, found: %s instead" % len(results))
|
||||
|
||||
results = results[12::13]
|
||||
# stylebench has 5 tests, each of these are made of up 5 subtests
|
||||
#
|
||||
# * Adding classes.
|
||||
# * Removing classes.
|
||||
# * Mutating attributes.
|
||||
# * Adding leaf elements.
|
||||
# * Removing leaf elements.
|
||||
#
|
||||
# which are made of two subtests each (sync/async) and repeated 5 times
|
||||
# each, thus, the list here looks like:
|
||||
#
|
||||
# [Test name/Adding classes - 0/ Sync; <x>]
|
||||
# [Test name/Adding classes - 0/ Async; <y>]
|
||||
# [Test name/Adding classes - 0; <x> + <y>]
|
||||
# [Test name/Removing classes - 0/ Sync; <x>]
|
||||
# [Test name/Removing classes - 0/ Async; <y>]
|
||||
# [Test name/Removing classes - 0; <x> + <y>]
|
||||
# ...
|
||||
# [Test name/Adding classes - 1 / Sync; <x>]
|
||||
# [Test name/Adding classes - 1 / Async; <y>]
|
||||
# [Test name/Adding classes - 1 ; <x> + <y>]
|
||||
# ...
|
||||
# [Test name/Removing leaf elements - 4; <x> + <y>]
|
||||
# [Test name; <sum>] <- This is what we want.
|
||||
#
|
||||
# So, 5 (subtests) *
|
||||
# 5 (repetitions) *
|
||||
# 3 (entries per repetition (sync/async/sum)) =
|
||||
# 75 entries for test before the sum.
|
||||
#
|
||||
# We receive 76 entries per test, which ads up to 380. We want to use
|
||||
# the 5 test entries, not the rest.
|
||||
if len(results) != 380:
|
||||
raise Exception("StyleBench has 380 entries, found: %s instead" % len(results))
|
||||
|
||||
results = results[75::76]
|
||||
score = 60 * 1000 / filter.geometric_mean(results) / correctionFactor
|
||||
return score
|
||||
|
||||
|
13
third_party/webkit/PerformanceTests/StyleBench/README_MOZILLA
vendored
Normal file
13
third_party/webkit/PerformanceTests/StyleBench/README_MOZILLA
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
The source from this directory was copied from the
|
||||
PerformanceTests/StyleBench directory of the Webkit repository
|
||||
at: https://svn.webkit.org/repository/webkit/trunk
|
||||
|
||||
The SVN revision used was: 234578
|
||||
|
||||
The contents of this directory are intended for use to "train" the
|
||||
profile guided optimization (PGO) of Firefox and for benchmarking
|
||||
scenarios. The files inside this directory are not intended to ship
|
||||
with Firefox or any other product. If files inside this directory
|
||||
are useful for other purposes (e.g. JavaScript libraries), consumers
|
||||
should vendor those files separately, as it is not appropriate to pull
|
||||
in components of StyleBench for use outside of StyleBench.
|
@ -1,20 +1,17 @@
|
||||
<!DOCTYPE html>
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||
<title>StyleBench 0.1</title>
|
||||
<link rel="stylesheet" href="../Speedometer/resources/main.css">
|
||||
<script src="../Speedometer/resources/main.js" defer></script>
|
||||
<script src="../Speedometer/resources/benchmark-runner.js" defer></script>
|
||||
<script src="../Speedometer/resources/benchmark-report.js" defer></script>
|
||||
<title>StyleBench 0.3</title>
|
||||
<link rel="stylesheet" href="resources/main.css">
|
||||
<script src="resources/main.js" defer></script>
|
||||
<script src="resources/benchmark-runner.js" defer></script>
|
||||
<script src="resources/benchmark-report.js" defer></script>
|
||||
<script src="../resources/statistics.js" defer></script>
|
||||
<script src="resources/style-bench.js" defer></script>
|
||||
<script src="resources/tests.js" defer></script>
|
||||
<script>
|
||||
addEventListener('load', () => {
|
||||
if (!window.location.protocol.startsWith('http'))
|
||||
showSection('local-message', false);
|
||||
|
||||
if (location.search == '?gecko' || location.search == '?raptor')
|
||||
startTest();
|
||||
});
|
||||
|
113
third_party/webkit/PerformanceTests/StyleBench/mozilla.patch
vendored
Normal file
113
third_party/webkit/PerformanceTests/StyleBench/mozilla.patch
vendored
Normal file
@ -0,0 +1,113 @@
|
||||
diff --git a/third_party/webkit/PerformanceTests/StyleBench/index.html b/third_party/webkit/PerformanceTests/StyleBench/index.html
|
||||
index c77554dc3506..2a561a9cbb54 100644
|
||||
--- a/third_party/webkit/PerformanceTests/StyleBench/index.html
|
||||
+++ b/third_party/webkit/PerformanceTests/StyleBench/index.html
|
||||
@@ -5,16 +5,22 @@
|
||||
<title>StyleBench 0.3</title>
|
||||
<link rel="stylesheet" href="resources/main.css">
|
||||
<script src="resources/main.js" defer></script>
|
||||
<script src="resources/benchmark-runner.js" defer></script>
|
||||
<script src="resources/benchmark-report.js" defer></script>
|
||||
<script src="../resources/statistics.js" defer></script>
|
||||
<script src="resources/style-bench.js" defer></script>
|
||||
<script src="resources/tests.js" defer></script>
|
||||
+ <script>
|
||||
+ addEventListener('load', () => {
|
||||
+ if (location.search == '?gecko' || location.search == '?raptor')
|
||||
+ startTest();
|
||||
+ });
|
||||
+ </script>
|
||||
</head>
|
||||
<body>
|
||||
<main>
|
||||
<a id="logo-link" href="javascript:showHome()"></a>
|
||||
|
||||
<section id="home" class="selected">
|
||||
<p>
|
||||
StyleBench is a browser benchmark that measures the performance of the style resolution mechanism.
|
||||
diff --git a/third_party/webkit/PerformanceTests/StyleBench/resources/benchmark-report.js b/third_party/webkit/PerformanceTests/StyleBench/resources/benchmark-report.js
|
||||
index b33021d9d9ce..58b3e46982d1 100644
|
||||
--- a/third_party/webkit/PerformanceTests/StyleBench/resources/benchmark-report.js
|
||||
+++ b/third_party/webkit/PerformanceTests/StyleBench/resources/benchmark-report.js
|
||||
@@ -1,12 +1,13 @@
|
||||
// This file can be customized to report results as needed.
|
||||
|
||||
(function () {
|
||||
- if (!window.testRunner && location.search != '?webkit' && location.hash != '#webkit')
|
||||
+ if (!window.testRunner && location.search != '?webkit' && location.hash != '#webkit' &&
|
||||
+ location.search != '?gecko' && location.search != '?raptor')
|
||||
return;
|
||||
|
||||
if (window.testRunner)
|
||||
testRunner.waitUntilDone();
|
||||
|
||||
var scriptElement = document.createElement('script');
|
||||
scriptElement.src = '../resources/runner.js';
|
||||
document.head.appendChild(scriptElement);
|
||||
@@ -31,20 +32,22 @@
|
||||
customIterationCount: iterationCount,
|
||||
doNotIgnoreInitialRun: true,
|
||||
doNotMeasureMemoryUsage: true,
|
||||
continueTesting: !isLastTest,
|
||||
unit: unit,
|
||||
name: name,
|
||||
aggregator: aggregator};
|
||||
}
|
||||
- PerfTestRunner.prepareToMeasureValuesAsync(createTest(null, 'Geometric'));
|
||||
+ if (window.PerfTestRunner)
|
||||
+ PerfTestRunner.prepareToMeasureValuesAsync(createTest(null, 'Geometric'));
|
||||
},
|
||||
didRunSuites: function (measuredValues) {
|
||||
- PerfTestRunner.measureValueAsync(measuredValues.geomean);
|
||||
+ if (window.PerfTestRunner)
|
||||
+ PerfTestRunner.measureValueAsync(measuredValues.geomean);
|
||||
valuesByIteration.push(measuredValues);
|
||||
},
|
||||
didFinishLastIteration: function () {
|
||||
document.head.removeChild(document.querySelector('style'));
|
||||
|
||||
var measuredValuesByFullName = {};
|
||||
function addToMeasuredValue(value, fullName, aggregator) {
|
||||
var values = measuredValuesByFullName[fullName] || new Array;
|
||||
@@ -63,21 +66,37 @@
|
||||
for (var subtestName in test.tests)
|
||||
addToMeasuredValue(test.tests[subtestName], suiteName + '/' + testName + '/' + subtestName);
|
||||
addToMeasuredValue(test.total, suiteName + '/' + testName, 'Total');
|
||||
}
|
||||
addToMeasuredValue(suite.total, suiteName, 'Total');
|
||||
}
|
||||
});
|
||||
|
||||
- PerfTestRunner.reportValues(createTest(null, null, false, 'pt'), scores);
|
||||
+ if (window.PerfTestRunner)
|
||||
+ PerfTestRunner.reportValues(createTest(null, null, false, 'pt'), scores);
|
||||
|
||||
var fullNames = new Array;
|
||||
for (var fullName in measuredValuesByFullName)
|
||||
fullNames.push(fullName);
|
||||
|
||||
- for (var i = 0; i < fullNames.length; i++) {
|
||||
- var values = measuredValuesByFullName[fullNames[i]];
|
||||
- PerfTestRunner.reportValues(createTest(fullNames[i], values.aggregator, i + 1 == fullNames.length), values);
|
||||
+ if (location.search == '?raptor') {
|
||||
+ var data = ['raptor-benchmark', 'speedometer', measuredValuesByFullName];
|
||||
+ window.postMessage(data, '*');
|
||||
+ } else if (typeof tpRecordTime !== "undefined") {
|
||||
+ var values = new Array;
|
||||
+ var allNames = new Array;
|
||||
+ for (var i = 0; i < fullNames.length; i++) {
|
||||
+ var vals = measuredValuesByFullName[fullNames[i]];
|
||||
+ values.push(vals);
|
||||
+ for (var count = 0; count < vals.length; count ++)
|
||||
+ allNames.push(fullNames[i]);
|
||||
+ }
|
||||
+ tpRecordTime(values.join(','), 0, allNames.join(','));
|
||||
+ } else if (window.PerfTestRunner) {
|
||||
+ for (var i = 0; i < fullNames.length; i++) {
|
||||
+ var values = measuredValuesByFullName[fullNames[i]];
|
||||
+ PerfTestRunner.reportValues(createTest(fullNames[i], values.aggregator, i + 1 == fullNames.length), values);
|
||||
+ }
|
||||
}
|
||||
}
|
||||
};
|
||||
})();
|
102
third_party/webkit/PerformanceTests/StyleBench/resources/benchmark-report.js
vendored
Normal file
102
third_party/webkit/PerformanceTests/StyleBench/resources/benchmark-report.js
vendored
Normal file
@ -0,0 +1,102 @@
|
||||
// This file can be customized to report results as needed.
|
||||
|
||||
(function () {
|
||||
if (!window.testRunner && location.search != '?webkit' && location.hash != '#webkit' &&
|
||||
location.search != '?gecko' && location.search != '?raptor')
|
||||
return;
|
||||
|
||||
if (window.testRunner)
|
||||
testRunner.waitUntilDone();
|
||||
|
||||
var scriptElement = document.createElement('script');
|
||||
scriptElement.src = '../resources/runner.js';
|
||||
document.head.appendChild(scriptElement);
|
||||
|
||||
var styleElement = document.createElement('style');
|
||||
styleElement.textContent = 'pre { padding-top: 600px; }';
|
||||
document.head.appendChild(styleElement);
|
||||
|
||||
var createTest;
|
||||
var valuesByIteration = new Array;
|
||||
|
||||
window.onload = function () {
|
||||
document.body.removeChild(document.querySelector('main'));
|
||||
startBenchmark();
|
||||
}
|
||||
|
||||
window.benchmarkClient = {
|
||||
iterationCount: 5, // Use 4 different instances of DRT/WTR to run 5 iterations.
|
||||
willStartFirstIteration: function (iterationCount) {
|
||||
createTest = function (name, aggregator, isLastTest, unit = 'ms') {
|
||||
return {
|
||||
customIterationCount: iterationCount,
|
||||
doNotIgnoreInitialRun: true,
|
||||
doNotMeasureMemoryUsage: true,
|
||||
continueTesting: !isLastTest,
|
||||
unit: unit,
|
||||
name: name,
|
||||
aggregator: aggregator};
|
||||
}
|
||||
if (window.PerfTestRunner)
|
||||
PerfTestRunner.prepareToMeasureValuesAsync(createTest(null, 'Geometric'));
|
||||
},
|
||||
didRunSuites: function (measuredValues) {
|
||||
if (window.PerfTestRunner)
|
||||
PerfTestRunner.measureValueAsync(measuredValues.geomean);
|
||||
valuesByIteration.push(measuredValues);
|
||||
},
|
||||
didFinishLastIteration: function () {
|
||||
document.head.removeChild(document.querySelector('style'));
|
||||
|
||||
var measuredValuesByFullName = {};
|
||||
function addToMeasuredValue(value, fullName, aggregator) {
|
||||
var values = measuredValuesByFullName[fullName] || new Array;
|
||||
measuredValuesByFullName[fullName] = values;
|
||||
values.push(value);
|
||||
values.aggregator = aggregator;
|
||||
}
|
||||
|
||||
var scores = [];
|
||||
valuesByIteration.forEach(function (measuredValues) {
|
||||
scores.push(measuredValues.score);
|
||||
for (var suiteName in measuredValues.tests) {
|
||||
var suite = measuredValues.tests[suiteName];
|
||||
for (var testName in suite.tests) {
|
||||
var test = suite.tests[testName];
|
||||
for (var subtestName in test.tests)
|
||||
addToMeasuredValue(test.tests[subtestName], suiteName + '/' + testName + '/' + subtestName);
|
||||
addToMeasuredValue(test.total, suiteName + '/' + testName, 'Total');
|
||||
}
|
||||
addToMeasuredValue(suite.total, suiteName, 'Total');
|
||||
}
|
||||
});
|
||||
|
||||
if (window.PerfTestRunner)
|
||||
PerfTestRunner.reportValues(createTest(null, null, false, 'pt'), scores);
|
||||
|
||||
var fullNames = new Array;
|
||||
for (var fullName in measuredValuesByFullName)
|
||||
fullNames.push(fullName);
|
||||
|
||||
if (location.search == '?raptor') {
|
||||
var data = ['raptor-benchmark', 'speedometer', measuredValuesByFullName];
|
||||
window.postMessage(data, '*');
|
||||
} else if (typeof tpRecordTime !== "undefined") {
|
||||
var values = new Array;
|
||||
var allNames = new Array;
|
||||
for (var i = 0; i < fullNames.length; i++) {
|
||||
var vals = measuredValuesByFullName[fullNames[i]];
|
||||
values.push(vals);
|
||||
for (var count = 0; count < vals.length; count ++)
|
||||
allNames.push(fullNames[i]);
|
||||
}
|
||||
tpRecordTime(values.join(','), 0, allNames.join(','));
|
||||
} else if (window.PerfTestRunner) {
|
||||
for (var i = 0; i < fullNames.length; i++) {
|
||||
var values = measuredValuesByFullName[fullNames[i]];
|
||||
PerfTestRunner.reportValues(createTest(fullNames[i], values.aggregator, i + 1 == fullNames.length), values);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
})();
|
299
third_party/webkit/PerformanceTests/StyleBench/resources/benchmark-runner.js
vendored
Normal file
299
third_party/webkit/PerformanceTests/StyleBench/resources/benchmark-runner.js
vendored
Normal file
@ -0,0 +1,299 @@
|
||||
// FIXME: Use the real promise if available.
|
||||
// FIXME: Make sure this interface is compatible with the real Promise.
|
||||
function SimplePromise() {
|
||||
this._chainedPromise = null;
|
||||
this._callback = null;
|
||||
}
|
||||
|
||||
SimplePromise.prototype.then = function (callback) {
|
||||
if (this._callback)
|
||||
throw "SimplePromise doesn't support multiple calls to then";
|
||||
this._callback = callback;
|
||||
this._chainedPromise = new SimplePromise;
|
||||
|
||||
if (this._resolved)
|
||||
this.resolve(this._resolvedValue);
|
||||
|
||||
return this._chainedPromise;
|
||||
}
|
||||
|
||||
SimplePromise.prototype.resolve = function (value) {
|
||||
if (!this._callback) {
|
||||
this._resolved = true;
|
||||
this._resolvedValue = value;
|
||||
return;
|
||||
}
|
||||
|
||||
var result = this._callback(value);
|
||||
if (result instanceof SimplePromise) {
|
||||
var chainedPromise = this._chainedPromise;
|
||||
result.then(function (result) { chainedPromise.resolve(result); });
|
||||
} else
|
||||
this._chainedPromise.resolve(result);
|
||||
}
|
||||
|
||||
function BenchmarkTestStep(testName, testFunction) {
|
||||
this.name = testName;
|
||||
this.run = testFunction;
|
||||
}
|
||||
|
||||
function BenchmarkRunner(suites, client) {
|
||||
this._suites = suites;
|
||||
this._prepareReturnValue = null;
|
||||
this._client = client;
|
||||
}
|
||||
|
||||
BenchmarkRunner.prototype.waitForElement = function (selector) {
|
||||
var promise = new SimplePromise;
|
||||
var contentDocument = this._frame.contentDocument;
|
||||
|
||||
function resolveIfReady() {
|
||||
var element = contentDocument.querySelector(selector);
|
||||
if (element)
|
||||
return promise.resolve(element);
|
||||
setTimeout(resolveIfReady, 50);
|
||||
}
|
||||
|
||||
resolveIfReady();
|
||||
return promise;
|
||||
}
|
||||
|
||||
BenchmarkRunner.prototype._removeFrame = function () {
|
||||
if (this._frame) {
|
||||
this._frame.parentNode.removeChild(this._frame);
|
||||
this._frame = null;
|
||||
}
|
||||
}
|
||||
|
||||
BenchmarkRunner.prototype._appendFrame = function (src) {
|
||||
var frame = document.createElement('iframe');
|
||||
frame.style.width = '800px';
|
||||
frame.style.height = '600px';
|
||||
frame.style.border = '0px none';
|
||||
frame.style.position = 'absolute';
|
||||
frame.setAttribute('scrolling', 'no');
|
||||
|
||||
var marginLeft = parseInt(getComputedStyle(document.body).marginLeft);
|
||||
var marginTop = parseInt(getComputedStyle(document.body).marginTop);
|
||||
if (window.innerWidth > 800 + marginLeft && window.innerHeight > 600 + marginTop) {
|
||||
frame.style.left = marginLeft + 'px';
|
||||
frame.style.top = marginTop + 'px';
|
||||
} else {
|
||||
frame.style.left = '0px';
|
||||
frame.style.top = '0px';
|
||||
}
|
||||
|
||||
if (this._client && this._client.willAddTestFrame)
|
||||
this._client.willAddTestFrame(frame);
|
||||
|
||||
document.body.insertBefore(frame, document.body.firstChild);
|
||||
this._frame = frame;
|
||||
return frame;
|
||||
}
|
||||
|
||||
BenchmarkRunner.prototype._waitAndWarmUp = function () {
|
||||
var startTime = Date.now();
|
||||
|
||||
function Fibonacci(n) {
|
||||
if (Date.now() - startTime > 100)
|
||||
return;
|
||||
if (n <= 0)
|
||||
return 0;
|
||||
else if (n == 1)
|
||||
return 1;
|
||||
return Fibonacci(n - 2) + Fibonacci(n - 1);
|
||||
}
|
||||
|
||||
var promise = new SimplePromise;
|
||||
setTimeout(function () {
|
||||
Fibonacci(100);
|
||||
promise.resolve();
|
||||
}, 200);
|
||||
return promise;
|
||||
}
|
||||
|
||||
BenchmarkRunner.prototype._writeMark = function(name) {
|
||||
if (window.performance && window.performance.mark)
|
||||
window.performance.mark(name);
|
||||
}
|
||||
|
||||
// This function ought be as simple as possible. Don't even use SimplePromise.
|
||||
BenchmarkRunner.prototype._runTest = function(suite, test, prepareReturnValue, callback)
|
||||
{
|
||||
var self = this;
|
||||
var now = window.performance && window.performance.now ? function () { return window.performance.now(); } : Date.now;
|
||||
|
||||
var contentWindow = self._frame.contentWindow;
|
||||
var contentDocument = self._frame.contentDocument;
|
||||
|
||||
self._writeMark(suite.name + '.' + test.name + '-start');
|
||||
var startTime = now();
|
||||
test.run(prepareReturnValue, contentWindow, contentDocument);
|
||||
var endTime = now();
|
||||
self._writeMark(suite.name + '.' + test.name + '-sync-end');
|
||||
|
||||
var syncTime = endTime - startTime;
|
||||
|
||||
var startTime = now();
|
||||
setTimeout(function () {
|
||||
// Some browsers don't immediately update the layout for paint.
|
||||
// Force the layout here to ensure we're measuring the layout time.
|
||||
var height = self._frame.contentDocument.body.getBoundingClientRect().height;
|
||||
var endTime = now();
|
||||
self._frame.contentWindow._unusedHeightValue = height; // Prevent dead code elimination.
|
||||
self._writeMark(suite.name + '.' + test.name + '-async-end');
|
||||
callback(syncTime, endTime - startTime, height);
|
||||
}, 0);
|
||||
}
|
||||
|
||||
function BenchmarkState(suites) {
|
||||
this._suites = suites;
|
||||
this._suiteIndex = -1;
|
||||
this._testIndex = 0;
|
||||
this.next();
|
||||
}
|
||||
|
||||
BenchmarkState.prototype.currentSuite = function() {
|
||||
return this._suites[this._suiteIndex];
|
||||
}
|
||||
|
||||
BenchmarkState.prototype.currentTest = function () {
|
||||
var suite = this.currentSuite();
|
||||
return suite ? suite.tests[this._testIndex] : null;
|
||||
}
|
||||
|
||||
BenchmarkState.prototype.next = function () {
|
||||
this._testIndex++;
|
||||
|
||||
var suite = this._suites[this._suiteIndex];
|
||||
if (suite && this._testIndex < suite.tests.length)
|
||||
return this;
|
||||
|
||||
this._testIndex = 0;
|
||||
do {
|
||||
this._suiteIndex++;
|
||||
} while (this._suiteIndex < this._suites.length && this._suites[this._suiteIndex].disabled);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
BenchmarkState.prototype.isFirstTest = function () {
|
||||
return !this._testIndex;
|
||||
}
|
||||
|
||||
BenchmarkState.prototype.prepareCurrentSuite = function (runner, frame) {
|
||||
var suite = this.currentSuite();
|
||||
var promise = new SimplePromise;
|
||||
frame.onload = function () {
|
||||
suite.prepare(runner, frame.contentWindow, frame.contentDocument).then(function (result) { promise.resolve(result); });
|
||||
}
|
||||
frame.src = 'resources/' + suite.url;
|
||||
return promise;
|
||||
}
|
||||
|
||||
BenchmarkRunner.prototype.step = function (state) {
|
||||
if (!state) {
|
||||
state = new BenchmarkState(this._suites);
|
||||
this._measuredValues = {tests: {}, total: 0, mean: NaN, geomean: NaN, score: NaN};
|
||||
}
|
||||
|
||||
var suite = state.currentSuite();
|
||||
if (!suite) {
|
||||
this._finalize();
|
||||
var promise = new SimplePromise;
|
||||
promise.resolve();
|
||||
return promise;
|
||||
}
|
||||
|
||||
if (state.isFirstTest()) {
|
||||
this._removeFrame();
|
||||
var self = this;
|
||||
return state.prepareCurrentSuite(this, this._appendFrame()).then(function (prepareReturnValue) {
|
||||
self._prepareReturnValue = prepareReturnValue;
|
||||
return self._runTestAndRecordResults(state);
|
||||
});
|
||||
}
|
||||
|
||||
return this._runTestAndRecordResults(state);
|
||||
}
|
||||
|
||||
BenchmarkRunner.prototype.runAllSteps = function (startingState) {
|
||||
var nextCallee = this.runAllSteps.bind(this);
|
||||
this.step(startingState).then(function (nextState) {
|
||||
if (nextState)
|
||||
nextCallee(nextState);
|
||||
});
|
||||
}
|
||||
|
||||
BenchmarkRunner.prototype.runMultipleIterations = function (iterationCount) {
|
||||
var self = this;
|
||||
var currentIteration = 0;
|
||||
|
||||
this._runNextIteration = function () {
|
||||
currentIteration++;
|
||||
if (currentIteration < iterationCount)
|
||||
self.runAllSteps();
|
||||
else if (this._client && this._client.didFinishLastIteration)
|
||||
this._client.didFinishLastIteration();
|
||||
}
|
||||
|
||||
if (this._client && this._client.willStartFirstIteration)
|
||||
this._client.willStartFirstIteration(iterationCount);
|
||||
|
||||
self.runAllSteps();
|
||||
}
|
||||
|
||||
BenchmarkRunner.prototype._runTestAndRecordResults = function (state) {
|
||||
var promise = new SimplePromise;
|
||||
var suite = state.currentSuite();
|
||||
var test = state.currentTest();
|
||||
|
||||
if (this._client && this._client.willRunTest)
|
||||
this._client.willRunTest(suite, test);
|
||||
|
||||
var self = this;
|
||||
setTimeout(function () {
|
||||
self._runTest(suite, test, self._prepareReturnValue, function (syncTime, asyncTime) {
|
||||
var suiteResults = self._measuredValues.tests[suite.name] || {tests:{}, total: 0};
|
||||
var total = syncTime + asyncTime;
|
||||
self._measuredValues.tests[suite.name] = suiteResults;
|
||||
suiteResults.tests[test.name] = {tests: {'Sync': syncTime, 'Async': asyncTime}, total: total};
|
||||
suiteResults.total += total;
|
||||
|
||||
if (self._client && self._client.didRunTest)
|
||||
self._client.didRunTest(suite, test);
|
||||
|
||||
state.next();
|
||||
promise.resolve(state);
|
||||
});
|
||||
}, 0);
|
||||
return promise;
|
||||
}
|
||||
|
||||
BenchmarkRunner.prototype._finalize = function () {
|
||||
this._removeFrame();
|
||||
|
||||
if (this._client && this._client.didRunSuites) {
|
||||
var product = 1;
|
||||
var values = [];
|
||||
for (var suiteName in this._measuredValues.tests) {
|
||||
var suiteTotal = this._measuredValues.tests[suiteName].total;
|
||||
product *= suiteTotal;
|
||||
values.push(suiteTotal);
|
||||
}
|
||||
|
||||
values.sort(function (a, b) { return a - b }); // Avoid the loss of significance for the sum.
|
||||
var total = values.reduce(function (a, b) { return a + b });
|
||||
var geomean = Math.pow(product, 1 / values.length);
|
||||
|
||||
var correctionFactor = 1.5; // This factor makes the test score look reasonably fit within 0 to 140.
|
||||
this._measuredValues.total = total;
|
||||
this._measuredValues.mean = total / values.length;
|
||||
this._measuredValues.geomean = geomean;
|
||||
this._measuredValues.score = 60 * 1000 / geomean / correctionFactor;
|
||||
this._client.didRunSuites(this._measuredValues);
|
||||
}
|
||||
|
||||
if (this._runNextIteration)
|
||||
this._runNextIteration();
|
||||
}
|
0
third_party/webkit/PerformanceTests/StyleBench/resources/gauge.png
vendored
Normal file
0
third_party/webkit/PerformanceTests/StyleBench/resources/gauge.png
vendored
Normal file
0
third_party/webkit/PerformanceTests/StyleBench/resources/gauge@2x.png
vendored
Normal file
0
third_party/webkit/PerformanceTests/StyleBench/resources/gauge@2x.png
vendored
Normal file
286
third_party/webkit/PerformanceTests/StyleBench/resources/main.css
vendored
Normal file
286
third_party/webkit/PerformanceTests/StyleBench/resources/main.css
vendored
Normal file
@ -0,0 +1,286 @@
|
||||
body {
|
||||
background-color: rgb(46, 51, 55);
|
||||
color: rgb(235, 235, 235);
|
||||
font-family: "Helvetica Neue", Helvetica, Verdana, sans-serif;
|
||||
}
|
||||
|
||||
::selection {
|
||||
color: rgb(46, 51, 55);
|
||||
background-color: rgb(235, 235, 235);
|
||||
}
|
||||
|
||||
h1,
|
||||
button {
|
||||
font-family: "Futura-Medium", Futura, "Helvetica Neue", Helvetica, Verdana, sans-serif;
|
||||
}
|
||||
|
||||
code {
|
||||
font-family: Menlo, Monaco, monospace;
|
||||
font-size: smaller;
|
||||
}
|
||||
|
||||
button {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
hr {
|
||||
border: 1px solid rgb(235, 235, 235);
|
||||
width: 50%;
|
||||
margin: 40px auto;
|
||||
}
|
||||
|
||||
img {
|
||||
-webkit-user-select: none;
|
||||
-webkit-user-drag: none;
|
||||
}
|
||||
|
||||
main {
|
||||
display: block;
|
||||
position: absolute;
|
||||
width: 800px;
|
||||
height: 600px;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
margin-top: -321px;
|
||||
margin-left: -421px;
|
||||
padding: 15px;
|
||||
border: 6px solid rgb(235, 235, 235);
|
||||
border-radius: 20px;
|
||||
}
|
||||
|
||||
#logo {
|
||||
position: absolute;
|
||||
left: -70px;
|
||||
top: 115px;
|
||||
width: 75px;
|
||||
height: 406px;
|
||||
}
|
||||
|
||||
h1 {
|
||||
margin-top: 30px;
|
||||
font-size: 40px;
|
||||
font-weight: normal;
|
||||
color: rgb(235, 235, 235);
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
p {
|
||||
font-size: 16px;
|
||||
line-height: 21px;
|
||||
}
|
||||
|
||||
a {
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
.buttons {
|
||||
margin-top: 30px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
button {
|
||||
-webkit-appearance: none;
|
||||
border: 3px solid rgb(235, 235, 235);
|
||||
border-radius: 10px;
|
||||
min-width: 200px;
|
||||
padding: 5px 20px;
|
||||
margin: 0 40px;
|
||||
font-size: 25px;
|
||||
color: rgb(235, 235, 235);
|
||||
background-color: transparent;
|
||||
|
||||
-webkit-user-select: none;
|
||||
}
|
||||
|
||||
button:active {
|
||||
background-color: rgb(235, 235, 235);
|
||||
color: rgb(46, 51, 55);
|
||||
border-color: rgb(235, 235, 235) !important;
|
||||
}
|
||||
|
||||
button:focus {
|
||||
outline: none;
|
||||
border-color: rgb(232, 79, 79);
|
||||
}
|
||||
|
||||
section {
|
||||
display: none;
|
||||
}
|
||||
|
||||
section > p {
|
||||
margin: 10px 20px;
|
||||
}
|
||||
|
||||
section.selected {
|
||||
display: block;
|
||||
}
|
||||
|
||||
#testContainer {
|
||||
position: absolute;
|
||||
top: 15px;
|
||||
left: 15px;
|
||||
width: 800px;
|
||||
height: 600px;
|
||||
}
|
||||
|
||||
section#home > p {
|
||||
margin: 0 auto;
|
||||
width: 70%;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
section#home > p:first-child {
|
||||
margin-top: 160px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
section#home > .show-about {
|
||||
margin-top: 100px;
|
||||
}
|
||||
|
||||
section#home > .buttons {
|
||||
margin-top: 80px;
|
||||
}
|
||||
|
||||
section#running > #progress {
|
||||
position: absolute;
|
||||
bottom: -6px;
|
||||
left: 60px;
|
||||
right: 60px;
|
||||
height: 6px;
|
||||
background-color: rgb(128, 128, 128);
|
||||
border-left: 6px solid rgb(46, 51, 55);
|
||||
border-right: 6px solid rgb(46, 51, 55);
|
||||
}
|
||||
|
||||
section#running #progress-completed {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
height: 6px;
|
||||
width: 0;
|
||||
background-color: rgb(235, 235, 235);
|
||||
}
|
||||
|
||||
section#running > #info {
|
||||
position: absolute;
|
||||
bottom: -25px;
|
||||
left: 60px;
|
||||
right: 60px;
|
||||
height: 12px;
|
||||
color: rgb(128, 128, 128);
|
||||
text-align: center;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
section#summarized-results > #result-number,
|
||||
section#summarized-results > #confidence-number {
|
||||
font-family: "Futura-CondensedMedium", Futura, "Helvetica Neue", Helvetica, Verdana, sans-serif;
|
||||
}
|
||||
|
||||
section#summarized-results > #result-number {
|
||||
text-align: center;
|
||||
font-size: 145px;
|
||||
line-height: 145px;
|
||||
}
|
||||
|
||||
section#summarized-results > #confidence-number {
|
||||
text-align: center;
|
||||
font-size: 36px;
|
||||
line-height: 36px;
|
||||
color: rgb(128, 128, 128);
|
||||
}
|
||||
|
||||
section#detailed-results > table {
|
||||
float: left;
|
||||
width: 50%;
|
||||
}
|
||||
|
||||
section#detailed-results > .arithmetic-mean {
|
||||
clear: both;
|
||||
padding-top: 32px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
section#detailed-results > .arithmetic-mean > label {
|
||||
font-weight: bold;
|
||||
margin-right: 10px;
|
||||
color: rgb(128, 128, 128);
|
||||
}
|
||||
|
||||
section#detailed-results > .show-about {
|
||||
margin-top: 30px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
section#about h1 {
|
||||
margin-top: 10px;
|
||||
margin-bottom: 0px;
|
||||
font-size: 25px;
|
||||
}
|
||||
|
||||
section#about .note {
|
||||
color: rgb(128, 128, 128);
|
||||
}
|
||||
|
||||
table {
|
||||
border-spacing: 0;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
th,
|
||||
td {
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
th {
|
||||
text-align: right;
|
||||
color: rgb(128, 128, 128);
|
||||
}
|
||||
|
||||
.gauge {
|
||||
position: relative;
|
||||
width: 738px;
|
||||
height: 78px;
|
||||
background-image: url(gauge.png);
|
||||
background-size: 100% 100%;
|
||||
background-repat: no-repeat;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.gauge > .window {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 33px;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.gauge > .window > .needle {
|
||||
position: absolute;
|
||||
left: 363px;
|
||||
bottom: -88px;
|
||||
width: 4px;
|
||||
height: 400px;
|
||||
background-color: rgb(247, 148, 29);
|
||||
|
||||
-webkit-transform: rotate(-70deg);
|
||||
-webkit-transform-origin: 2px 400px;
|
||||
|
||||
-moz-transform: rotate(-70deg);
|
||||
-moz-transform-origin: 2px 400px;
|
||||
|
||||
transform: rotate(-70deg);
|
||||
transform-origin: 2px 400px;
|
||||
}
|
||||
|
||||
@media (-webkit-min-device-pixel-ratio: 2), (min--moz-device-pixel-ratio: 2), (min-resolution: 2dppx), (min-resolution: 192dpi) {
|
||||
#logo {
|
||||
content: url(logo@2x.png); /* FIXME: This does not work in Firefox. */
|
||||
}
|
||||
|
||||
.gauge {
|
||||
background-image: url(gauge@2x.png);
|
||||
}
|
||||
}
|
246
third_party/webkit/PerformanceTests/StyleBench/resources/main.js
vendored
Normal file
246
third_party/webkit/PerformanceTests/StyleBench/resources/main.js
vendored
Normal file
@ -0,0 +1,246 @@
|
||||
window.benchmarkClient = {
|
||||
displayUnit: 'runs/min',
|
||||
iterationCount: 10,
|
||||
stepCount: null,
|
||||
suitesCount: null,
|
||||
_measuredValuesList: [],
|
||||
_finishedTestCount: 0,
|
||||
_progressCompleted: null,
|
||||
willAddTestFrame: function (frame) {
|
||||
var main = document.querySelector('main');
|
||||
var style = getComputedStyle(main);
|
||||
frame.style.left = main.offsetLeft + parseInt(style.borderLeftWidth) + parseInt(style.paddingLeft) + 'px';
|
||||
frame.style.top = main.offsetTop + parseInt(style.borderTopWidth) + parseInt(style.paddingTop) + 'px';
|
||||
},
|
||||
willRunTest: function (suite, test) {
|
||||
document.getElementById('info').textContent = suite.name + ' ( ' + this._finishedTestCount + ' / ' + this.stepCount + ' )';
|
||||
},
|
||||
didRunTest: function () {
|
||||
this._finishedTestCount++;
|
||||
this._progressCompleted.style.width = (this._finishedTestCount * 100 / this.stepCount) + '%';
|
||||
},
|
||||
didRunSuites: function (measuredValues) {
|
||||
this._measuredValuesList.push(measuredValues);
|
||||
},
|
||||
willStartFirstIteration: function () {
|
||||
this._measuredValuesList = [];
|
||||
this._finishedTestCount = 0;
|
||||
this._progressCompleted = document.getElementById('progress-completed');
|
||||
document.getElementById('logo-link').onclick = function (event) { event.preventDefault(); return false; }
|
||||
},
|
||||
didFinishLastIteration: function () {
|
||||
document.getElementById('logo-link').onclick = null;
|
||||
|
||||
var results = this._computeResults(this._measuredValuesList, this.displayUnit);
|
||||
|
||||
this._updateGaugeNeedle(results.mean);
|
||||
document.getElementById('result-number').textContent = results.formattedMean;
|
||||
if (results.formattedDelta)
|
||||
document.getElementById('confidence-number').textContent = '\u00b1 ' + results.formattedDelta;
|
||||
|
||||
this._populateDetailedResults(results.formattedValues);
|
||||
document.getElementById('results-with-statistics').textContent = results.formattedMeanAndDelta;
|
||||
|
||||
if (this.displayUnit == 'ms') {
|
||||
document.getElementById('show-summary').style.display = 'none';
|
||||
showResultDetails();
|
||||
} else
|
||||
showResultsSummary();
|
||||
},
|
||||
_computeResults: function (measuredValuesList, displayUnit) {
|
||||
var suitesCount = this.suitesCount;
|
||||
function valueForUnit(measuredValues) {
|
||||
if (displayUnit == 'ms')
|
||||
return measuredValues.geomean;
|
||||
return measuredValues.score;
|
||||
}
|
||||
|
||||
function sigFigFromPercentDelta(percentDelta) {
|
||||
return Math.ceil(-Math.log(percentDelta)/Math.log(10)) + 3;
|
||||
}
|
||||
|
||||
function toSigFigPrecision(number, sigFig) {
|
||||
var nonDecimalDigitCount = number < 1 ? 0 : (Math.floor(Math.log(number)/Math.log(10)) + 1);
|
||||
return number.toPrecision(Math.max(nonDecimalDigitCount, Math.min(6, sigFig)));
|
||||
}
|
||||
|
||||
var values = measuredValuesList.map(valueForUnit);
|
||||
var sum = values.reduce(function (a, b) { return a + b; }, 0);
|
||||
var arithmeticMean = sum / values.length;
|
||||
var meanSigFig = 4;
|
||||
var formattedDelta;
|
||||
var formattedPercentDelta;
|
||||
if (window.Statistics) {
|
||||
var delta = Statistics.confidenceIntervalDelta(0.95, values.length, sum, Statistics.squareSum(values));
|
||||
if (!isNaN(delta)) {
|
||||
var percentDelta = delta * 100 / arithmeticMean;
|
||||
meanSigFig = sigFigFromPercentDelta(percentDelta);
|
||||
formattedDelta = toSigFigPrecision(delta, 2);
|
||||
formattedPercentDelta = toSigFigPrecision(percentDelta, 2) + '%';
|
||||
}
|
||||
}
|
||||
|
||||
var formattedMean = toSigFigPrecision(arithmeticMean, Math.max(meanSigFig, 3));
|
||||
|
||||
return {
|
||||
formattedValues: values.map(function (value) {
|
||||
return toSigFigPrecision(value, 4) + ' ' + displayUnit;
|
||||
}),
|
||||
mean: arithmeticMean,
|
||||
formattedMean: formattedMean,
|
||||
formattedDelta: formattedDelta,
|
||||
formattedMeanAndDelta: formattedMean + (formattedDelta ? ' \xb1 ' + formattedDelta + ' (' + formattedPercentDelta + ')' : ''),
|
||||
};
|
||||
},
|
||||
_addDetailedResultsRow: function (table, iterationNumber, value) {
|
||||
var row = document.createElement('tr');
|
||||
var th = document.createElement('th');
|
||||
th.textContent = 'Iteration ' + (iterationNumber + 1);
|
||||
var td = document.createElement('td');
|
||||
td.textContent = value;
|
||||
row.appendChild(th);
|
||||
row.appendChild(td);
|
||||
table.appendChild(row);
|
||||
},
|
||||
_updateGaugeNeedle: function (rpm) {
|
||||
var needleAngle = Math.max(0, Math.min(rpm, 140)) - 70;
|
||||
var needleRotationValue = 'rotate(' + needleAngle + 'deg)';
|
||||
|
||||
var gaugeNeedleElement = document.querySelector('#summarized-results > .gauge .needle');
|
||||
gaugeNeedleElement.style.setProperty('-webkit-transform', needleRotationValue);
|
||||
gaugeNeedleElement.style.setProperty('-moz-transform', needleRotationValue);
|
||||
gaugeNeedleElement.style.setProperty('-ms-transform', needleRotationValue);
|
||||
gaugeNeedleElement.style.setProperty('transform', needleRotationValue);
|
||||
},
|
||||
_populateDetailedResults: function (formattedValues) {
|
||||
var resultsTables = document.querySelectorAll('.results-table');
|
||||
var i = 0;
|
||||
resultsTables[0].innerHTML = '';
|
||||
for (; i < Math.ceil(formattedValues.length / 2); i++)
|
||||
this._addDetailedResultsRow(resultsTables[0], i, formattedValues[i]);
|
||||
resultsTables[1].innerHTML = '';
|
||||
for (; i < formattedValues.length; i++)
|
||||
this._addDetailedResultsRow(resultsTables[1], i, formattedValues[i]);
|
||||
},
|
||||
prepareUI: function () {
|
||||
window.addEventListener('popstate', function (event) {
|
||||
if (event.state) {
|
||||
var sectionToShow = event.state.section;
|
||||
if (sectionToShow) {
|
||||
var sections = document.querySelectorAll('main > section');
|
||||
for (var i = 0; i < sections.length; i++) {
|
||||
if (sections[i].id === sectionToShow)
|
||||
return showSection(sectionToShow, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
return showSection('home', false);
|
||||
}, false);
|
||||
|
||||
function updateScreenSize() {
|
||||
// FIXME: Detect when the window size changes during the test.
|
||||
var screenIsTooSmall = window.innerWidth < 850 || window.innerHeight < 650;
|
||||
document.getElementById('screen-size').textContent = window.innerWidth + 'px by ' + window.innerHeight + 'px';
|
||||
document.getElementById('screen-size-warning').style.display = screenIsTooSmall ? null : 'none';
|
||||
}
|
||||
|
||||
window.addEventListener('resize', updateScreenSize);
|
||||
updateScreenSize();
|
||||
}
|
||||
}
|
||||
|
||||
function enableOneSuite(suites, suiteToEnable)
|
||||
{
|
||||
suiteToEnable = suiteToEnable.toLowerCase();
|
||||
var found = false;
|
||||
for (var i = 0; i < suites.length; i++) {
|
||||
var currentSuite = suites[i];
|
||||
if (currentSuite.name.toLowerCase() == suiteToEnable) {
|
||||
currentSuite.disabled = false;
|
||||
found = true;
|
||||
} else
|
||||
currentSuite.disabled = true;
|
||||
}
|
||||
return found;
|
||||
}
|
||||
|
||||
function startBenchmark() {
|
||||
if (location.search.length > 1) {
|
||||
var parts = location.search.substring(1).split('&');
|
||||
for (var i = 0; i < parts.length; i++) {
|
||||
var keyValue = parts[i].split('=');
|
||||
var key = keyValue[0];
|
||||
var value = keyValue[1];
|
||||
switch (key) {
|
||||
case 'unit':
|
||||
if (value == 'ms')
|
||||
benchmarkClient.displayUnit = 'ms';
|
||||
else
|
||||
console.error('Invalid unit: ' + value);
|
||||
break;
|
||||
case 'iterationCount':
|
||||
var parsedValue = parseInt(value);
|
||||
if (!isNaN(parsedValue))
|
||||
benchmarkClient.iterationCount = parsedValue;
|
||||
else
|
||||
console.error('Invalid iteration count: ' + value);
|
||||
break;
|
||||
case 'suite':
|
||||
if (!enableOneSuite(Suites, value)) {
|
||||
alert('Suite "' + value + '" does not exist. No tests to run.');
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var enabledSuites = Suites.filter(function (suite) { return !suite.disabled; });
|
||||
var totalSubtestsCount = enabledSuites.reduce(function (testsCount, suite) { return testsCount + suite.tests.length; }, 0);
|
||||
benchmarkClient.stepCount = benchmarkClient.iterationCount * totalSubtestsCount;
|
||||
benchmarkClient.suitesCount = enabledSuites.length;
|
||||
var runner = new BenchmarkRunner(Suites, benchmarkClient);
|
||||
runner.runMultipleIterations(benchmarkClient.iterationCount);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function showSection(sectionIdentifier, pushState) {
|
||||
var currentSectionElement = document.querySelector('section.selected');
|
||||
console.assert(currentSectionElement);
|
||||
|
||||
var newSectionElement = document.getElementById(sectionIdentifier);
|
||||
console.assert(newSectionElement);
|
||||
|
||||
currentSectionElement.classList.remove('selected');
|
||||
newSectionElement.classList.add('selected');
|
||||
|
||||
if (pushState)
|
||||
history.pushState({section: sectionIdentifier}, document.title);
|
||||
}
|
||||
|
||||
function showHome() {
|
||||
showSection('home', true);
|
||||
}
|
||||
|
||||
function startTest() {
|
||||
if (startBenchmark())
|
||||
showSection('running');
|
||||
}
|
||||
|
||||
function showResultsSummary() {
|
||||
showSection('summarized-results', true);
|
||||
}
|
||||
|
||||
function showResultDetails() {
|
||||
showSection('detailed-results', true);
|
||||
}
|
||||
|
||||
function showAbout() {
|
||||
showSection('about', true);
|
||||
}
|
||||
|
||||
window.addEventListener('DOMContentLoaded', function () {
|
||||
if (benchmarkClient.prepareUI)
|
||||
benchmarkClient.prepareUI();
|
||||
});
|
@ -12,15 +12,27 @@ class Random
|
||||
return this.seed = this.seed * 16807 % 2147483647;
|
||||
}
|
||||
|
||||
underOne()
|
||||
{
|
||||
return (this.next % 1048576) / 1048576;
|
||||
}
|
||||
|
||||
chance(chance)
|
||||
{
|
||||
return this.next % 1048576 < chance * 1048576;
|
||||
return this.underOne() < chance;
|
||||
}
|
||||
|
||||
number(under)
|
||||
{
|
||||
return this.next % under;
|
||||
}
|
||||
|
||||
numberSquareWeightedToLow(under)
|
||||
{
|
||||
const random = this.underOne();
|
||||
const random2 = random * random;
|
||||
return Math.floor(random2 * under);
|
||||
}
|
||||
}
|
||||
|
||||
function nextAnimationFrame()
|
||||
@ -35,9 +47,19 @@ class StyleBench
|
||||
return {
|
||||
name: 'Default',
|
||||
elementTypeCount: 10,
|
||||
idChance: 0.05,
|
||||
elementChance: 0.5,
|
||||
classCount: 200,
|
||||
classChance: 0.3,
|
||||
starChance: 0.05,
|
||||
attributeChance: 0.02,
|
||||
attributeCount: 10,
|
||||
attributeValueCount: 20,
|
||||
attributeOperators: ['','='],
|
||||
elementClassChance: 0.5,
|
||||
elementMaximumClasses: 3,
|
||||
elementAttributeChance: 0.2,
|
||||
elementMaximumAttributes: 3,
|
||||
combinators: [' ', '>',],
|
||||
pseudoClasses: [],
|
||||
pseudoClassChance: 0,
|
||||
@ -49,9 +71,11 @@ class StyleBench
|
||||
maximumTreeWidth: 50,
|
||||
repeatingSequenceChance: 0.2,
|
||||
repeatingSequenceMaximumLength: 3,
|
||||
leafClassMutationChance: 0.1,
|
||||
leafMutationChance: 0.1,
|
||||
styleSeed: 1,
|
||||
domSeed: 2,
|
||||
stepCount: 5,
|
||||
mutationsPerStep: 100,
|
||||
};
|
||||
}
|
||||
|
||||
@ -70,21 +94,32 @@ class StyleBench
|
||||
});
|
||||
}
|
||||
|
||||
static pseudoClassConfiguration()
|
||||
static structuralPseudoClassConfiguration()
|
||||
{
|
||||
return Object.assign(this.defaultConfiguration(), {
|
||||
name: 'Positional pseudo classes',
|
||||
name: 'Structural pseudo classes',
|
||||
pseudoClassChance: 0.1,
|
||||
pseudoClasses: [
|
||||
'first-child',
|
||||
'last-child',
|
||||
'first-of-type',
|
||||
'last-of-type',
|
||||
'only-of-type',
|
||||
'empty',
|
||||
],
|
||||
});
|
||||
}
|
||||
|
||||
static nthPseudoClassConfiguration()
|
||||
{
|
||||
return Object.assign(this.defaultConfiguration(), {
|
||||
name: 'Nth pseudo classes',
|
||||
pseudoClassChance: 0.1,
|
||||
pseudoClasses: [
|
||||
'nth-child(2n+1)',
|
||||
'nth-last-child(3n)',
|
||||
'nth-of-type(3n)',
|
||||
'nth-last-of-type(4n)',
|
||||
'first-child',
|
||||
'last-child',
|
||||
'first-of-type',
|
||||
'last-of-type',
|
||||
'only-of-type',
|
||||
],
|
||||
});
|
||||
}
|
||||
@ -102,7 +137,8 @@ class StyleBench
|
||||
return [
|
||||
this.descendantCombinatorConfiguration(),
|
||||
this.siblingCombinatorConfiguration(),
|
||||
this.pseudoClassConfiguration(),
|
||||
this.structuralPseudoClassConfiguration(),
|
||||
this.nthPseudoClassConfiguration(),
|
||||
this.beforeAndAfterConfiguration(),
|
||||
];
|
||||
}
|
||||
@ -110,6 +146,7 @@ class StyleBench
|
||||
constructor(configuration)
|
||||
{
|
||||
this.configuration = configuration;
|
||||
this.idCount = 0;
|
||||
|
||||
this.baseStyle = document.createElement("style");
|
||||
this.baseStyle.textContent = `
|
||||
@ -119,10 +156,8 @@ class StyleBench
|
||||
}
|
||||
#testroot * {
|
||||
display: inline-block;
|
||||
}
|
||||
#testroot :empty {
|
||||
width:10px;
|
||||
height:10px;
|
||||
min-width:10px;
|
||||
}
|
||||
`;
|
||||
document.head.appendChild(this.baseStyle);
|
||||
@ -137,19 +172,36 @@ class StyleBench
|
||||
randomElementName()
|
||||
{
|
||||
const elementTypeCount = this.configuration.elementTypeCount;
|
||||
return `elem${ this.random.number(elementTypeCount) }`;
|
||||
return `elem${ this.random.numberSquareWeightedToLow(elementTypeCount) }`;
|
||||
}
|
||||
|
||||
randomClassName()
|
||||
{
|
||||
const classCount = this.configuration.classCount;
|
||||
return `class${ this.random.number(classCount) }`;
|
||||
return `class${ this.random.numberSquareWeightedToLow(classCount) }`;
|
||||
}
|
||||
|
||||
randomClassNameFromRange(range)
|
||||
{
|
||||
const maximum = Math.round(range * this.configuration.classCount);
|
||||
return `class${ this.random.number(maximum) }`;
|
||||
return `class${ this.random.numberSquareWeightedToLow(maximum) }`;
|
||||
}
|
||||
|
||||
randomAttributeName()
|
||||
{
|
||||
const attributeCount = this.configuration.attributeCount;
|
||||
return `attr${ this.random.numberSquareWeightedToLow(attributeCount) }`;
|
||||
}
|
||||
|
||||
randomAttributeValue()
|
||||
{
|
||||
const attributeValueCount = this.configuration.attributeValueCount;
|
||||
const valueNum = this.random.numberSquareWeightedToLow(attributeValueCount);
|
||||
if (valueNum == 0)
|
||||
return "";
|
||||
if (valueNum == 1)
|
||||
return "val";
|
||||
return `val${valueNum}`;
|
||||
}
|
||||
|
||||
randomCombinator()
|
||||
@ -158,28 +210,63 @@ class StyleBench
|
||||
return combinators[this.random.number(combinators.length)]
|
||||
}
|
||||
|
||||
randomPseudoClass()
|
||||
randomPseudoClass(isLast)
|
||||
{
|
||||
const pseudoClasses = this.configuration.pseudoClasses;
|
||||
return pseudoClasses[this.random.number(pseudoClasses.length)]
|
||||
const pseudoClass = pseudoClasses[this.random.number(pseudoClasses.length)]
|
||||
if (!isLast && pseudoClass == 'empty')
|
||||
return this.randomPseudoClass(isLast);
|
||||
return pseudoClass;
|
||||
}
|
||||
|
||||
makeSimpleSelector(index, length)
|
||||
randomId()
|
||||
{
|
||||
const idCount = this.configuration.idChance * this.configuration.elementCount ;
|
||||
return `id${ this.random.number(idCount) }`;
|
||||
}
|
||||
|
||||
randomAttributeSelector()
|
||||
{
|
||||
const name = this.randomAttributeName();
|
||||
const operators = this.configuration.attributeOperators;
|
||||
const operator = operators[this.random.numberSquareWeightedToLow(operators.length)];
|
||||
if (operator == '')
|
||||
return `[${name}]`;
|
||||
const value = this.randomAttributeValue();
|
||||
return `[${name}${operator}"${value}"]`;
|
||||
}
|
||||
|
||||
makeCompoundSelector(index, length)
|
||||
{
|
||||
const isFirst = index == 0;
|
||||
const isLast = index == length - 1;
|
||||
const usePseudoClass = this.random.chance(this.configuration.pseudoClassChance) && this.configuration.pseudoClasses.length;
|
||||
const useElement = usePseudoClass || this.random.chance(this.configuration.elementChance); // :nth-of-type etc only make sense with element
|
||||
const useClass = !useElement || this.random.chance(this.configuration.classChance);
|
||||
const useId = isFirst && this.random.chance(this.configuration.idChance);
|
||||
const useElement = !useId && (usePseudoClass || this.random.chance(this.configuration.elementChance)); // :nth-of-type etc only make sense with element
|
||||
const useAttribute = !useId && this.random.chance(this.configuration.attributeChance);
|
||||
const useIdElementOrAttribute = useId || useElement || useAttribute;
|
||||
const useStar = !useIdElementOrAttribute && !isFirst && this.random.chance(this.configuration.starChance);
|
||||
const useClass = !useId && !useStar && (!useIdElementOrAttribute || this.random.chance(this.configuration.classChance));
|
||||
const useBeforeOrAfter = isLast && this.random.chance(this.configuration.beforeAfterChance);
|
||||
let result = "";
|
||||
if (useElement)
|
||||
result += this.randomElementName();
|
||||
if (useStar)
|
||||
result = "*";
|
||||
if (useId)
|
||||
result += "#" + this.randomId();
|
||||
if (useClass) {
|
||||
// Use a smaller pool of class names on the left side of the selectors to create containers.
|
||||
result += "." + this.randomClassNameFromRange((index + 1) / length);
|
||||
const classCount = this.random.numberSquareWeightedToLow(2) + 1;
|
||||
for (let i = 0; i < classCount; ++i) {
|
||||
// Use a smaller pool of class names on the left side of the selectors to create containers.
|
||||
result += "." + this.randomClassNameFromRange((index + 1) / length);
|
||||
}
|
||||
}
|
||||
if (useAttribute)
|
||||
result += this.randomAttributeSelector();
|
||||
|
||||
if (usePseudoClass)
|
||||
result += ":" + this.randomPseudoClass();
|
||||
result += ":" + this.randomPseudoClass(isLast);
|
||||
if (useBeforeOrAfter) {
|
||||
if (this.random.chance(0.5))
|
||||
result += "::before";
|
||||
@ -192,12 +279,12 @@ class StyleBench
|
||||
makeSelector()
|
||||
{
|
||||
const length = this.random.number(this.configuration.maximumSelectorLength) + 1;
|
||||
let result = this.makeSimpleSelector(0, length);
|
||||
for (let i = 0; i < length; ++i) {
|
||||
let result = this.makeCompoundSelector(0, length);
|
||||
for (let i = 1; i < length; ++i) {
|
||||
const combinator = this.randomCombinator();
|
||||
if (combinator != ' ')
|
||||
result += " " + combinator;
|
||||
result += " " + this.makeSimpleSelector(i, length);
|
||||
result += " " + this.makeCompoundSelector(i, length);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@ -212,7 +299,7 @@ class StyleBench
|
||||
let declaration = `background-color: rgb(${this.randomColorComponent}, ${this.randomColorComponent}, ${this.randomColorComponent});`;
|
||||
|
||||
if (selector.endsWith('::before') || selector.endsWith('::after'))
|
||||
declaration += " content: '\xa0';";
|
||||
declaration += " content: ''; min-width:5px; display:inline-block;";
|
||||
|
||||
return declaration;
|
||||
}
|
||||
@ -242,12 +329,23 @@ class StyleBench
|
||||
makeElement()
|
||||
{
|
||||
const element = document.createElement(this.randomElementName());
|
||||
const hasClasses = this.random.chance(0.5);
|
||||
const hasClasses = this.random.chance(this.configuration.elementClassChance);
|
||||
const hasAttributes = this.random.chance(this.configuration.elementAttributeChance);
|
||||
if (hasClasses) {
|
||||
const count = this.random.number(3) + 1;
|
||||
const count = this.random.numberSquareWeightedToLow(this.configuration.elementMaximumClasses) + 1;
|
||||
for (let i = 0; i < count; ++i)
|
||||
element.classList.add(this.randomClassName());
|
||||
}
|
||||
if (hasAttributes) {
|
||||
const count = this.random.number(this.configuration.elementMaximumAttributes) + 1;
|
||||
for (let i = 0; i < count; ++i)
|
||||
element.setAttribute(this.randomAttributeName(), this.randomAttributeValue());
|
||||
}
|
||||
const hasId = this.random.chance(this.configuration.idChance);
|
||||
if (hasId) {
|
||||
element.id = `id${ this.idCount }`;
|
||||
this.idCount++;
|
||||
}
|
||||
return element;
|
||||
}
|
||||
|
||||
@ -320,7 +418,7 @@ class StyleBench
|
||||
for (let i = 0; i < count;) {
|
||||
const element = this.randomTreeElement();
|
||||
// There are more leaves than branches. Avoid skewing towards leaf mutations.
|
||||
if (!element.firstChild && !this.random.chance(this.configuration.leafClassMutationChance))
|
||||
if (!element.firstChild && !this.random.chance(this.configuration.leafMutationChance))
|
||||
continue;
|
||||
++i;
|
||||
const classList = element.classList;
|
||||
@ -333,7 +431,7 @@ class StyleBench
|
||||
for (let i = 0; i < count;) {
|
||||
const element = this.randomTreeElement();
|
||||
const classList = element.classList;
|
||||
if (!element.firstChild && !this.random.chance(this.configuration.leafClassMutationChance))
|
||||
if (!element.firstChild && !this.random.chance(this.configuration.leafMutationChance))
|
||||
continue;
|
||||
if (!classList.length)
|
||||
continue;
|
||||
@ -371,6 +469,33 @@ class StyleBench
|
||||
this.updateCachedTestElements();
|
||||
}
|
||||
|
||||
mutateAttributes(count)
|
||||
{
|
||||
for (let i = 0; i < count;) {
|
||||
const element = this.randomTreeElement();
|
||||
// There are more leaves than branches. Avoid skewing towards leaf mutations.
|
||||
if (!element.firstChild && !this.random.chance(this.configuration.leafMutationChance))
|
||||
continue;
|
||||
const attributeNames = element.getAttributeNames();
|
||||
let mutatedAttributes = false;
|
||||
for (const name of attributeNames) {
|
||||
if (name == "class" || name == "id")
|
||||
continue;
|
||||
if (this.random.chance(0.5))
|
||||
element.removeAttribute(name);
|
||||
else
|
||||
element.setAttribute(name, this.randomAttributeValue());
|
||||
mutatedAttributes = true;
|
||||
}
|
||||
if (!mutatedAttributes) {
|
||||
const attributeCount = this.random.number(this.configuration.elementMaximumAttributes) + 1;
|
||||
for (let j = 0; j < attributeCount; ++j)
|
||||
element.setAttribute(this.randomAttributeName(), this.randomAttributeValue());
|
||||
}
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
async runForever()
|
||||
{
|
||||
while (true) {
|
||||
@ -378,6 +503,7 @@ class StyleBench
|
||||
this.removeClasses(10);
|
||||
this.addLeafElements(10);
|
||||
this.removeLeafElements(10);
|
||||
this.mutateAttributes(10);
|
||||
|
||||
await nextAnimationFrame();
|
||||
}
|
||||
|
@ -1,18 +1,21 @@
|
||||
function makeSteps(count)
|
||||
function makeSteps(configuration)
|
||||
{
|
||||
let steps = [];
|
||||
for (let i = 0; i < count; ++i) {
|
||||
steps.push(new BenchmarkTestStep('Adding classes', (bench, contentWindow, contentDocument) => {
|
||||
bench.addClasses(100);
|
||||
const steps = [];
|
||||
for (i = 0; i < configuration.stepCount; ++i) {
|
||||
steps.push(new BenchmarkTestStep(`Adding classes - ${i}`, (bench, contentWindow, contentDocument) => {
|
||||
bench.addClasses(configuration.mutationsPerStep);
|
||||
}));
|
||||
steps.push(new BenchmarkTestStep('Removing classes', (bench, contentWindow, contentDocument) => {
|
||||
bench.removeClasses(100);
|
||||
steps.push(new BenchmarkTestStep(`Removing classes - ${i}`, (bench, contentWindow, contentDocument) => {
|
||||
bench.removeClasses(configuration.mutationsPerStep);
|
||||
}));
|
||||
steps.push(new BenchmarkTestStep('Adding leaf elements', (bench, contentWindow, contentDocument) => {
|
||||
bench.addLeafElements(100);
|
||||
steps.push(new BenchmarkTestStep(`Mutating attributes - ${i}`, (bench, contentWindow, contentDocument) => {
|
||||
bench.mutateAttributes(configuration.mutationsPerStep);
|
||||
}));
|
||||
steps.push(new BenchmarkTestStep('Removing leaf elements', (bench, contentWindow, contentDocument) => {
|
||||
bench.removeLeafElements(100);
|
||||
steps.push(new BenchmarkTestStep(`Adding leaf elements - ${i}`, (bench, contentWindow, contentDocument) => {
|
||||
bench.addLeafElements(configuration.mutationsPerStep);
|
||||
}));
|
||||
steps.push(new BenchmarkTestStep(`Removing leaf elements - ${i}`, (bench, contentWindow, contentDocument) => {
|
||||
bench.removeLeafElements(configuration.mutationsPerStep);
|
||||
}));
|
||||
}
|
||||
return steps;
|
||||
@ -28,7 +31,7 @@ function makeSuite(configuration)
|
||||
return contentWindow.createBenchmark(configuration);
|
||||
});
|
||||
},
|
||||
tests: makeSteps(5),
|
||||
tests: makeSteps(configuration),
|
||||
};
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user