Changeset 179710 in webkit


Ignore:
Timestamp:
Feb 5, 2015 2:34:13 PM (9 years ago)
Author:
rniwa@webkit.org
Message:

New perf dashboard should compare results to baseline and target
https://bugs.webkit.org/show_bug.cgi?id=141286

Reviewed by Chris Dumez.

Compare the selected value against baseline and target values as done in v1. e.g. "5% below target"
Also use d3.format to format the selected value to show four significant figures.

  • public/v2/app.js:

(App.Pane.searchCommit):
(App.Pane._fetch): Create time series here via createChartData so that _computeStatus can use them
to compute the status text without having to recreate them.
(App.createChartData): Added.
(App.PaneController._updateDetails): Use 3d.format on current and old values.
(App.PaneController._computeStatus): Added. Computes the status text.
(App.PaneController._relativeDifferentToLaterPointInTimeSeries): Added.
(App.AnalysisTaskController._fetchedManifest): Use createChartData as done in App.Pane._fetch. Also
format the values using chartData.formatter.

  • public/v2/chart-pane.css: Enlarge the status text. Show the status text in red if it's worse than

the baseline and in blue if it's better than the target.

  • public/v2/data.js:

(TimeSeries.prototype.findPointAfterTime): Added.

  • public/v2/index.html: Added a new tbody for the status text and the selected value. Also fixed

the bug that we were not showing the old value's unit.

  • public/v2/interactive-chart.js:

(App.InteractiveChartComponent._constructGraphIfPossible): Use chartData.formatter. Also cleaned up
the code to show the baseline and the target lines.

  • public/v2/manifest.js:

(App.Manifest.fetchRunsWithPlatformAndMetric): Added smallerIsBetter.

