зеркало из https://github.com/mozilla/treeherder.git
Bug 1142680 - initial work to get a compare-talos equivalent stood up
This commit is contained in:
Родитель
87325652ad
Коммит
fd0f772aa6
39
Gruntfile.js
39
Gruntfile.js
|
@ -51,9 +51,17 @@ module.exports = function(grunt) {
|
|||
dest:'dist'
|
||||
}
|
||||
},
|
||||
compare: {
|
||||
src:'webapp/app/compare.html',
|
||||
nonull: true,
|
||||
options:{
|
||||
dest:'dist'
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
usemin:{ html:['dist/index.html', 'dist/help.html', 'dist/logviewer.html', 'dist/perf.html'] },
|
||||
usemin:{ html:['dist/index.html', 'dist/help.html', 'dist/logviewer.html',
|
||||
'dist/perf.html', 'dist/compare.html'] },
|
||||
|
||||
'cache-busting': {
|
||||
indexjs: {
|
||||
|
@ -74,6 +82,12 @@ module.exports = function(grunt) {
|
|||
file: 'dist/js/perf.min.js',
|
||||
cleanup: true
|
||||
},
|
||||
comparejs: {
|
||||
replace: ['dist/**/*.html'],
|
||||
replacement: 'compare.min.js',
|
||||
file: 'dist/js/compare.min.js',
|
||||
cleanup: true
|
||||
},
|
||||
indexcss: {
|
||||
replace: ['dist/**/*.html'],
|
||||
replacement: 'index.min.css',
|
||||
|
@ -107,7 +121,8 @@ module.exports = function(grunt) {
|
|||
{ src:'webapp/app/index.html', dest:'dist/index.html', nonull: true },
|
||||
{ src:'webapp/app/help.html', dest:'dist/help.html', nonull: true },
|
||||
{ src:'webapp/app/logviewer.html', dest:'dist/logviewer.html', nonull: true },
|
||||
{ src:'webapp/app/perf.html', dest:'dist/perf.html', nonull: true }
|
||||
{ src:'webapp/app/perf.html', dest:'dist/perf.html', nonull: true },
|
||||
{ src:'webapp/app/compare.html', dest:'dist/compare.html', nonull: true }
|
||||
]
|
||||
},
|
||||
// Copy img dir
|
||||
|
@ -215,6 +230,26 @@ module.exports = function(grunt) {
|
|||
keepClosingSlash: true
|
||||
}
|
||||
}
|
||||
},
|
||||
compare: {
|
||||
cwd: 'webapp/app',
|
||||
src: 'partials/perf/*.html',
|
||||
dest: 'dist/js/compare.min.js',
|
||||
options: {
|
||||
usemin: 'dist/js/compare.min.js',
|
||||
append: true,
|
||||
htmlmin: {
|
||||
collapseBooleanAttributes: true,
|
||||
collapseWhitespace: true,
|
||||
removeAttributeQuotes: true,
|
||||
removeComments: true,
|
||||
removeEmptyAttributes: true,
|
||||
removeRedundantAttributes: true,
|
||||
removeScriptTypeAttributes: true,
|
||||
removeStyleLinkTypeAttributes: true,
|
||||
keepClosingSlash: true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
<!DOCTYPE html>
|
||||
<html ng-app="compare">
|
||||
<head>
|
||||
<meta charset="iso-8859-1" />
|
||||
<title>Compare Performance</title>
|
||||
<!-- build:css css/perf.min.css -->
|
||||
<link href="css/bootstrap.css" rel="stylesheet" media="screen">
|
||||
<link href="css/perf.css" rel="stylesheet" media="screen">
|
||||
<!-- endbuild -->
|
||||
<link id="favicon" type="image/png" rel="shortcut icon" href="img/tree_open.png">
|
||||
<style>
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<section ui-view>
|
||||
</section>
|
||||
|
||||
<script src="js/config/local.conf.js"></script>
|
||||
|
||||
<!-- build:js js/compare.min.js -->
|
||||
<script src="vendor/jquery-2.0.3.js"></script>
|
||||
<script src="vendor/underscore-min.js"></script>
|
||||
<script src="vendor/angular/angular.js"></script>
|
||||
<script src="vendor/angular/angular-route.js"></script>
|
||||
<script src="vendor/angular/angular-resource.js"></script>
|
||||
<script src="vendor/angular/angular-cookies.js"></script>
|
||||
<script src="vendor/angular/angular-ui-router.js"></script>
|
||||
<script src="vendor/angular/angular-sanitize.min.js"></script>
|
||||
<script src="vendor/angular-local-storage.min.js"></script>
|
||||
<script src="vendor/ui-bootstrap-tpls-0.11.2.min.js"></script>
|
||||
<script src="vendor/bootstrap.js"></script>
|
||||
<script src="vendor/mousetrap.min.js"></script>
|
||||
<script src="js/treeherder.js"></script>
|
||||
<script src="js/providers.js"></script>
|
||||
<script src="js/compareperf.js"></script>
|
||||
<!-- endbuild -->
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -165,9 +165,67 @@ to { opacity: 0; }
|
|||
}
|
||||
|
||||
|
||||
<<<<<<< HEAD
|
||||
<<<<<<< HEAD
|
||||
.subtest-header {
|
||||
=======
|
||||
.subtestheader {
|
||||
>>>>>>> initial work to get compare-talos stood up inside of perfherder
|
||||
=======
|
||||
.subtest-header {
|
||||
>>>>>>> addressed all feedback except a common library, a few TODO items left in the code
|
||||
background-image: linear-gradient(to bottom, #6A7B86, #424F5A);
|
||||
color: white;
|
||||
font-weight: bold;
|
||||
}
|
||||
<<<<<<< HEAD
|
||||
<<<<<<< HEAD
|
||||
<<<<<<< HEAD
|
||||
|
||||
=======
|
||||
>>>>>>> addressed all feedback except a common library, a few TODO items left in the code
|
||||
=======
|
||||
|
||||
>>>>>>> addressed review feedback: whitespace, blank lines, s/compare.js/compareperf.js/, cleaned up angular classes and extra <div>'s, reduced a forEach(..) call to a _.where(...) call, etc.
|
||||
.subtest-improvement {
|
||||
background-color: green;
|
||||
color: white;
|
||||
font-weight: bold;
|
||||
}
|
||||
<<<<<<< HEAD
|
||||
<<<<<<< HEAD
|
||||
|
||||
=======
|
||||
>>>>>>> addressed all feedback except a common library, a few TODO items left in the code
|
||||
=======
|
||||
|
||||
>>>>>>> addressed review feedback: whitespace, blank lines, s/compare.js/compareperf.js/, cleaned up angular classes and extra <div>'s, reduced a forEach(..) call to a _.where(...) call, etc.
|
||||
.subtest-regression {
|
||||
background-color: red;
|
||||
color: white;
|
||||
font-weight: bold;
|
||||
}
|
||||
<<<<<<< HEAD
|
||||
<<<<<<< HEAD
|
||||
|
||||
=======
|
||||
>>>>>>> addressed all feedback except a common library, a few TODO items left in the code
|
||||
=======
|
||||
|
||||
>>>>>>> addressed review feedback: whitespace, blank lines, s/compare.js/compareperf.js/, cleaned up angular classes and extra <div>'s, reduced a forEach(..) call to a _.where(...) call, etc.
|
||||
.subtest-empty {
|
||||
display: none;
|
||||
}
|
||||
|
||||
<<<<<<< HEAD
|
||||
=======
|
||||
>>>>>>> initial work to get compare-talos stood up inside of perfherder
|
||||
=======
|
||||
>>>>>>> addressed all feedback except a common library, a few TODO items left in the code
|
||||
.subtest-result button {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.subtest-result:hover button {
|
||||
display: inline-block;
|
||||
}
|
||||
|
@ -178,3 +236,15 @@ to { opacity: 0; }
|
|||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.compare-improvement {
|
||||
background-color: green;
|
||||
color: white;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.compare-regression {
|
||||
background-color: red;
|
||||
color: white;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
|
Двоичный файл не отображается.
После Ширина: | Высота: | Размер: 58 KiB |
|
@ -0,0 +1,399 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, you can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Utility Functions
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
|
||||
/**
|
||||
* Compute the standard deviation for an array of values.
|
||||
*
|
||||
* @param values
|
||||
* An array of numbers.
|
||||
* @param avg
|
||||
* Average of the values.
|
||||
* @return a number (the standard deviation)
|
||||
*/
|
||||
function stddev(values, avg) {
|
||||
if (values.length <= 1) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return Math.sqrt(
|
||||
values.map(function (v) { return Math.pow(v - avg, 2); })
|
||||
.reduce(function (a, b) { return a + b; }) / (values.length - 1));
|
||||
}
|
||||
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// End Utility Functions
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
|
||||
var compare = angular.module("compare", ['ui.router', 'ui.bootstrap', 'treeherder']);
|
||||
|
||||
//TODO: make getSeriesSummary part of a common library
|
||||
compare.factory('getSeriesSummary', [ function() {
|
||||
return function(signature, signatureProps, optionCollectionMap, pgo, e10s) {
|
||||
var platform = signatureProps.machine_platform + " " +
|
||||
signatureProps.machine_architecture;
|
||||
var extra = "";
|
||||
if (signatureProps.job_group_symbol === "T-e10s") {
|
||||
extra = " e10s";
|
||||
}
|
||||
var testName = signatureProps.test;
|
||||
var subtestSignatures;
|
||||
if (testName === undefined) {
|
||||
testName = "summary";
|
||||
subtestSignatures = signatureProps.subtest_signatures;
|
||||
}
|
||||
var name = signatureProps.suite + " " + testName +
|
||||
" " + optionCollectionMap[signatureProps.option_collection_hash] + extra;
|
||||
|
||||
//Only keep summary signatures, filter in/out e10s and pgo
|
||||
if (name.indexOf('summary') <= 0) {
|
||||
return null;
|
||||
}
|
||||
if (e10s && (name.indexOf('e10s') <= 0)) {
|
||||
return null;
|
||||
} else if (!e10s && (name.indexOf('e10s') > 0)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
//TODO: pgo is linux/windows only- what about osx and android
|
||||
if (pgo && (name.indexOf('pgo') <= 1)) {
|
||||
return null;
|
||||
} else if (!pgo && (name.indexOf('pgo') > 0)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return { name: name, signature: signature, platform: platform,
|
||||
subtestSignatures: subtestSignatures };
|
||||
};
|
||||
}]);
|
||||
|
||||
compare.controller('CompareCtrl', [ '$state', '$stateParams', '$scope', '$rootScope', '$location',
|
||||
'thServiceDomain', '$http', '$q', '$timeout', 'getSeriesSummary',
|
||||
function CompareCtrl($state, $stateParams, $scope, $rootScope, $location,
|
||||
thServiceDomain, $http, $q, $timeout, getSeriesSummary) {
|
||||
|
||||
function displayComparision() {
|
||||
//TODO: determine the dates of the two revisions and only grab what we need
|
||||
$scope.timeRange = 2592000; // last 30 days
|
||||
$scope.testList = [];
|
||||
$scope.platformList = [];
|
||||
|
||||
var signatureURL = thServiceDomain + '/api/project/' + $scope.originalProject +
|
||||
'/performance-data/0/get_performance_series_summary/?interval=' +
|
||||
$scope.timeRange;
|
||||
|
||||
$http.get(signatureURL).then(
|
||||
function(response) {
|
||||
var seriesList = [];
|
||||
|
||||
Object.keys(response.data).forEach(function(signature) {
|
||||
var seriesSummary = getSeriesSummary(signature,
|
||||
response.data[signature],
|
||||
optionCollectionMap,
|
||||
$stateParams.pgo,
|
||||
$stateParams.e10s);
|
||||
|
||||
if (seriesSummary != null && seriesSummary.signature !== undefined) {
|
||||
seriesList.push(seriesSummary);
|
||||
|
||||
if ($scope.platformList.indexOf(seriesSummary.platform) === -1) {
|
||||
$scope.platformList.push(seriesSummary.platform);
|
||||
}
|
||||
|
||||
if ($scope.testList.indexOf(seriesSummary.name) === -1) {
|
||||
$scope.testList.push(seriesSummary.name);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// find summary results for all tests/platforms for the original rev
|
||||
var signatureURL = thServiceDomain + '/api/project/' +
|
||||
$scope.originalProject + '/performance-data/0/' +
|
||||
'get_performance_data/?interval_seconds=' + $scope.timeRange;
|
||||
|
||||
// TODO: figure how how to reduce these maps
|
||||
var rawResultsMap = {};
|
||||
|
||||
$q.all(seriesList.map(function(series) {
|
||||
return $http.get(signatureURL + "&signatures=" + series.signature).then(function(response) {
|
||||
response.data.forEach(function(data) {
|
||||
rawResultsMap[data.series_signature] = calculateStats(data.blob, $scope.originalResultSetID);
|
||||
rawResultsMap[data.series_signature].name = series.name;
|
||||
rawResultsMap[data.series_signature].platform = series.platform;
|
||||
});
|
||||
});
|
||||
})).then(function () {
|
||||
// find summary results for all tests/platforms for the original rev
|
||||
var signatureURL = thServiceDomain + '/api/project/' +
|
||||
$scope.newProject + '/performance-data/0/' +
|
||||
'get_performance_data/?interval_seconds=' + $scope.timeRange;
|
||||
|
||||
//ok, now get the new revision
|
||||
var signatureListURL = thServiceDomain + '/api/project/' + $scope.newProject +
|
||||
'/performance-data/0/get_performance_series_summary/?interval=' +
|
||||
$scope.timeRange;
|
||||
|
||||
var newRawResultsMap = {};
|
||||
var newSeriesList = [];
|
||||
|
||||
$http.get(signatureListURL).then(function(response) {
|
||||
Object.keys(response.data).forEach(function(signature) {
|
||||
var seriesSummary = getSeriesSummary(signature,
|
||||
response.data[signature],
|
||||
optionCollectionMap,
|
||||
$stateParams.pgo,
|
||||
$stateParams.e10s);
|
||||
|
||||
if (seriesSummary != null && seriesSummary.signature !== undefined) {
|
||||
newSeriesList.push(seriesSummary);
|
||||
|
||||
if ($scope.platformList.indexOf(seriesSummary.platform) === -1) {
|
||||
$scope.platformList.push(seriesSummary.platform);
|
||||
}
|
||||
|
||||
if ($scope.testList.indexOf(seriesSummary.name) === -1) {
|
||||
$scope.testList.push(seriesSummary.name);
|
||||
}
|
||||
}
|
||||
});
|
||||
$scope.testList.sort();
|
||||
$scope.platformList.sort();
|
||||
|
||||
$q.all(newSeriesList.map(function(series) {
|
||||
return $http.get(signatureURL + "&signatures=" + series.signature).then(function(response) {
|
||||
response.data.forEach(function(data) {
|
||||
newRawResultsMap[data.series_signature] = calculateStats(data.blob, $scope.newResultSetID);
|
||||
newRawResultsMap[data.series_signature].name = series.name;
|
||||
newRawResultsMap[data.series_signature].platform = series.platform;
|
||||
});
|
||||
});
|
||||
})).then(function () {
|
||||
$scope.dataLoading = false;
|
||||
displayResults(rawResultsMap, newRawResultsMap);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
//TODO: put this into a generic library
|
||||
function calculateStats(perfData, resultSetID) {
|
||||
var geomeans = [];
|
||||
var total = 0;
|
||||
_.where(perfData, { result_set_id: resultSetID }).forEach(function(pdata) {
|
||||
geomeans.push(pdata.geomean);
|
||||
total += pdata.geomean;
|
||||
});
|
||||
|
||||
var avg = total / geomeans.length;
|
||||
var sigma = stddev(geomeans, avg);
|
||||
return {geomean: avg.toFixed(2), stddev: sigma.toFixed(2), runs: geomeans.length};
|
||||
}
|
||||
|
||||
//TODO: put this into a generic library
|
||||
function isReverseTest(testName) {
|
||||
var reverseTests = ['dromaeo_dom', 'dromaeo_css', 'v8_7', 'canvasmark'];
|
||||
var found = false;
|
||||
reverseTests.forEach(function(rt) {
|
||||
if (testName.indexOf(rt) >= 0) {
|
||||
found = true;
|
||||
}
|
||||
});
|
||||
return found;
|
||||
}
|
||||
|
||||
function displayResults(rawResultsMap, newRawResultsMap) {
|
||||
var counter = 0;
|
||||
var compareResultsMap = {};
|
||||
|
||||
$scope.testList.forEach(function(testName) {
|
||||
if (counter > 0 && compareResultsMap[(counter-1)].headerColumns==2) {
|
||||
counter--;
|
||||
}
|
||||
|
||||
//TODO: figure out a cleaner method for making the names a header row
|
||||
compareResultsMap[counter++] = {'name': testName.replace(' summary', ''),
|
||||
'isEmpty': true, 'isMinor': false, 'headerColumns': 2,
|
||||
'originalGeoMean': 'Old Rev', 'originalStddev': 'StdDev',
|
||||
'newGeoMean': 'New Rev', 'newStddev': 'StdDev',
|
||||
'delta': 'Delta', 'deltaPercentage': 'Delta'};
|
||||
|
||||
|
||||
$scope.platformList.forEach(function(platform) {
|
||||
var cmap = {'originalGeoMean': NaN, 'originalRuns': 0, 'originalStddev': NaN,
|
||||
'newGeoMean': NaN, 'newRuns': 0, 'newStddev': NaN, 'headerColumns': 1,
|
||||
'delta': NaN, 'deltaPercentage': NaN, 'isEmpty': false,
|
||||
'isRegression': false, 'isImprovement': false, 'isMinor': true};
|
||||
|
||||
var oldSig = _.find(Object.keys(rawResultsMap), function (sig) {
|
||||
return (rawResultsMap[sig].name == testName && rawResultsMap[sig].platform == platform)});
|
||||
var newSig = _.find(Object.keys(newRawResultsMap), function (sig) {
|
||||
return (newRawResultsMap[sig].name == testName && newRawResultsMap[sig].platform == platform)});
|
||||
|
||||
if (oldSig) {
|
||||
var originalData = rawResultsMap[oldSig];
|
||||
cmap.originalGeoMean = originalData.geomean;
|
||||
cmap.originalRuns = originalData.runs;
|
||||
cmap.originalStddev = originalData.stddev;
|
||||
cmap.originalStddevPct = ((originalData.stddev / originalData.geomean) * 100).toFixed(2);
|
||||
}
|
||||
if (newSig) {
|
||||
var newData = newRawResultsMap[newSig];
|
||||
cmap.newGeoMean = newData.geomean;
|
||||
cmap.newRuns = newData.runs;
|
||||
cmap.newStddev = newData.stddev;
|
||||
cmap.newStddevPct = ((newData.stddev / newData.geomean) * 100).toFixed(2);
|
||||
}
|
||||
|
||||
if ((cmap.originalRuns == 0 && cmap.newRuns == 0) ||
|
||||
(testName == 'tp5n summary opt')) {
|
||||
// We don't generate numbers for tp5n, just counters
|
||||
cmap.isEmpty = true;
|
||||
} else {
|
||||
cmap.delta = (cmap.newGeoMean - cmap.originalGeoMean).toFixed(2);
|
||||
cmap.deltaPercentage = (cmap.delta / cmap.originalGeoMean * 100).toFixed(2);
|
||||
if (cmap.deltaPercentage > 2.0) {
|
||||
cmap.isMinor = false;
|
||||
isReverseTest(testName) ? cmap.isImprovement = true : cmap.isRegression = true;
|
||||
} else if (cmap.deltaPercentage < -2.0) {
|
||||
cmap.isMinor = false;
|
||||
isReverseTest(testName) ? cmap.isRegression = true : cmap.isImprovement = true;
|
||||
}
|
||||
|
||||
//TODO: do we need zoom? can we have >1 highlighted revision?
|
||||
var originalSeries = encodeURIComponent(JSON.stringify(
|
||||
{ project: $scope.originalProject,
|
||||
signature: oldSig,
|
||||
visible: true}));
|
||||
|
||||
var newSeries = encodeURIComponent(JSON.stringify(
|
||||
{ project: $scope.newProject,
|
||||
signature: newSig,
|
||||
visible: true}));
|
||||
|
||||
var detailsLink = thServiceDomain + '/perf.html#/graphs?timerange=' +
|
||||
$scope.timeRange + '&series=' + newSeries;
|
||||
|
||||
if (oldSig != newSig) {
|
||||
detailsLink += '&series=' + originalSeries;
|
||||
}
|
||||
|
||||
detailsLink += '&highlightedRevision=' + $scope.newRevision;
|
||||
|
||||
cmap.detailsLink = detailsLink;
|
||||
cmap.name = platform;
|
||||
compareResultsMap[counter++] = cmap;
|
||||
}
|
||||
});
|
||||
});
|
||||
$scope.compareResults = Object.keys(compareResultsMap).map(function(k) {
|
||||
return compareResultsMap[k];
|
||||
});
|
||||
}
|
||||
|
||||
function verifyRevision(project, revision, rsid) {
|
||||
var uri = thServiceDomain + '/api/project/' + project +
|
||||
'/resultset/?format=json&full=false&with_jobs=false&revision=' +
|
||||
revision;
|
||||
|
||||
return $http.get(uri).then(function(response) {
|
||||
var results = response.data.results;
|
||||
if (results.length > 0) {
|
||||
|
||||
//TODO: this is a bit hacky to pass in 'original' as a text string
|
||||
if (rsid == 'original') {
|
||||
$scope.originalResultSetID = results[0].id;
|
||||
} else {
|
||||
$scope.newResultSetID = results[0].id;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function updateURL() {
|
||||
$state.transitionTo('compare', { 'originalProject': $scope.originalProject,
|
||||
'originalRevision': $scope.originalRevision,
|
||||
'newProject': $scope.newProject,
|
||||
'newRevision': $scope.newRevision},
|
||||
{location: true, inherit: true, notify: false, relative: $state.$current});
|
||||
}
|
||||
|
||||
var optionCollectionMap = {};
|
||||
$scope.dataLoading = true;
|
||||
|
||||
$http.get(thServiceDomain + '/api/optioncollectionhash').then(
|
||||
function(response) {
|
||||
response.data.forEach(function(dict) {
|
||||
optionCollectionMap[dict.option_collection_hash] =
|
||||
dict.options.map(function(option) {
|
||||
return option.name; }).join(" ");
|
||||
});
|
||||
}).then(function() {
|
||||
$stateParams.pgo = Boolean($stateParams.pgo);
|
||||
$stateParams.e10s = Boolean($stateParams.e10s);
|
||||
$scope.hideMinorChanges = Boolean($stateParams.hideMinorChanges);
|
||||
|
||||
// TODO: validate projects and revisions
|
||||
$scope.originalProject = $stateParams.originalProject;
|
||||
$scope.newProject = $stateParams.newProject;
|
||||
$scope.newRevision = $stateParams.newRevision;
|
||||
$scope.originalRevision = $stateParams.originalRevision;
|
||||
if (!$scope.originalProject ||
|
||||
!$scope.newProject ||
|
||||
!$scope.originalRevision ||
|
||||
!$scope.newRevision) {
|
||||
//TODO: get an error to the UI
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
verifyRevision($scope.originalProject, $scope.originalRevision, "original").then(function () {
|
||||
verifyRevision($scope.newProject, $scope.newRevision, "new").then(function () {
|
||||
$http.get(thServiceDomain + '/api/repository/').then(function(response) {
|
||||
$scope.projects = response.data;
|
||||
});
|
||||
});
|
||||
});
|
||||
displayComparision();
|
||||
});
|
||||
}]);
|
||||
|
||||
|
||||
compare.config(function($stateProvider, $urlRouterProvider) {
|
||||
$urlRouterProvider.deferIntercept(); // so we don't reload on url change
|
||||
|
||||
$stateProvider.state('compare', {
|
||||
templateUrl: 'partials/perf/comparectrl.html',
|
||||
url: '/compare?originalProject&originalRevision&newProject&newRevision&hideMinorChanges&e10s&pgo',
|
||||
controller: 'CompareCtrl'
|
||||
});
|
||||
|
||||
$urlRouterProvider.otherwise('/compare');
|
||||
})
|
||||
// define the interception
|
||||
.run(function ($rootScope, $urlRouter, $location, $state) {
|
||||
$rootScope.$on('$locationChangeSuccess', function(e, newUrl, oldUrl) {
|
||||
// Prevent $urlRouter's default handler from firing
|
||||
e.preventDefault();
|
||||
if ($state.current.name !== 'compare') {
|
||||
// here for first time, synchronize
|
||||
$urlRouter.sync();
|
||||
}
|
||||
});
|
||||
|
||||
// Configures $urlRouter's listener *after* custom listener
|
||||
$urlRouter.listen();
|
||||
})
|
||||
|
||||
|
|
@ -0,0 +1,103 @@
|
|||
<nav class="navbar navbar-default" role="navigation">
|
||||
<div class="container-fluid">
|
||||
<div class="navbar-header">
|
||||
<<<<<<< HEAD
|
||||
<<<<<<< HEAD
|
||||
<a class="navbar-brand" href="#">Perfherder Compare</a>
|
||||
=======
|
||||
<a class="navbar-brand" href="#">Perfherder Compare Talos</a>
|
||||
>>>>>>> initial work to get compare-talos stood up inside of perfherder
|
||||
=======
|
||||
<a class="navbar-brand" href="#">Perfherder Compare</a>
|
||||
>>>>>>> addressed review feedback: whitespace, blank lines, s/compare.js/compareperf.js/, cleaned up angular classes and extra <div>'s, reduced a forEach(..) call to a _.where(...) call, etc.
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<<<<<<< HEAD
|
||||
<<<<<<< HEAD
|
||||
<div class="container-fluid">
|
||||
<div id="datapoint-detail" ng-show="originalRevision && newRevision">
|
||||
<div ng-if="dataLoading">
|
||||
Loading all results, please wait a minute...
|
||||
<img src="img/dancing_cat.gif" />
|
||||
</div>
|
||||
<div id="subtest-summary" ng-if="!dataLoading">
|
||||
<h4>Compare all data for revision {{newProject}}: {{newRevision}} to {{originalProject}}: {{originalRevision}}</h4>
|
||||
<p class="help-block">Hover over each entry for more options.</p>
|
||||
<table class="table">
|
||||
<tbody>
|
||||
<tr ng-class="{'subtest-header': compareResult.headerColumns==2, 'subtest-empty': compareResult.isEmpty && !compareResult.headerColumns==2, 'subtest-empty': (hideMinorChanges && compareResult.isMinor)}" ng-repeat="compareResult in compareResults">
|
||||
<td colspan="{{compareResult.headerColumns}}">{{compareResult.name}}</td>
|
||||
<td ng-class="{'subtest-empty': compareResult.headerColumns==2}"><a ng-href="{{compareResult.detailsLink}}">Details</a></td>
|
||||
<td ng-attr-title="runs: {{compareResult.originalRuns}}">{{compareResult.originalGeoMean}}</td>
|
||||
<td>+/-{{compareResult.originalStddev}} ({{compareResult.originalStddevPct}}%)</td>
|
||||
<td ng-attr-title="runs: {{compareResult.newRuns}}">{{compareResult.newGeoMean}}</td>
|
||||
<td>+/-{{compareResult.newStddev}} ({{compareResult.newStddevPct}}%)</td>
|
||||
<td ng-class="{'subtest-regression': compareResult.isRegression, 'subtest-improvement': compareResult.isImprovement}">{{compareResult.delta}}</td>
|
||||
<td ng-class="{'subtest-regression': compareResult.isRegression, 'subtest-improvement': compareResult.isImprovement}">{{compareResult.deltaPercentage}}%</td>
|
||||
=======
|
||||
<div class="ph-horizontal-layout">
|
||||
<div id="revision-chooser">
|
||||
|
||||
</div>
|
||||
<div id="data-display">
|
||||
=======
|
||||
<div class="container-fluid">
|
||||
>>>>>>> addressed review feedback: whitespace, blank lines, s/compare.js/compareperf.js/, cleaned up angular classes and extra <div>'s, reduced a forEach(..) call to a _.where(...) call, etc.
|
||||
<div id="datapoint-detail" ng-show="originalRevision && newRevision">
|
||||
<div ng-if="dataLoading">
|
||||
Loading all results, please wait a minute...
|
||||
<img src="img/dancing_cat.gif" />
|
||||
</div>
|
||||
<div id="subtest-summary" ng-if="!dataLoading">
|
||||
<h4>Compare all data for revision {{newProject}}: {{newRevision}} to {{originalProject}}: {{originalRevision}}</h4>
|
||||
<p class="help-block">Hover over each entry for more options.</p>
|
||||
<table class="table">
|
||||
<tbody>
|
||||
<<<<<<< HEAD
|
||||
<tr ng-class="{'subtest-header': compareResult.isHeader, 'subtest-empty': compareResult.isEmpty && !compareResult.isHeader}" ng-repeat="compareResult in compareResults">
|
||||
<td><a ng-class="{'subtest-empty': compareResult.isHeader}" ng-href="{{compareResult.detailsLink}}">Details</a></td>
|
||||
<td>{{compareResult.name}}</td>
|
||||
<<<<<<< HEAD
|
||||
<td ng-attr-title="runs: {{compareResult.originalRuns}}">{{compareResult.originalGeoMean}}</td><td>{{compareResult.originalVariation}}</td>
|
||||
<td ng-attr-title="runs: {{compareResult.newRuns}}">{{compareResult.newGeoMean}}</td><td>{{compareResult.newVariation}}</td>
|
||||
<td ng-style="compareResult.type === 'regression' && {'background-color': 'red', 'color': 'white', 'font-weight': 'bold'} ||
|
||||
compareResult.type === 'improvement' && {'background-color': 'green', 'color': 'white', 'font-weight': 'bold'}">{{compareResult.delta}}</td>
|
||||
<td ng-style="compareResult.type === 'regression' && {'background-color': 'red', 'color': 'white', 'font-weight': 'bold'} ||
|
||||
compareResult.type === 'improvement' && {'background-color': 'green', 'color': 'white', 'font-weight': 'bold'}">{{compareResult.deltaPercentage}}</td>
|
||||
>>>>>>> initial work to get compare-talos stood up inside of perfherder
|
||||
=======
|
||||
=======
|
||||
<tr ng-class="{'subtest-header': compareResult.headerColumns==2, 'subtest-empty': compareResult.isEmpty && !compareResult.headerColumns==2, 'subtest-empty': (hideMinorChanges && compareResult.isMinor)}" ng-repeat="compareResult in compareResults">
|
||||
<td colspan="{{compareResult.headerColumns}}">{{compareResult.name}}</td>
|
||||
<td ng-class="{'subtest-empty': compareResult.headerColumns==2}"><a ng-href="{{compareResult.detailsLink}}">Details</a></td>
|
||||
>>>>>>> additional cleanup: details after name, header column for testname is colspan=2, support url param hideMinorChanges
|
||||
<td ng-attr-title="runs: {{compareResult.originalRuns}}">{{compareResult.originalGeoMean}}</td>
|
||||
<td>+/-{{compareResult.originalStddev}} ({{compareResult.originalStddevPct}}%)</td>
|
||||
<td ng-attr-title="runs: {{compareResult.newRuns}}">{{compareResult.newGeoMean}}</td>
|
||||
<td>+/-{{compareResult.newStddev}} ({{compareResult.newStddevPct}}%)</td>
|
||||
<<<<<<< HEAD
|
||||
<td ng-class="{'subtest-regression': compareResult.isRegression, 'subtest-improvement': compareResult.isImprovement, 'subtest-header': compareResult.isHeader}">{{compareResult.delta}}</td>
|
||||
<td ng-class="{'subtest-regression': compareResult.isRegression, 'subtest-improvement': compareResult.isImprovement, 'subtest-header': compareResult.isHeader}">{{compareResult.deltaPercentage}}%</td>
|
||||
>>>>>>> addressed all feedback except a common library, a few TODO items left in the code
|
||||
=======
|
||||
<td ng-class="{'subtest-regression': compareResult.isRegression, 'subtest-improvement': compareResult.isImprovement}">{{compareResult.delta}}</td>
|
||||
<td ng-class="{'subtest-regression': compareResult.isRegression, 'subtest-improvement': compareResult.isImprovement}">{{compareResult.deltaPercentage}}%</td>
|
||||
>>>>>>> additional cleanup: details after name, header column for testname is colspan=2, support url param hideMinorChanges
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<<<<<<< HEAD
|
||||
<<<<<<< HEAD
|
||||
=======
|
||||
</div>
|
||||
<div class="graph-right-padding"></div>
|
||||
>>>>>>> initial work to get compare-talos stood up inside of perfherder
|
||||
=======
|
||||
>>>>>>> addressed review feedback: whitespace, blank lines, s/compare.js/compareperf.js/, cleaned up angular classes and extra <div>'s, reduced a forEach(..) call to a _.where(...) call, etc.
|
||||
</div>
|
||||
|
||||
|
Загрузка…
Ссылка в новой задаче