Diff
Modified: trunk/PerformanceTests/Animometer/developer.html (196296 => 196297)
--- trunk/PerformanceTests/Animometer/developer.html 2016-02-09 03:30:44 UTC (rev 196296)
+++ trunk/PerformanceTests/Animometer/developer.html 2016-02-09 03:30:47 UTC (rev 196297)
@@ -8,14 +8,14 @@
<script src=""
<script src=""
- <script src="" charset="utf-8"></script>
+ <script src=""
<script src="" charset="utf-8"></script>
- <script src="" charset="utf-8"></script>
+ <script src=""
<script src=""
<script src=""
<script src=""
- <script src=""
+ <script src="" charset="utf-8"></script>
</head>
<body>
<main>
@@ -103,7 +103,7 @@
<h1>Graph:</h1>
</header>
<nav>
- <form name="graph-options">
+ <form name="time-graph-options">
<ul>
<li><label><input type="checkbox" name="markers" checked> Markers</label>
<span>time: <span class="time"></span></span></li>
Modified: trunk/PerformanceTests/Animometer/resources/debug-runner/animometer.js (196296 => 196297)
--- trunk/PerformanceTests/Animometer/resources/debug-runner/animometer.js 2016-02-09 03:30:44 UTC (rev 196296)
+++ trunk/PerformanceTests/Animometer/resources/debug-runner/animometer.js 2016-02-09 03:30:47 UTC (rev 196297)
@@ -19,6 +19,111 @@
}
});
+DeveloperResultsTable = Utilities.createSubclass(ResultsTable,
+ function(element, headers)
+ {
+ ResultsTable.call(this, element, headers);
+ }, {
+
+ _addGraphButton: function(td, testName, testResults)
+ {
+ var data = ""
+ if (!data)
+ return;
+
+ var button = Utilities.createElement("button", { class: "small-button" }, td);
+
+ button.addEventListener("click", function() {
+ var graphData = {
+ axes: [Strings.text.complexity, Strings.text.frameRate],
+ samples: data,
+ complexityAverageSamples: testResults[Strings.json.complexityAverageSamples],
+ averages: {},
+ marks: testResults[Strings.json.marks]
+ };
+ [Strings.json.experiments.complexity, Strings.json.experiments.frameRate].forEach(function(experiment) {
+ if (experiment in testResults)
+ graphData.averages[experiment] = testResults[experiment];
+ });
+
+ [
+ Strings.json.score,
+ Strings.json.regressions.timeRegressions,
+ Strings.json.regressions.complexityRegression,
+ Strings.json.regressions.complexityAverageRegression,
+ Strings.json.targetFrameLength
+ ].forEach(function(key) {
+ if (testResults[key])
+ graphData[key] = testResults[key];
+ });
+
+ benchmarkController.showTestGraph(testName, graphData);
+ });
+
+ button.textContent = Strings.text.graph + "...";
+ },
+
+ _isNoisyMeasurement: function(jsonExperiment, data, measurement, options)
+ {
+ const percentThreshold = 10;
+ const averageThreshold = 2;
+
+ if (measurement == Strings.json.measurements.percent)
+ return data[Strings.json.measurements.percent] >= percentThreshold;
+
+ if (jsonExperiment == Strings.json.experiments.frameRate && measurement == Strings.json.measurements.average)
+ return Math.abs(data[Strings.json.measurements.average] - options["frame-rate"]) >= averageThreshold;
+
+ return false;
+ },
+
+ _addTest: function(testName, testResults, options)
+ {
+ var row = Utilities.createElement("tr", {}, this.element);
+
+ var isNoisy = false;
+ [Strings.json.experiments.complexity, Strings.json.experiments.frameRate].forEach(function (experiment) {
+ var data = ""
+ for (var measurement in data) {
+ if (this._isNoisyMeasurement(experiment, data, measurement, options))
+ isNoisy = true;
+ }
+ }, this);
+
+ this._flattenedHeaders.forEach(function (header) {
+ var className = "";
+ if (header.className) {
+ if (typeof header.className == "function")
+ className = header.className(testResults, options);
+ else
+ className = header.className;
+ }
+
+ if (header.title == Strings.text.testName) {
+ if (isNoisy)
+ className += " noisy-results";
+ var td = Utilities.createElement("td", { class: className }, row);
+ td.textContent = testName;
+ return;
+ }
+
+ var td = Utilities.createElement("td", { class: className }, row);
+ if (header.title == Strings.text.graph) {
+ this._addGraphButton(td, testName, testResults);
+ } else if (!("text" in header)) {
+ td.textContent = testResults[header.title];
+ } else if (typeof header.text == "string") {
+ var data = ""
+ if (typeof data == "number")
+ data = ""
+ td.textContent = data;
+ } else {
+ td.textContent = header.text(testResults, testName);
+ }
+ }, this);
+ }
+});
+
Utilities.extendObject(window.benchmarkRunnerClient, {
testsCount: null,
progressBar: null,
@@ -45,6 +150,12 @@
setSectionHeader: function(sectionIdentifier, title)
{
document.querySelector("#" + sectionIdentifier + " h1").textContent = title;
+ },
+
+ populateTable: function(tableIdentifier, headers, data)
+ {
+ var table = new DeveloperResultsTable(document.getElementById(tableIdentifier), headers);
+ table.showIterations(data, benchmarkRunnerClient.options);
}
});
@@ -343,7 +454,7 @@
initialize: function()
{
document.forms["benchmark-options"].addEventListener("change", benchmarkController.onBenchmarkOptionsChanged, true);
- document.forms["graph-options"].addEventListener("change", benchmarkController.onGraphOptionsChanged, true);
+ document.forms["time-graph-options"].addEventListener("change", benchmarkController.onTimeGraphOptionsChanged, true);
optionsManager.updateUIFromLocalStorage();
suitesManager.createElements();
suitesManager.updateUIFromLocalStorage();
@@ -397,10 +508,9 @@
document.querySelector("#results-json div").classList.remove("hidden");
},
- showTestGraph: function(testName, score, mean, graphData)
+ showTestGraph: function(testName, graphData)
{
sectionsManager.setSectionHeader("test-graph", testName);
- sectionsManager.setSectionScore("test-graph", score, mean);
sectionsManager.showSection("test-graph", true);
this.updateGraphData(graphData);
}
Modified: trunk/PerformanceTests/Animometer/resources/debug-runner/graph.js (196296 => 196297)
--- trunk/PerformanceTests/Animometer/resources/debug-runner/graph.js 2016-02-09 03:30:44 UTC (rev 196296)
+++ trunk/PerformanceTests/Animometer/resources/debug-runner/graph.js 2016-02-09 03:30:47 UTC (rev 196297)
@@ -5,12 +5,22 @@
{
var element = document.getElementById("test-graph-data");
element.innerHTML = "";
+ element.graphData = graphData;
document.querySelector("hr").style.width = this.layoutCounter++ + "px";
var margins = new Insets(30, 30, 30, 40);
var size = Point.elementClientSize(element).subtract(margins.size);
+ this.createTimeGraph(graphData, margins, size);
+ this.onTimeGraphOptionsChanged();
+
+ this.onGraphTypeChanged();
+ },
+
+ createTimeGraph: function(graphData, margins, size)
+ {
var svg = d3.select("#test-graph-data").append("svg")
+ .attr("id", "time-graph")
.attr("width", size.width + margins.left + margins.right)
.attr("height", size.height + margins.top + margins.bottom)
.append("g")
@@ -22,10 +32,14 @@
// Axis scales
var x = d3.scale.linear()
.range([0, size.width])
- .domain([0, d3.max(graphData.samples, function(s) { return s.time; })]);
+ .domain([
+ Math.min(d3.min(graphData.samples, function(s) { return s.time; }), 0),
+ d3.max(graphData.samples, function(s) { return s.time; })]);
+ var complexityMax = d3.max(graphData.samples, function(s) { return s.complexity; });
+
var yLeft = d3.scale.linear()
.range([size.height, 0])
- .domain([0, d3.max(graphData.samples, function(s) { return s.complexity; })]);
+ .domain([0, complexityMax]);
var yRight = d3.scale.linear()
.range([size.height, 0])
.domain([1000/20, 1000/60]);
@@ -98,32 +112,33 @@
.attr("class", "marker")
.attr("transform", "translate(" + xLocation + ", 0)");
markerGroup.append("text")
- .attr("transform", "translate(10, " + (yMin - 10) + ") rotate(-90)")
- .style("text-anchor", "start")
- .text(markName)
+ .attr("transform", "translate(10, " + (yMin - 10) + ") rotate(-90)")
+ .style("text-anchor", "start")
+ .text(markName)
markerGroup.append("line")
- .attr("x1", 0)
- .attr("x2", 0)
- .attr("y1", yMin)
- .attr("y2", yMax);
+ .attr("x1", 0)
+ .attr("x2", 0)
+ .attr("y1", yMin)
+ .attr("y2", yMax);
}
- // left-mean
- svg.append("line")
- .attr("x1", x(0))
- .attr("x2", size.width)
- .attr("y1", yLeft(graphData.mean[0]))
- .attr("y2", yLeft(graphData.mean[0]))
- .attr("class", "left-mean mean");
+ if (Strings.json.experiments.complexity in graphData.averages) {
+ var complexity = graphData.averages[Strings.json.experiments.complexity];
+ var regression = svg.append("g")
+ .attr("class", "complexity mean");
+ this._addRegressionLine(regression, x, yLeft, [[graphData.samples[0].time, complexity.average], [graphData.samples[graphData.samples.length - 1].time, complexity.average]], complexity.stdev);
+ }
+ if (Strings.json.experiments.frameRate in graphData.averages) {
+ var frameRate = graphData.averages[Strings.json.experiments.frameRate];
+ var average = yRight(1000/frameRate.average);
+ svg.append("line")
+ .attr("x1", x(0))
+ .attr("x2", size.width)
+ .attr("y1", average)
+ .attr("y2", average)
+ .attr("class", "fps mean");
+ }
- // right-mean
- svg.append("line")
- .attr("x1", x(0))
- .attr("x2", size.width)
- .attr("y1", yRight(graphData.mean[1]))
- .attr("y2", yRight(graphData.mean[1]))
- .attr("class", "right-mean mean");
-
// right-target
if (targetFrameLength) {
svg.append("line")
@@ -135,7 +150,7 @@
}
// Cursor
- var cursorGroup = svg.append("g").attr("id", "cursor");
+ var cursorGroup = svg.append("g").attr("class", "cursor");
cursorGroup.append("line")
.attr("x1", 0)
.attr("x2", 0)
@@ -179,19 +194,19 @@
.attr("fill", "transparent")
.attr("x", 0)
.attr("y", 0)
- .attr("width", size.x)
- .attr("height", size.y);
+ .attr("width", size.width)
+ .attr("height", size.height);
var timeBisect = d3.bisector(function(d) { return d.time; }).right;
var statsToHighlight = ["complexity", "rawFPS", "filteredFPS"];
area.on("mouseover", function() {
- document.getElementById("cursor").classList.remove("hidden");
+ document.querySelector("#time-graph .cursor").classList.remove("hidden");
document.querySelector("#test-graph nav").classList.remove("hide-data");
}).on("mouseout", function() {
- document.getElementById("cursor").classList.add("hidden");
+ document.querySelector("#time-graph .cursor").classList.add("hidden");
document.querySelector("#test-graph nav").classList.add("hide-data");
}).on("mousemove", function() {
- var form = document.forms["graph-options"].elements;
+ var form = document.forms["time-graph-options"].elements;
var mx_domain = x.invert(d3.mouse(this)[0]);
var index = Math.min(timeBisect(allData, mx_domain), allData.length - 1);
@@ -229,9 +244,9 @@
cursorGroup.select("." + name)
.attr("cx", cursor_x)
.attr("cy", data_y);
- document.querySelector("#cursor ." + name).classList.remove("hidden");
+ document.querySelector("#time-graph .cursor ." + name).classList.remove("hidden");
} else
- document.querySelector("#cursor ." + name).classList.add("hidden");
+ document.querySelector("#time-graph .cursor ." + name).classList.add("hidden");
});
if (form["rawFPS"].checked)
@@ -243,27 +258,58 @@
.attr("y2", Math.max.apply(null, ys));
});
- this.onGraphOptionsChanged();
},
- onGraphOptionsChanged: function() {
- var form = document.forms["graph-options"].elements;
+ _showOrHideNodes: function(isShown, selector) {
+ var nodeList = document.querySelectorAll(selector);
+ if (isShown) {
+ for (var i = 0; i < nodeList.length; ++i)
+ nodeList[i].classList.remove("hidden");
+ } else {
+ for (var i = 0; i < nodeList.length; ++i)
+ nodeList[i].classList.add("hidden");
+ }
+ },
- function showOrHideNodes(isShown, selector) {
- var nodeList = document.querySelectorAll(selector);
- if (isShown) {
- for (var i = 0; i < nodeList.length; ++i)
- nodeList[i].classList.remove("hidden");
- } else {
- for (var i = 0; i < nodeList.length; ++i)
- nodeList[i].classList.add("hidden");
+ onTimeGraphOptionsChanged: function() {
+ var form = document.forms["time-graph-options"].elements;
+ benchmarkController._showOrHideNodes(form["markers"].checked, ".marker");
+ benchmarkController._showOrHideNodes(form["averages"].checked, "#test-graph-data .mean");
+ benchmarkController._showOrHideNodes(form["complexity"].checked, "#complexity");
+ benchmarkController._showOrHideNodes(form["rawFPS"].checked, "#rawFPS");
+ benchmarkController._showOrHideNodes(form["filteredFPS"].checked, "#filteredFPS");
+ benchmarkController._showOrHideNodes(form["regressions"].checked, "#regressions");
+ },
+
+ onGraphTypeChanged: function() {
+ var form = document.forms["graph-type"].elements;
+ var graphData = document.getElementById("test-graph-data").graphData;
+ var isTimeSelected = true;
+
+ benchmarkController._showOrHideNodes(isTimeSelected, "#time-graph");
+ benchmarkController._showOrHideNodes(isTimeSelected, "form[name=time-graph-options]");
+
+ var score, mean;
+ if (isTimeSelected) {
+ score = graphData.score.toFixed(2);
+
+ var regression = graphData.averages.complexity;
+ mean = [
+ "mean: ",
+ regression.average.toFixed(2),
+ " ± ",
+ regression.stdev.toFixed(2),
+ " (",
+ regression.percent.toFixed(2),
+ "%)"];
+ if (regression.concern) {
+ mean = mean.concat([
+ ", worst 5%: ",
+ regression.concern.toFixed(2)]);
}
+ mean = mean.join("");
}
- showOrHideNodes(form["markers"].checked, ".marker");
- showOrHideNodes(form["averages"].checked, ".mean");
- showOrHideNodes(form["complexity"].checked, "#complexity");
- showOrHideNodes(form["rawFPS"].checked, "#rawFPS");
- showOrHideNodes(form["filteredFPS"].checked, "#filteredFPS");
+ sectionsManager.setSectionScore("test-graph", score, mean);
}
});
Modified: trunk/PerformanceTests/Animometer/resources/runner/animometer.js (196296 => 196297)
--- trunk/PerformanceTests/Animometer/resources/runner/animometer.js 2016-02-09 03:30:44 UTC (rev 196296)
+++ trunk/PerformanceTests/Animometer/resources/runner/animometer.js 2016-02-09 03:30:47 UTC (rev 196297)
@@ -98,58 +98,6 @@
});
},
- _addGraphButton: function(td, testName, testResults)
- {
- var data = ""
- if (!data)
- return;
-
- var button = Utilities.createElement("button", { class: "small-button" }, td);
-
- button.addEventListener("click", function() {
- var score = testResults[Strings.json.score].toFixed(2);
- var complexity = testResults[Strings.json.experiments.complexity];
- var mean = [
- "mean: ",
- complexity[Strings.json.measurements.average].toFixed(2),
- " ± ",
- complexity[Strings.json.measurements.stdev].toFixed(2),
- " (",
- complexity[Strings.json.measurements.percent].toFixed(2),
- "%), worst 5%: ",
- complexity[Strings.json.measurements.concern].toFixed(2)].join("");
-
- var graphData = {
- axes: [Strings.text.experiments.complexity, Strings.text.experiments.frameRate],
- mean: [
- testResults[Strings.json.experiments.complexity][Strings.json.measurements.average],
- 1000 / testResults[Strings.json.experiments.frameRate][Strings.json.measurements.average]
- ],
- samples: data,
- marks: testResults[Strings.json.marks]
- }
- if (testResults[Strings.json.targetFrameLength])
- graphData.targetFrameLength = testResults[Strings.json.targetFrameLength];
- benchmarkController.showTestGraph(testName, score, mean, graphData);
- });
-
- button.textContent = Strings.text.results.graph + "...";
- },
-
- _isNoisyMeasurement: function(jsonExperiment, data, measurement, options)
- {
- const percentThreshold = 10;
- const averageThreshold = 2;
-
- if (measurement == Strings.json.measurements.percent)
- return data[Strings.json.measurements.percent] >= percentThreshold;
-
- if (jsonExperiment == Strings.json.experiments.frameRate && measurement == Strings.json.measurements.average)
- return Math.abs(data[Strings.json.measurements.average] - options["frame-rate"]) >= averageThreshold;
-
- return false;
- },
-
_addEmptyRow: function()
{
var row = Utilities.createElement("tr", {}, this.element);
@@ -162,45 +110,15 @@
{
var row = Utilities.createElement("tr", {}, this.element);
- var isNoisy = false;
- [Strings.json.experiments.complexity, Strings.json.experiments.frameRate].forEach(function (experiment) {
- var data = ""
- for (var measurement in data) {
- if (this._isNoisyMeasurement(experiment, data, measurement, options))
- isNoisy = true;
- }
- }, this);
-
this._flattenedHeaders.forEach(function (header) {
- var className = "";
- if (header.className) {
- if (typeof header.className == "function")
- className = header.className(testResults, options);
- else
- className = header.className;
- }
-
+ var td = Utilities.createElement("td", {}, row);
if (header.title == Strings.text.testName) {
- var titleClassName = className;
- if (isNoisy)
- titleClassName += " noisy-results";
- var td = Utilities.createElement("td", { class: titleClassName }, row);
td.textContent = testName;
- return;
- }
-
- var td = Utilities.createElement("td", { class: className }, row);
- if (header.title == Strings.text.results.graph) {
- this._addGraphButton(td, testName, testResults);
- } else if (!("text" in header)) {
- td.textContent = testResults[header.title];
- } else if (typeof header.text == "string") {
+ } else if (header.text) {
var data = ""
if (typeof data == "number")
data = ""
td.textContent = data;
- } else {
- td.textContent = header.text(testResults, testName);
}
}, this);
},
Modified: trunk/PerformanceTests/ChangeLog (196296 => 196297)
--- trunk/PerformanceTests/ChangeLog 2016-02-09 03:30:44 UTC (rev 196296)
+++ trunk/PerformanceTests/ChangeLog 2016-02-09 03:30:47 UTC (rev 196297)
@@ -1,5 +1,23 @@
2016-02-07 Jon Lee <jon...@apple.com>
+ Move ResultsTable functionality not needed for release tests out.
+ Move reporting of score and mean to selection of the time-based graph.
+
+ * Animometer/developer.html: Rename graph-options to time-graph-options.
+ * Animometer/resources/debug-runner/animometer.js:
+ (DeveloperResultsTable): Moved from runner/animometer.js. Switch from mean
+ values to "average" objects which can hold stdev. Move graph button and
+ calculation of noisy measurements here. Sophisticated header processing
+ is not needed in release suite.
+ (populateTable): Use DeveloperResultsTable.
+ * Animometer/resources/debug-runner/graph.js: Pull time graph creation to
+ its own function, and add a new onGraphTypeChanged handler in preparation
+ of a complexity graph to be added later.
+ * Animometer/resources/runner/animometer.js:
+ (ResultsTable): Simplify to just handle test names and scores.
+
+2016-02-07 Jon Lee <jon...@apple.com>
+
Tests: reuse objects already made.
Avoid thrash of object creation and removal by maintaining an index that