From 36d22d82aa202bb199967e9512281e9a53db42c9 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 21:33:14 +0200 Subject: Adding upstream version 115.7.0esr. Signed-off-by: Daniel Baumann --- .../MotionMark/resources/runner/animometer.css | 520 +++++++++++++++++ .../MotionMark/resources/runner/animometer.js | 626 +++++++++++++++++++++ .../resources/runner/benchmark-runner.js | 179 ++++++ .../MotionMark/resources/runner/crystal.svg | 92 +++ .../MotionMark/resources/runner/lines.svg | 26 + .../MotionMark/resources/runner/logo.svg | 26 + .../MotionMark/resources/runner/tests.js | 81 +++ 7 files changed, 1550 insertions(+) create mode 100644 third_party/webkit/PerformanceTests/MotionMark/resources/runner/animometer.css create mode 100644 third_party/webkit/PerformanceTests/MotionMark/resources/runner/animometer.js create mode 100644 third_party/webkit/PerformanceTests/MotionMark/resources/runner/benchmark-runner.js create mode 100644 third_party/webkit/PerformanceTests/MotionMark/resources/runner/crystal.svg create mode 100644 third_party/webkit/PerformanceTests/MotionMark/resources/runner/lines.svg create mode 100644 third_party/webkit/PerformanceTests/MotionMark/resources/runner/logo.svg create mode 100644 third_party/webkit/PerformanceTests/MotionMark/resources/runner/tests.js (limited to 'third_party/webkit/PerformanceTests/MotionMark/resources/runner') diff --git a/third_party/webkit/PerformanceTests/MotionMark/resources/runner/animometer.css b/third_party/webkit/PerformanceTests/MotionMark/resources/runner/animometer.css new file mode 100644 index 0000000000..86da6bea1c --- /dev/null +++ b/third_party/webkit/PerformanceTests/MotionMark/resources/runner/animometer.css @@ -0,0 +1,520 @@ +/* Outer harness */ + +html, +body { + min-height: 100%; +} + +body { + background-color: hsl(0, 0%, 95%); + + font-family: "Helvetica Neue", Helvetica, Verdana, sans-serif; + font-size: 15px; + + cursor: default; + + -webkit-user-select: none; +} + +body.showing-intro, +body.showing-results { + background-color: hsl(35, 100%, 100%); + background-image: url(crystal.svg), url(lines.svg); + background-size: auto 225%, auto 100%; + background-repeat: no-repeat; + + animation: background-fade 1s ease-in 1s, background-color 60s linear infinite 2s; + animation-play-state: paused; + + will-change: background-color; +} + +body.showing-test-container { + overflow: hidden; +} + +body.images-loaded { + animation-play-state: running; +} + +@media screen and (min-width: 667px) { + body { + font-size: 24px; + } + + body.showing-intro, + body.showing-results { + background-size: 200% 100%, 150% auto; + } +} + +@media screen and (min-width: 1025px) { + body.showing-intro, + body.showing-results { + background-size: 150% 100%, 150% auto; + } +} + +::selection { + background-color: black; + color: white; +} + +.hidden { + display: none; +} + +section { + display: none; +} + +section.selected { + display: block; +} + +svg.logo { + width: 350px; + height: 88px; + + max-width: 100%; + + padding-bottom: 1em; + + color: hsl(35, 100%, 50%); + + animation: foreground-color 60s linear infinite 2s; + animation-play-state: paused; + + will-change: color; +} + +body.images-loaded svg.logo { + animation-play-state: running; +} + +@media screen and (min-width: 667px) { + svg.logo { + width: 525px; + height: 130px; + } +} + +section .body { + margin: 0 1em; + max-width: 350px; +} + +section .body p { + margin: 1em 0; + line-height: 1.5em; + + -webkit-user-select: text; + cursor: text; +} + +@media screen and (min-width: 667px) { + section .body { + margin-left: 2.5em; + max-width: 500px; + transform: skewX(-10deg); + } + + section button { + transform: none; + } +} + +button { + background-color: hsl(35, 100%, 50%); + color: white; + + padding: 0.25em; + margin: 1.5em -0.25em 0 0; + + min-width: 50%; + + border: none; + + font-family: inherit; + font-size: inherit; + + transform: skewX(-10deg); + + transition: 100ms filter ease-in-out; + + animation: background-color 60s linear infinite 2s; + animation-play-state: paused; + + will-change: background-color; +} + +body.images-loaded button { + animation-play-state: running; +} + +button:hover { + filter: brightness(115%); +} + +button:active { + filter: brightness(130%); +} + +button:disabled { + opacity: 0.5; + filter: none !important; +} + +@media print { + button { + display: none; + } +} + +.portrait-orientation-check { + display: none; +} + +@media screen and (max-device-width: 1025px) and (orientation: portrait) { + .portrait-orientation-check { + display: block; + } +} + +@media screen and (max-device-width: 1025px) and (orientation: portrait) { + .landscape-orientation-check { + /* This keeps the button color animation in sync with page, while display: none does not. */ + visibility: hidden; + } +} + +@keyframes background-fade { + 100% { + background-color: hsl(35, 100%, 50%); + } +} + +@keyframes background-color { + 0%, 10% { + background-color: hsl(35, 100%, 50%); + } + + 12%, 20% { + background-color: hsl(75, 100%, 30%); + } + + 22%, 30% { + background-color: hsl(115, 100%, 30%); + } + + 32%, 40% { + background-color: hsl(155, 100%, 30%); + } + + 42%, 50% { + background-color: hsl(195, 100%, 30%); + } + + 52%, 60% { + background-color: hsl(235, 100%, 30%); + } + + 62%, 70% { + background-color: hsl(275, 100%, 30%); + } + + 72%, 80% { + background-color: hsl(315, 100%, 30%); + } + + 82%, 90% { + background-color: hsl(355, 100%, 30%); + } + + 92%, 100% { + background-color: hsl(395, 100%, 50%); + } +} + +@keyframes foreground-color { + 0%, 10% { + color: hsl(35, 100%, 50%); + } + + 12%, 20% { + color: hsl(75, 100%, 30%); + } + + 22%, 30% { + color: hsl(115, 100%, 30%); + } + + 32%, 40% { + color: hsl(155, 100%, 30%); + } + + 42%, 50% { + color: hsl(195, 100%, 30%); + } + + 52%, 60% { + color: hsl(235, 100%, 30%); + } + + 62%, 70% { + color: hsl(275, 100%, 30%); + } + + 72%, 80% { + color: hsl(315, 100%, 30%); + } + + 82%, 90% { + color: hsl(355, 100%, 30%); + } + + 92%, 100% { + color: hsl(395, 100%, 50%); + } +} + +/* Intro section, About page */ + +#intro, #about { + padding: 2em; +} + +#intro { + opacity: 0; + transition: opacity 500ms ease-in; +} + +body.images-loaded #intro { + opacity: 1; +} + +#about .body { + transform: none; + margin: 0; + max-width: initial; +} + +#about li { + line-height: 1.5em; +} + +#about button { + padding: .75em 2em; + margin: 1.5em auto 0; + min-width: initial; + transform: skewX(-10deg); +} + +@media screen and (min-width: 667px) { + #about .body { + font-size: .7em; + margin: 1em; + } + + #about ol, #about ul { + padding-left: 3em; + } +} + + +#intro a, #about a, +#intro a:visited, #about a:visited { + color: black; +} + +/* Running test section */ + +.frame-container { + position: absolute; + + top: 50%; + left: 50%; +} + +.frame-container > iframe { + width: 100%; + height: 100%; + + border: 0; + margin: 0; +} + +body.small .frame-container { + width: 568px; + height: 320px; + margin-left: -284px; + margin-top: -160px; +} + +body.medium .frame-container { + width: 900px; + height: 600px; + margin-left: -450px; + margin-top: -300px; +} + +body.large .frame-container { + width: 1600px; + height: 800px; + margin-left: -800px; + margin-top: -400px; +} + +/* Results section */ + +#results { + padding: 2em; +} + +#results .body { + -webkit-user-select: text; +} + +#results .score-container { + padding-bottom: 2em; +} + +#results .table-container { + position: relative; +} + +#results .table-container > div { + margin-left: 40%; +} + +#results .score { + font-size: 5em; + font-weight: bold; + font-style: italic; + line-height: 1; + margin: 0; +} + +#results .confidence { + font-size: 2em; + font-style: italic; + line-height: 1; + margin: 0; + text-indent: 1.75em; + color: hsl(0, 0%, 40%); + padding-bottom: .3em; +} + +#results table { + border-spacing: 0; + margin: 0; + padding: 0; + min-width: 25%; +} + +#results table td, +#results table th { + padding: 0.25em; +} + +#results table td.suites-separator { + padding: 0; +} + +#results table tr:nth-child(even) { + background-color: hsla(0, 0%, 0%, 0.05); +} + +#results #results-header { + top: 0; + left: 0; + width: 40%; + position: absolute; +} + +#results #results-score { + float: left; +} + +#results #results-data span { + font-size: .75em; + color: hsl(0, 0%, 40%); +} + +#results #results-header td, +#results #results-header th { + text-align: right; + padding-right: 1em !important; + padding-left: 0.5em !important; +} + +#results #results-score td, +#results #results-score th { + text-align: left; + padding-right: 0.5em !important; +} + +#results #results-score td { + cursor: text; +} + +@media screen and (min-width: 667px) { + #results .score, + #results .confidence { + font-style: normal; + } +} + +.detail span { + display: none; +} + +body.small .detail .small, +body.medium .detail .medium, +body.large .detail .large { + display: initial; +} + +#overlay { + position: fixed; + + top: 0; + left: 0; + bottom: 0; + right: 0; + + background: hsla(0, 0%, 100%, 0.9); +} + +@supports (-webkit-backdrop-filter: blur(10px)) { + #overlay { + background: hsla(0, 0%, 100%, 0.7); + -webkit-backdrop-filter: blur(20px); + } +} + +#overlay > div { + position: absolute; + + width: 500px; + height: 500px; + + margin-top: -250px; + margin-left: -250px; + + top: 50%; + left: 50%; +} + +#overlay > div div { + overflow: scroll; + + font-size: 12px; + -webkit-user-select: text; + cursor: text; + + max-height: 250px; + + border: 1px solid hsla(0, 0%, 0%, 0.1); + padding: 1em; +} diff --git a/third_party/webkit/PerformanceTests/MotionMark/resources/runner/animometer.js b/third_party/webkit/PerformanceTests/MotionMark/resources/runner/animometer.js new file mode 100644 index 0000000000..65e8c5450d --- /dev/null +++ b/third_party/webkit/PerformanceTests/MotionMark/resources/runner/animometer.js @@ -0,0 +1,626 @@ +ResultsDashboard = Utilities.createClass( + function(options, testData) + { + this._iterationsSamplers = []; + this._options = options; + this._results = null; + if (testData) { + this._iterationsSamplers = testData; + this._processData(); + } + }, { + + push: function(suitesSamplers) + { + this._iterationsSamplers.push(suitesSamplers); + }, + + _processData: function() + { + this._results = {}; + this._results[Strings.json.results.iterations] = []; + + var iterationsScores = []; + this._iterationsSamplers.forEach(function(iteration, index) { + var testsScores = []; + var testsLowerBoundScores = []; + var testsUpperBoundScores = []; + + var result = {}; + this._results[Strings.json.results.iterations][index] = result; + + var suitesResult = {}; + result[Strings.json.results.tests] = suitesResult; + + for (var suiteName in iteration) { + var suiteData = iteration[suiteName]; + + var suiteResult = {}; + suitesResult[suiteName] = suiteResult; + + for (var testName in suiteData) { + if (!suiteData[testName][Strings.json.result]) + this.calculateScore(suiteData[testName]); + + suiteResult[testName] = suiteData[testName][Strings.json.result]; + delete suiteData[testName][Strings.json.result]; + + testsScores.push(suiteResult[testName][Strings.json.score]); + testsLowerBoundScores.push(suiteResult[testName][Strings.json.scoreLowerBound]); + testsUpperBoundScores.push(suiteResult[testName][Strings.json.scoreUpperBound]); + } + } + + result[Strings.json.score] = Statistics.geometricMean(testsScores); + result[Strings.json.scoreLowerBound] = Statistics.geometricMean(testsLowerBoundScores); + result[Strings.json.scoreUpperBound] = Statistics.geometricMean(testsUpperBoundScores); + iterationsScores.push(result[Strings.json.score]); + }, this); + + this._results[Strings.json.score] = Statistics.sampleMean(iterationsScores.length, iterationsScores.reduce(function(a, b) { return a + b; })); + this._results[Strings.json.scoreLowerBound] = this._results[Strings.json.results.iterations][0][Strings.json.scoreLowerBound]; + this._results[Strings.json.scoreUpperBound] = this._results[Strings.json.results.iterations][0][Strings.json.scoreUpperBound]; + }, + + calculateScore: function(data) + { + var result = {}; + data[Strings.json.result] = result; + var samples = data[Strings.json.samples]; + + var desiredFrameLength = 1000/60; + if (this._options["controller"] == "ramp30") + desiredFrameLength = 1000/30; + + function findRegression(series, profile) { + var minIndex = Math.round(.025 * series.length); + var maxIndex = Math.round(.975 * (series.length - 1)); + var minComplexity = series.getFieldInDatum(minIndex, Strings.json.complexity); + var maxComplexity = series.getFieldInDatum(maxIndex, Strings.json.complexity); + + if (Math.abs(maxComplexity - minComplexity) < 20 && maxIndex - minIndex < 20) { + minIndex = 0; + maxIndex = series.length - 1; + minComplexity = series.getFieldInDatum(minIndex, Strings.json.complexity); + maxComplexity = series.getFieldInDatum(maxIndex, Strings.json.complexity); + } + + var complexityIndex = series.fieldMap[Strings.json.complexity]; + var frameLengthIndex = series.fieldMap[Strings.json.frameLength]; + var regressionOptions = { desiredFrameLength: desiredFrameLength }; + if (profile) + regressionOptions.preferredProfile = profile; + return { + minComplexity: minComplexity, + maxComplexity: maxComplexity, + samples: series.slice(minIndex, maxIndex + 1), + regression: new Regression( + series.data, + function (data, i) { return data[i][complexityIndex]; }, + function (data, i) { return data[i][frameLengthIndex]; }, + minIndex, maxIndex, regressionOptions) + }; + } + + var complexitySamples; + // Convert these samples into SampleData objects if needed + [Strings.json.complexity, Strings.json.complexityAverage, Strings.json.controller].forEach(function(seriesName) { + var series = samples[seriesName]; + if (series && !(series instanceof SampleData)) + samples[seriesName] = new SampleData(series.fieldMap, series.data); + }); + + var isRampController = ["ramp", "ramp30"].indexOf(this._options["controller"]) != -1; + var predominantProfile = ""; + if (isRampController) { + var profiles = {}; + data[Strings.json.controller].forEach(function(regression) { + if (regression[Strings.json.regressions.profile]) { + var profile = regression[Strings.json.regressions.profile]; + profiles[profile] = (profiles[profile] || 0) + 1; + } + }); + + var maxProfileCount = 0; + for (var profile in profiles) { + if (profiles[profile] > maxProfileCount) { + predominantProfile = profile; + maxProfileCount = profiles[profile]; + } + } + } + + [Strings.json.complexity, Strings.json.complexityAverage].forEach(function(seriesName) { + if (!(seriesName in samples)) + return; + + var regression = {}; + result[seriesName] = regression; + var regressionResult = findRegression(samples[seriesName], predominantProfile); + if (seriesName == Strings.json.complexity) + complexitySamples = regressionResult.samples; + var calculation = regressionResult.regression; + regression[Strings.json.regressions.segment1] = [ + [regressionResult.minComplexity, calculation.s1 + calculation.t1 * regressionResult.minComplexity], + [calculation.complexity, calculation.s1 + calculation.t1 * calculation.complexity] + ]; + regression[Strings.json.regressions.segment2] = [ + [calculation.complexity, calculation.s2 + calculation.t2 * calculation.complexity], + [regressionResult.maxComplexity, calculation.s2 + calculation.t2 * regressionResult.maxComplexity] + ]; + regression[Strings.json.complexity] = calculation.complexity; + regression[Strings.json.measurements.stdev] = Math.sqrt(calculation.error / samples[seriesName].length); + }); + + if (isRampController) { + var timeComplexity = new Experiment; + data[Strings.json.controller].forEach(function(regression) { + timeComplexity.sample(regression[Strings.json.complexity]); + }); + + var experimentResult = {}; + result[Strings.json.controller] = experimentResult; + experimentResult[Strings.json.score] = timeComplexity.mean(); + experimentResult[Strings.json.measurements.average] = timeComplexity.mean(); + experimentResult[Strings.json.measurements.stdev] = timeComplexity.standardDeviation(); + experimentResult[Strings.json.measurements.percent] = timeComplexity.percentage(); + + const bootstrapIterations = 2500; + var bootstrapResult = Regression.bootstrap(complexitySamples.data, bootstrapIterations, function(resampleData) { + var complexityIndex = complexitySamples.fieldMap[Strings.json.complexity]; + resampleData.sort(function(a, b) { + return a[complexityIndex] - b[complexityIndex]; + }); + + var resample = new SampleData(complexitySamples.fieldMap, resampleData); + var regressionResult = findRegression(resample, predominantProfile); + return regressionResult.regression.complexity; + }, .8); + + result[Strings.json.complexity][Strings.json.bootstrap] = bootstrapResult; + result[Strings.json.score] = bootstrapResult.median; + result[Strings.json.scoreLowerBound] = bootstrapResult.confidenceLow; + result[Strings.json.scoreUpperBound] = bootstrapResult.confidenceHigh; + } else { + var marks = data[Strings.json.marks]; + var samplingStartIndex = 0, samplingEndIndex = -1; + if (Strings.json.samplingStartTimeOffset in marks) + samplingStartIndex = marks[Strings.json.samplingStartTimeOffset].index; + if (Strings.json.samplingEndTimeOffset in marks) + samplingEndIndex = marks[Strings.json.samplingEndTimeOffset].index; + + var averageComplexity = new Experiment; + var averageFrameLength = new Experiment; + var controllerSamples = samples[Strings.json.controller]; + controllerSamples.forEach(function (sample, i) { + if (i >= samplingStartIndex && (samplingEndIndex == -1 || i < samplingEndIndex)) { + averageComplexity.sample(controllerSamples.getFieldInDatum(sample, Strings.json.complexity)); + var smoothedFrameLength = controllerSamples.getFieldInDatum(sample, Strings.json.smoothedFrameLength); + if (smoothedFrameLength && smoothedFrameLength != -1) + averageFrameLength.sample(smoothedFrameLength); + } + }); + + var experimentResult = {}; + result[Strings.json.controller] = experimentResult; + experimentResult[Strings.json.measurements.average] = averageComplexity.mean(); + experimentResult[Strings.json.measurements.concern] = averageComplexity.concern(Experiment.defaults.CONCERN); + experimentResult[Strings.json.measurements.stdev] = averageComplexity.standardDeviation(); + experimentResult[Strings.json.measurements.percent] = averageComplexity.percentage(); + + experimentResult = {}; + result[Strings.json.frameLength] = experimentResult; + experimentResult[Strings.json.measurements.average] = 1000 / averageFrameLength.mean(); + experimentResult[Strings.json.measurements.concern] = averageFrameLength.concern(Experiment.defaults.CONCERN); + experimentResult[Strings.json.measurements.stdev] = averageFrameLength.standardDeviation(); + experimentResult[Strings.json.measurements.percent] = averageFrameLength.percentage(); + + result[Strings.json.score] = averageComplexity.score(Experiment.defaults.CONCERN); + result[Strings.json.scoreLowerBound] = result[Strings.json.score] - averageFrameLength.standardDeviation(); + result[Strings.json.scoreUpperBound] = result[Strings.json.score] + averageFrameLength.standardDeviation(); + } + }, + + get data() + { + return this._iterationsSamplers; + }, + + get results() + { + if (this._results) + return this._results[Strings.json.results.iterations]; + this._processData(); + return this._results[Strings.json.results.iterations]; + }, + + get options() + { + return this._options; + }, + + _getResultsProperty: function(property) + { + if (this._results) + return this._results[property]; + this._processData(); + return this._results[property]; + }, + + get score() + { + return this._getResultsProperty(Strings.json.score); + }, + + get scoreLowerBound() + { + return this._getResultsProperty(Strings.json.scoreLowerBound); + }, + + get scoreUpperBound() + { + return this._getResultsProperty(Strings.json.scoreUpperBound); + } +}); + +ResultsTable = Utilities.createClass( + function(element, headers) + { + this.element = element; + this._headers = headers; + + this._flattenedHeaders = []; + this._headers.forEach(function(header) { + if (header.disabled) + return; + + if (header.children) + this._flattenedHeaders = this._flattenedHeaders.concat(header.children); + else + this._flattenedHeaders.push(header); + }, this); + + this._flattenedHeaders = this._flattenedHeaders.filter(function (header) { + return !header.disabled; + }); + + this.clear(); + }, { + + clear: function() + { + this.element.textContent = ""; + }, + + _addHeader: function() + { + var thead = Utilities.createElement("thead", {}, this.element); + var row = Utilities.createElement("tr", {}, thead); + + this._headers.forEach(function (header) { + if (header.disabled) + return; + + var th = Utilities.createElement("th", {}, row); + if (header.title != Strings.text.graph) + th.innerHTML = header.title; + if (header.children) + th.colSpan = header.children.length; + }); + }, + + _addBody: function() + { + this.tbody = Utilities.createElement("tbody", {}, this.element); + }, + + _addEmptyRow: function() + { + var row = Utilities.createElement("tr", {}, this.tbody); + this._flattenedHeaders.forEach(function (header) { + return Utilities.createElement("td", { class: "suites-separator" }, row); + }); + }, + + _addTest: function(testName, testResult, options) + { + var row = Utilities.createElement("tr", {}, this.tbody); + + this._flattenedHeaders.forEach(function (header) { + var td = Utilities.createElement("td", {}, row); + if (header.text == Strings.text.testName) { + td.textContent = testName; + } else if (typeof header.text == "string") { + var data = testResult[header.text]; + if (typeof data == "number") + data = data.toFixed(2); + td.innerHTML = data; + } else + td.innerHTML = header.text(testResult); + }, this); + }, + + _addIteration: function(iterationResult, iterationData, options) + { + var testsResults = iterationResult[Strings.json.results.tests]; + for (var suiteName in testsResults) { + this._addEmptyRow(); + var suiteResult = testsResults[suiteName]; + var suiteData = iterationData[suiteName]; + for (var testName in suiteResult) + this._addTest(testName, suiteResult[testName], options, suiteData[testName]); + } + }, + + showIterations: function(dashboard) + { + this.clear(); + this._addHeader(); + this._addBody(); + + var iterationsResults = dashboard.results; + iterationsResults.forEach(function(iterationResult, index) { + this._addIteration(iterationResult, dashboard.data[index], dashboard.options); + }, this); + } +}); + +window.benchmarkRunnerClient = { + iterationCount: 1, + options: null, + results: null, + + initialize: function(suites, options) + { + this.options = options; + }, + + willStartFirstIteration: function() + { + this.results = new ResultsDashboard(this.options); + }, + + didRunSuites: function(suitesSamplers) + { + this.results.push(suitesSamplers); + }, + + didRunTest: function(testData) + { + this.results.calculateScore(testData); + }, + + didFinishLastIteration: function() + { + benchmarkController.showResults(); + } +}; + +window.sectionsManager = +{ + showSection: function(sectionIdentifier, pushState) + { + var sections = document.querySelectorAll("main > section"); + for (var i = 0; i < sections.length; ++i) { + document.body.classList.remove("showing-" + sections[i].id); + } + document.body.classList.add("showing-" + sectionIdentifier); + + 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); + }, + + setSectionScore: function(sectionIdentifier, score, confidence) + { + document.querySelector("#" + sectionIdentifier + " .score").textContent = score; + if (confidence) + document.querySelector("#" + sectionIdentifier + " .confidence").textContent = confidence; + }, + + populateTable: function(tableIdentifier, headers, dashboard) + { + var table = new ResultsTable(document.getElementById(tableIdentifier), headers); + table.showIterations(dashboard); + } +}; + +window.benchmarkController = { + initialize: function() + { + benchmarkController.addOrientationListenerIfNecessary(); + }, + + determineCanvasSize: function() { + var match = window.matchMedia("(max-device-width: 760px)"); + if (match.matches) { + document.body.classList.add("small"); + return; + } + + match = window.matchMedia("(max-device-width: 1600px)"); + if (match.matches) { + document.body.classList.add("medium"); + return; + } + + match = window.matchMedia("(max-width: 1600px)"); + if (match.matches) { + document.body.classList.add("medium"); + return; + } + + document.body.classList.add("large"); + }, + + addOrientationListenerIfNecessary: function() { + if (!("orientation" in window)) + return; + + this.orientationQuery = window.matchMedia("(orientation: landscape)"); + this._orientationChanged(this.orientationQuery); + this.orientationQuery.addListener(this._orientationChanged); + }, + + _orientationChanged: function(match) + { + benchmarkController.isInLandscapeOrientation = match.matches; + if (match.matches) + document.querySelector(".start-benchmark p").classList.add("hidden"); + else + document.querySelector(".start-benchmark p").classList.remove("hidden"); + benchmarkController.updateStartButtonState(); + }, + + updateStartButtonState: function() + { + document.getElementById("run-benchmark").disabled = !this.isInLandscapeOrientation; + }, + + _startBenchmark: function(suites, options, frameContainerID) + { + benchmarkController.determineCanvasSize(); + + var configuration = document.body.className.match(/small|medium|large/); + if (configuration) + options[Strings.json.configuration] = configuration[0]; + + benchmarkRunnerClient.initialize(suites, options); + var frameContainer = document.getElementById(frameContainerID); + var runner = new BenchmarkRunner(suites, frameContainer, benchmarkRunnerClient); + runner.runMultipleIterations(); + + sectionsManager.showSection("test-container"); + }, + + startBenchmark: function() + { + var options = { + "test-interval": 30, + "display": "minimal", + "tiles": "big", + "controller": "ramp", + "kalman-process-error": 1, + "kalman-measurement-error": 4, + "time-measurement": "performance" + }; + this._startBenchmark(Suites, options, "test-container"); + }, + + showResults: function() + { + if (!this.addedKeyEvent) { + document.addEventListener("keypress", this.handleKeyPress, false); + this.addedKeyEvent = true; + } + + var dashboard = benchmarkRunnerClient.results; + var score = dashboard.score; + var confidence = "±" + (Statistics.largestDeviationPercentage(dashboard.scoreLowerBound, score, dashboard.scoreUpperBound) * 100).toFixed(2) + "%"; + sectionsManager.setSectionScore("results", score.toFixed(2), confidence); + sectionsManager.populateTable("results-header", Headers.testName, dashboard); + sectionsManager.populateTable("results-score", Headers.score, dashboard); + sectionsManager.populateTable("results-data", Headers.details, dashboard); + sectionsManager.showSection("results", true); + }, + + handleKeyPress: function(event) + { + switch (event.charCode) + { + case 27: // esc + benchmarkController.hideDebugInfo(); + break; + case 106: // j + benchmarkController.showDebugInfo(); + break; + case 115: // s + benchmarkController.selectResults(event.target); + break; + } + }, + + hideDebugInfo: function() + { + var overlay = document.getElementById("overlay"); + if (!overlay) + return; + document.body.removeChild(overlay); + }, + + showDebugInfo: function() + { + if (document.getElementById("overlay")) + return; + + var overlay = Utilities.createElement("div", { + id: "overlay" + }, document.body); + var container = Utilities.createElement("div", {}, overlay); + + var header = Utilities.createElement("h3", {}, container); + header.textContent = "Debug Output"; + + var data = Utilities.createElement("div", {}, container); + data.textContent = "Please wait..."; + setTimeout(function() { + var output = { + options: benchmarkRunnerClient.results.options, + data: benchmarkRunnerClient.results.data + }; + data.textContent = JSON.stringify(output, function(key, value) { + if (typeof value === 'number') + return Utilities.toFixedNumber(value, 3); + return value; + }, 1); + }, 0); + data.onclick = function() { + var selection = window.getSelection(); + selection.removeAllRanges(); + var range = document.createRange(); + range.selectNode(data); + selection.addRange(range); + }; + + var button = Utilities.createElement("button", {}, container); + button.textContent = "Done"; + button.onclick = function() { + benchmarkController.hideDebugInfo(); + }; + }, + + selectResults: function(target) + { + target.selectRange = ((target.selectRange || 0) + 1) % 3; + + var selection = window.getSelection(); + selection.removeAllRanges(); + var range = document.createRange(); + switch (target.selectRange) { + case 0: { + range.selectNode(document.getElementById("results-score")); + break; + } + case 1: { + range.setStart(document.querySelector("#results .score"), 0); + range.setEndAfter(document.querySelector("#results-score"), 0); + break; + } + case 2: { + range.selectNodeContents(document.querySelector("#results .score")); + break; + } + } + selection.addRange(range); + } +}; + +window.addEventListener("load", function() { benchmarkController.initialize(); }); diff --git a/third_party/webkit/PerformanceTests/MotionMark/resources/runner/benchmark-runner.js b/third_party/webkit/PerformanceTests/MotionMark/resources/runner/benchmark-runner.js new file mode 100644 index 0000000000..1aa630356c --- /dev/null +++ b/third_party/webkit/PerformanceTests/MotionMark/resources/runner/benchmark-runner.js @@ -0,0 +1,179 @@ +BenchmarkRunnerState = Utilities.createClass( + function(suites) + { + this._suites = suites; + this._suiteIndex = -1; + this._testIndex = 0; + this.next(); + }, { + + currentSuite: function() + { + return this._suites[this._suiteIndex]; + }, + + currentTest: function() + { + var suite = this.currentSuite(); + return suite ? suite.tests[this._testIndex] : null; + }, + + isFirstTest: function() + { + return !this._testIndex; + }, + + next: function() + { + this._testIndex++; + + var suite = this._suites[this._suiteIndex]; + if (suite && this._testIndex < suite.tests.length) + return; + + this._testIndex = 0; + do { + this._suiteIndex++; + } while (this._suiteIndex < this._suites.length && this._suites[this._suiteIndex].disabled); + }, + + prepareCurrentTest: function(runner, frame) + { + var test = this.currentTest(); + var promise = new SimplePromise; + + frame.onload = function() { + promise.resolve(); + }; + + frame.src = "tests/" + test.url; + return promise; + } +}); + +BenchmarkRunner = Utilities.createClass( + function(suites, frameContainer, client) + { + this._suites = suites; + this._client = client; + this._frameContainer = frameContainer; + }, { + + _appendFrame: function() + { + var frame = document.createElement("iframe"); + frame.setAttribute("scrolling", "no"); + + this._frameContainer.insertBefore(frame, this._frameContainer.firstChild); + this._frame = frame; + return frame; + }, + + _removeFrame: function() + { + if (this._frame) { + this._frame.parentNode.removeChild(this._frame); + this._frame = null; + } + }, + + _runBenchmarkAndRecordResults: 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 contentWindow = this._frame.contentWindow; + var self = this; + + var options = { complexity: test.complexity }; + Utilities.extendObject(options, this._client.options); + Utilities.extendObject(options, contentWindow.Utilities.parseParameters()); + + var benchmark = new contentWindow.benchmarkClass(options); + document.body.style.backgroundColor = benchmark.backgroundColor(); + benchmark.run().then(function(testData) { + var suiteResults = self._suitesResults[suite.name] || {}; + suiteResults[test.name] = testData; + self._suitesResults[suite.name] = suiteResults; + + if (self._client && self._client.didRunTest) + self._client.didRunTest(testData); + + state.next(); + if (state.currentSuite() != suite) + self._removeFrame(); + promise.resolve(state); + }); + + return promise; + }, + + step: function(state) + { + if (!state) { + state = new BenchmarkRunnerState(this._suites); + this._suitesResults = {}; + } + + var suite = state.currentSuite(); + if (!suite) { + this._finalize(); + var promise = new SimplePromise; + promise.resolve(); + return promise; + } + + if (state.isFirstTest()) { + this._appendFrame(); + } + + return state.prepareCurrentTest(this, this._frame).then(function(prepareReturnValue) { + return this._runBenchmarkAndRecordResults(state); + }.bind(this)); + }, + + runAllSteps: function(startingState) + { + var nextCallee = this.runAllSteps.bind(this); + this.step(startingState).then(function(nextState) { + if (nextState) + nextCallee(nextState); + }); + }, + + runMultipleIterations: function() + { + var self = this; + var currentIteration = 0; + + this._runNextIteration = function() { + currentIteration++; + if (currentIteration < self._client.iterationCount) + self.runAllSteps(); + else if (this._client && this._client.didFinishLastIteration) { + document.body.style.backgroundColor = ""; + self._client.didFinishLastIteration(); + } + } + + if (this._client && this._client.willStartFirstIteration) + this._client.willStartFirstIteration(); + + this.runAllSteps(); + }, + + _finalize: function() + { + this._removeFrame(); + + if (this._client && this._client.didRunSuites) + this._client.didRunSuites(this._suitesResults); + + if (this._runNextIteration) + this._runNextIteration(); + } +}); diff --git a/third_party/webkit/PerformanceTests/MotionMark/resources/runner/crystal.svg b/third_party/webkit/PerformanceTests/MotionMark/resources/runner/crystal.svg new file mode 100644 index 0000000000..0090df6c0c --- /dev/null +++ b/third_party/webkit/PerformanceTests/MotionMark/resources/runner/crystal.svg @@ -0,0 +1,92 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/third_party/webkit/PerformanceTests/MotionMark/resources/runner/lines.svg b/third_party/webkit/PerformanceTests/MotionMark/resources/runner/lines.svg new file mode 100644 index 0000000000..83458b8095 --- /dev/null +++ b/third_party/webkit/PerformanceTests/MotionMark/resources/runner/lines.svg @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/third_party/webkit/PerformanceTests/MotionMark/resources/runner/logo.svg b/third_party/webkit/PerformanceTests/MotionMark/resources/runner/logo.svg new file mode 100644 index 0000000000..a7d0eaf375 --- /dev/null +++ b/third_party/webkit/PerformanceTests/MotionMark/resources/runner/logo.svg @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/third_party/webkit/PerformanceTests/MotionMark/resources/runner/tests.js b/third_party/webkit/PerformanceTests/MotionMark/resources/runner/tests.js new file mode 100644 index 0000000000..aa938c5189 --- /dev/null +++ b/third_party/webkit/PerformanceTests/MotionMark/resources/runner/tests.js @@ -0,0 +1,81 @@ +var Headers = { + testName: [ + { + title: "" + Strings.text.testName + "", + text: Strings.text.testName + } + ], + score: [ + { + title: Strings.text.score, + text: Strings.json.score + } + ], + details: [ + { + title: " ", + text: function(data) { + var bootstrap = data[Strings.json.complexity][Strings.json.bootstrap]; + return "±" + (Statistics.largestDeviationPercentage(bootstrap.confidenceLow, bootstrap.median, bootstrap.confidenceHigh) * 100).toFixed(2) + "%"; + } + } + ] +}; + +var Suite = function(name, tests) { + this.name = name; + this.tests = tests; +}; + +var Suites = []; + +Suites.push(new Suite("Animometer", + [ + { + url: "master/multiply.html", + name: "Multiply" + }, + { + url: "master/canvas-stage.html?pathType=arcs", + name: "Canvas Arcs" + }, + { + url: "master/leaves.html", + name: "Leaves" + }, + { + url: "master/canvas-stage.html?pathType=linePath", + name: "Paths" + }, + { + url: "master/canvas-stage.html?pathType=line&lineCap=square", + name: "Canvas Lines" + }, + { + url: "master/focus.html", + name: "Focus" + }, + { + url: "master/image-data.html", + name: "Images" + }, + { + url: "master/text.html", + name: "Design" + }, + { + url: "master/svg-particles.html", + name: "Suits" + }, + ] +)); + +function suiteFromName(name) +{ + return Suites.find(function(suite) { return suite.name == name; }); +} + +function testFromName(suite, name) +{ + return suite.tests.find(function(test) { return test.name == name; }); +} -- cgit v1.2.3