Location:
trunk/Websites/perf.webkit.org
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • trunk/Websites/perf.webkit.org/ChangeLog

    r179686 r179710  
     12015-02-05  Ryosuke Niwa  <rniwa@webkit.org>
     2
     3        New perf dashboard should compare results to baseline and target
     4        https://bugs.webkit.org/show_bug.cgi?id=141286
     5
     6        Reviewed by Chris Dumez.
     7
     8        Compare the selected value against baseline and target values as done in v1. e.g. "5% below target"
     9        Also use d3.format to format the selected value to show four significant figures.
     10
     11        * public/v2/app.js:
     12        (App.Pane.searchCommit):
     13        (App.Pane._fetch): Create time series here via createChartData so that _computeStatus can use them
     14        to compute the status text without having to recreate them.
     15        (App.createChartData): Added.
     16        (App.PaneController._updateDetails): Use 3d.format on current and old values.
     17        (App.PaneController._computeStatus): Added. Computes the status text.
     18        (App.PaneController._relativeDifferentToLaterPointInTimeSeries): Added.
     19        (App.AnalysisTaskController._fetchedManifest): Use createChartData as done in App.Pane._fetch. Also
     20        format the values using chartData.formatter.
     21
     22        * public/v2/chart-pane.css: Enlarge the status text. Show the status text in red if it's worse than
     23        the baseline and in blue if it's better than the target.
     24
     25        * public/v2/data.js:
     26        (TimeSeries.prototype.findPointAfterTime): Added.
     27
     28        * public/v2/index.html: Added a new tbody for the status text and the selected value. Also fixed
     29        the bug that we were not showing the old value's unit.
     30
     31        * public/v2/interactive-chart.js:
     32        (App.InteractiveChartComponent._constructGraphIfPossible): Use chartData.formatter. Also cleaned up
     33        the code to show the baseline and the target lines.
     34
     35        * public/v2/manifest.js:
     36        (App.Manifest.fetchRunsWithPlatformAndMetric): Added smallerIsBetter.
     37
    1382015-02-05  Ryosuke Niwa  <rniwa@webkit.org>
    239
  • trunk/Websites/perf.webkit.org/public/v2/app.js

    r179686 r179710  
    282282            if (self.isDestroyed || !self.get('chartData') || !commits.length)
    283283                return;
    284             var currentRuns = self.get('chartData').current.timeSeriesByCommitTime().series();
     284            var currentRuns = self.get('chartData').current.series();
    285285            if (!currentRuns.length)
    286286                return;
     
    330330                self.set('platform', result.platform);
    331331                self.set('metric', result.metric);
    332                 self.set('chartData', result.runs);
     332                self.set('chartData', App.createChartData(result));
    333333            }, function (result) {
    334334                if (!result || typeof(result) === "string")
     
    365365    }
    366366});
     367
     368App.createChartData = function (data)
     369{
     370    var runs = data.runs;
     371    return {
     372        current: runs.current.timeSeriesByCommitTime(),
     373        baseline: runs.baseline ? runs.baseline.timeSeriesByCommitTime() : null,
     374        target: runs.target ? runs.target.timeSeriesByCommitTime() : null,
     375        unit: data.unit,
     376        formatter: data.useSI ? d3.format('.4s') : d3.format('.4g'),
     377        smallerIsBetter: data.smallerIsBetter,
     378    };
     379}
    367380
    368381App.encodePrettifiedJSON = function (plain)
     
    750763        }
    751764
     765        var chartData = this.get('chartData');
    752766        this.set('details', Ember.Object.create({
    753             currentValue: currentMeasurement.mean().toFixed(2),
    754             oldValue: oldMeasurement && selectedPoints ? oldMeasurement.mean().toFixed(2) : null,
     767            status: this._computeStatus(currentPoint),
     768            currentValue: chartData.formatter(currentMeasurement.mean()),
     769            oldValue: oldMeasurement && selectedPoints ? chartData.formatter(oldMeasurement.mean()) : null,
    755770            buildNumber: buildNumber,
    756771            buildURL: buildURL,
     
    765780        this.set('cannotAnalyze', !this.get('newAnalysisTaskName') || !points || points.length < 2);
    766781    }.observes('newAnalysisTaskName'),
     782    _computeStatus: function (currentPoint)
     783    {
     784        var chartData = this.get('chartData');
     785
     786        var diffFromBaseline = this._relativeDifferentToLaterPointInTimeSeries(currentPoint, chartData.baseline);
     787        var diffFromTarget = this._relativeDifferentToLaterPointInTimeSeries(currentPoint, chartData.target);
     788
     789        var label = '';
     790        var className = '';
     791        var formatter = d3.format('.3p');
     792
     793        var smallerIsBetter = chartData.smallerIsBetter;
     794        if (diffFromBaseline !== undefined && diffFromBaseline > 0 == smallerIsBetter) {
     795            label = formatter(Math.abs(diffFromBaseline)) + ' ' + (smallerIsBetter ? 'above' : 'below') + ' baseline';
     796            className = 'worse';
     797        } else if (diffFromTarget !== undefined && diffFromTarget < 0 == smallerIsBetter) {
     798            label = formatter(Math.abs(diffFromTarget)) + ' ' + (smallerIsBetter ? 'below' : 'above') + ' target';
     799            className = 'better';
     800        } else if (diffFromTarget !== undefined)
     801            label = formatter(Math.abs(diffFromTarget)) + ' until target';
     802
     803        return {className: className, label: label};
     804    },
     805    _relativeDifferentToLaterPointInTimeSeries: function (currentPoint, timeSeries)
     806    {
     807        if (!currentPoint || !timeSeries)
     808            return undefined;
     809       
     810        var referencePoint = timeSeries.findPointAfterTime(currentPoint.time);
     811        if (!referencePoint)
     812            return undefined;
     813
     814        return (currentPoint.value - referencePoint.value) / referencePoint.value;
     815    }
    767816});
    768817
     
    836885        highlightedItems[end.measurement.id()] = true;
    837886
     887        var chartData = App.createChartData(data);
    838888        var formatedPoints = currentTimeSeries.seriesBetweenPoints(start, end).map(function (point, index) {
    839889            return {
     
    841891                measurement: point.measurement,
    842892                label: 'Point ' + (index + 1),
    843                 value: point.value + (runs.unit ? ' ' + runs.unit : ''),
     893                value: chartData.formatter(point.value) + (data.unit ? ' ' + data.unit : ''),
    844894            };
    845895        });
    846896
    847897        var margin = (end.time - start.time) * 0.1;
    848         this.set('chartData', runs);
     898        this.set('chartData', chartData);
    849899        this.set('chartDomain', [start.time - margin, +end.time + margin]);
    850900        this.set('highlightedItems', highlightedItems);
  • trunk/Websites/perf.webkit.org/public/v2/chart-pane.css

    r179611 r179710  
    211211    word-break: break-word;
    212212    border-top: solid 1px #ccc;
     213    border-bottom: solid 1px #ccc;
    213214    padding: 0.2rem;
    214215}
     
    233234}
    234235
     236.chart-pane .details-table .status th {
     237    visibility: hidden;
     238}
     239
     240.chart-pane .details-table .status td {
     241    font-size: 1rem;
     242}
     243
    235244.chart-pane .chart {
    236245    height: 100%;
     
    258267}
    259268
    260 .chart .commit-time-line {
    261     stroke: #999;
    262 }
    263 
    264269.chart .dot {
    265270    fill: #666;
     
    273278}
    274279
    275 .chart path.area.baseline {
     280.chart path.current {
     281    stroke: #999;
     282}
     283
     284.chart path.baseline {
    276285    stroke: #f66;
    277     fill: #fdd;
    278     opacity: 0.4;
    279 }
    280 
    281 .chart path.area.target {
     286}
     287.chart-pane .status .worse {
     288    color: #c33;
     289}
     290
     291.chart path.target {
    282292    stroke: #66f;
    283     fill: #ddf;
    284     opacity: 0.4;
     293}
     294.chart-pane .status .better {
     295    color: #33c;
    285296}
    286297
  • trunk/Websites/perf.webkit.org/public/v2/data.js

    r179591 r179710  
    361361}
    362362
     363TimeSeries.prototype.findPointAfterTime = function (time)
     364{
     365    return this._series.find(function (point) { return point.time >= time; });
     366}
     367
    363368TimeSeries.prototype.seriesBetweenPoints = function (startPoint, endPoint)
    364369{
  • trunk/Websites/perf.webkit.org/public/v2/index.html

    r179661 r179710  
    255255            {{/each}}
    256256            </tbody>
    257             <tr><th>Current</th><td>{{details.currentValue}} {{chartData.unit}}
    258             {{#if details.oldValue}}
    259                 (from {{details.oldValue}})
    260             {{/if}}</td></tr>
     257            <tbody class="status">
     258                <tr>
     259                    <th>Current</th>
     260                    <td>
     261                        {{details.currentValue}} {{chartData.unit}}
     262                        {{#if details.oldValue}}
     263                            (from {{details.oldValue}} {{chartData.unit}})
     264                        {{/if}}
     265                        {{#if details.status.label}}
     266                            <br>
     267                            <span {{bind-attr class=details.status.className}}>{{details.status.label}}</span>
     268                        {{/if}}
     269                    </td>
     270                </tr>
     271            </tbody>
    261272            {{#if details.buildNumber}}
    262273                <tr>
  • trunk/Websites/perf.webkit.org/public/v2/interactive-chart.js

    r179623 r179710  
    6767
    6868        if (this.get('showYAxis')) {
    69             this._yAxis = d3.svg.axis().scale(this._y).orient("left").ticks(6).tickFormat(
    70                 chartData.useSI ? d3.format("s") : d3.format(".3g"));
     69            this._yAxis = d3.svg.axis().scale(this._y).orient("left").ticks(6).tickFormat(chartData.formatter);
    7170            this._yAxisLabels = svg.append("g")
    7271                .attr("class", "y axis");
     
    101100        this._highlights = null;
    102101
    103         this._currentTimeSeries = chartData.current.timeSeriesByCommitTime();
     102        this._currentTimeSeries = chartData.current;
    104103        this._currentTimeSeriesData = this._currentTimeSeries.series();
    105         this._baselineTimeSeries = chartData.baseline ? chartData.baseline.timeSeriesByCommitTime() : null;
    106         this._targetTimeSeries = chartData.target ? chartData.target.timeSeriesByCommitTime() : null;
     104        this._baselineTimeSeries = chartData.baseline;
     105        this._targetTimeSeries = chartData.target;
    107106
    108107        this._yAxisUnit = chartData.unit;
    109108
    110         var minMax = this._minMaxForAllTimeSeries();
    111         var smallEnoughValue = minMax[0] - (minMax[1] - minMax[0]) * 10;
    112         var largeEnoughValue = minMax[1] + (minMax[1] - minMax[0]) * 10;
    113 
    114         // FIXME: Flip the sides based on smallerIsBetter-ness.
    115109        if (this._baselineTimeSeries) {
    116             var data = this._baselineTimeSeries.series();
    117             this._areas.push(this._clippedContainer
     110            this._paths.push(this._clippedContainer
    118111                .append("path")
    119                 .datum(data.map(function (point) { return {time: point.time, value: point.value, interval: point.interval ? point.interval : [point.value, largeEnoughValue]}; }))
    120                 .attr("class", "area baseline"));
     112                .datum(this._baselineTimeSeries.series())
     113                .attr("class", "baseline"));
    121114        }
    122115        if (this._targetTimeSeries) {
    123             var data = this._targetTimeSeries.series();
    124             this._areas.push(this._clippedContainer
     116            this._paths.push(this._clippedContainer
    125117                .append("path")
    126                 .datum(data.map(function (point) { return {time: point.time, value: point.value, interval: point.interval ? point.interval : [smallEnoughValue, point.value]}; }))
    127                 .attr("class", "area target"));
     118                .datum(this._targetTimeSeries.series())
     119                .attr("class", "target"));
    128120        }
    129121
     
    136128            .append("path")
    137129            .datum(this._currentTimeSeriesData)
    138             .attr("class", "commit-time-line"));
     130            .attr("class", "current"));
    139131
    140132        this._dots.push(this._clippedContainer
  • trunk/Websites/perf.webkit.org/public/v2/manifest.js

    r179647 r179710  
    282282                'Allocations': 'bytes'
    283283            }[suffix];
    284 
    285             // FIXME: Include this information in JSON and process it in RunsData.fetchRuns
    286             runs.unit = unit;
    287             runs.useSI = unit == 'bytes';
    288 
    289             return {platform: platform, metric: metric, runs: runs};
     284            var smallerIsBetter = unit != 'fps' && unit != '/s'; // Assume smaller is better for unit-less metrics.
     285
     286            return {platform: platform, metric: metric, runs: runs, unit: unit, useSI: unit == 'bytes', smallerIsBetter: smallerIsBetter};
    290287        });
    291288    },
Note: See TracChangeset for help on using the changeset viewer.