Changeset 179913 in webkit


Ignore:
Timestamp:
Feb 10, 2015 6:45:43 PM (9 years ago)
Author:
rniwa@webkit.org
Message:

New perf dashboard shouldn't always show outliners
https://bugs.webkit.org/show_bug.cgi?id=141445

Reviewed by Chris Dumez.

Use the simple moving average with an average difference envelope to compute the y-axis range to show
to avoid expanding it spuriously to show one off outlier.

  • public/v2/app.js:

(App.Pane): Don't show the full y-axis range by default.
(App.Pane._computeChartData): Use the first strategies for the moving average and the enveloping if
one is not specified by the user but without showing them in the charts.
(App.Pane._computeMovingAverage): Takes moving average and enveloping strategies as arguments instead
of retrieving via chosenMovingAverageStrategy and chosenEnvelopingStrategy.

(App.ChartsController._parsePaneList): Added showFullYAxis as a query string argument to each pane.
(App.ChartsController._serializePaneList): Ditto.

  • public/v2/chart-pane.css: Added a CSS rule for when y-axis is clickable.
  • public/v2/index.html: Pass in showFullYAxis as an argument to the main interactive chart.
  • public/v2/interactive-chart.js:

(App.InteractiveChartComponent._constructGraphIfPossible): Add an event listener on y-axis labels when
the chart is interactive so that toggle showFullYAxis. Also hide the moving average and/or the envelope
if they are not specified by the user (i.e. only used to adjust y-axis range).
(App.InteractiveChartComponent._updateDomain): Don't exit early if y-axis domains are different even if
x-axis domain remained the same. Without this change, the charts would never redraw.
(App.InteractiveChartComponent._minMaxForAllTimeSeries): Use the moving average instead of the current
time series to compute the y-axis range if showFullYAxis is false. When showFullYAxis is true, expand
y-axis all the way down to 0 or the minimum value in the current time series whichever is smaller.

  • public/v2/js/statistics.js:

(Statistics.MovingAverageStrategies): Use a wider window in Simple Moving Average by default.

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

Legend:

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

    r179881 r179913  
     12015-02-10  Ryosuke Niwa  <rniwa@webkit.org>
     2
     3        New perf dashboard shouldn't always show outliners
     4        https://bugs.webkit.org/show_bug.cgi?id=141445
     5
     6        Reviewed by Chris Dumez.
     7
     8        Use the simple moving average with an average difference envelope to compute the y-axis range to show
     9        to avoid expanding it spuriously to show one off outlier.
     10
     11        * public/v2/app.js:
     12        (App.Pane): Don't show the full y-axis range by default.
     13        (App.Pane._computeChartData): Use the first strategies for the moving average and the enveloping if
     14        one is not specified by the user but without showing them in the charts.
     15        (App.Pane._computeMovingAverage): Takes moving average and enveloping strategies as arguments instead
     16        of retrieving via chosenMovingAverageStrategy and chosenEnvelopingStrategy.
     17
     18        (App.ChartsController._parsePaneList): Added showFullYAxis as a query string argument to each pane.
     19        (App.ChartsController._serializePaneList): Ditto.
     20
     21        * public/v2/chart-pane.css: Added a CSS rule for when y-axis is clickable.
     22
     23        * public/v2/index.html: Pass in showFullYAxis as an argument to the main interactive chart.
     24
     25        * public/v2/interactive-chart.js:
     26        (App.InteractiveChartComponent._constructGraphIfPossible): Add an event listener on y-axis labels when
     27        the chart is interactive so that toggle showFullYAxis. Also hide the moving average and/or the envelope
     28        if they are not specified by the user (i.e. only used to adjust y-axis range).
     29        (App.InteractiveChartComponent._updateDomain): Don't exit early if y-axis domains are different even if
     30        x-axis domain remained the same. Without this change, the charts would never redraw.
     31        (App.InteractiveChartComponent._minMaxForAllTimeSeries): Use the moving average instead of the current
     32        time series to compute the y-axis range if showFullYAxis is false. When showFullYAxis is true, expand
     33        y-axis all the way down to 0 or the minimum value in the current time series whichever is smaller.
     34
     35        * public/v2/js/statistics.js:
     36        (Statistics.MovingAverageStrategies): Use a wider window in Simple Moving Average by default.
     37
    1382015-02-10  Ryosuke Niwa  <rniwa@webkit.org>
    239
  • trunk/Websites/perf.webkit.org/public/v2/app.js

    r179881 r179913  
    298298    metric: null,
    299299    selectedItem: null,
     300    showFullYAxis: false,
    300301    searchCommit: function (repository, keyword) {
    301302        var self = this;
     
    477478
    478479        var chartData = App.createChartData(this.get('fetchedData'));
    479         chartData.movingAverage = this._computeMovingAverage(chartData);
    480 
    481         this._updateStrategyConfigIfNeeded(this.get('chosenMovingAverageStrategy'), 'movingAverageConfig');
    482         this._updateStrategyConfigIfNeeded(this.get('chosenEnvelopingStrategy'), 'envelopingConfig');
     480
     481        var movingAverageStrategy = this.get('chosenMovingAverageStrategy');
     482        this._updateStrategyConfigIfNeeded(movingAverageStrategy, 'movingAverageConfig');
     483
     484        var envelopingStrategy = this.get('chosenEnvelopingStrategy');
     485        this._updateStrategyConfigIfNeeded(envelopingStrategy, 'envelopingConfig');
     486
     487        if (!movingAverageStrategy || !movingAverageStrategy.execute) {
     488            movingAverageStrategy = Statistics.MovingAverageStrategies[0];
     489            chartData.hideMovingAverage = true;
     490        }
     491        if (!envelopingStrategy || !envelopingStrategy.execute) {
     492            envelopingStrategy = Statistics.EnvelopingStrategies[0];
     493            chartData.hideEnvelope = true;
     494        }
     495
     496        chartData.movingAverage = this._computeMovingAverage(chartData, movingAverageStrategy, envelopingStrategy);
    483497
    484498        this.set('chartData', chartData);
    485499    }.observes('chosenMovingAverageStrategy', 'chosenMovingAverageStrategy.parameterList.@each.value',
    486500        'chosenEnvelopingStrategy', 'chosenEnvelopingStrategy.parameterList.@each.value'),
    487     _computeMovingAverage: function (chartData)
     501    _computeMovingAverage: function (chartData, movingAverageStrategy, envelopingStrategy)
    488502    {
    489503        var currentTimeSeriesData = chartData.current.series();
    490         var movingAverageStrategy = this.get('chosenMovingAverageStrategy');
    491         if (!movingAverageStrategy || !movingAverageStrategy.execute)
    492             return null;
    493 
    494504        var movingAverageValues = this._executeStrategy(movingAverageStrategy, currentTimeSeriesData);
    495505        if (!movingAverageValues)
    496506            return null;
    497507
    498         var envelopeDelta = null;
    499         var envelopingStrategy = this.get('chosenEnvelopingStrategy');
    500         if (envelopingStrategy && envelopingStrategy.execute)
    501             envelopeDelta = this._executeStrategy(envelopingStrategy, currentTimeSeriesData, [movingAverageValues]);
    502        
     508        var envelopeDelta = this._executeStrategy(envelopingStrategy, currentTimeSeriesData, [movingAverageValues]);
     509
    503510        return new TimeSeries(currentTimeSeriesData.map(function (point, index) {
    504511            var value = movingAverageValues[index];
     
    672679                selectedItem: selectedItem,
    673680                timeRange: timeRange,
    674                 movingAverageConfig: paneInfo[3],
    675                 envelopingConfig: paneInfo[4],
     681                showFullYAxis: paneInfo[3],
     682                movingAverageConfig: paneInfo[4],
     683                envelopingConfig: paneInfo[5],
    676684            });
    677685        });
     
    688696                pane.get('metricId'),
    689697                pane.get('timeRange') ? pane.get('timeRange').map(function (date) { return date.getTime() }) : pane.get('selectedItem'),
     698                pane.get('showFullYAxis'),
    690699                pane.get('movingAverageConfig'),
    691700                pane.get('envelopingConfig'),
     
    698707        Ember.run.debounce(this, '_updateQueryString', 1000);
    699708    }.observes('sharedZoom', 'panes.@each.platform', 'panes.@each.metric', 'panes.@each.selectedItem', 'panes.@each.timeRange',
    700         'panes.@each.movingAverageConfig', 'panes.@each.envelopingConfig'),
     709        'panes.@each.showFullYAxis', 'panes.@each.movingAverageConfig', 'panes.@each.envelopingConfig'),
    701710
    702711    _updateQueryString: function ()
  • trunk/Websites/perf.webkit.org/public/v2/chart-pane.css

    r179878 r179913  
    443443}
    444444
     445.chart .axis.interactive text {
     446    cursor: pointer;
     447}
     448
    445449.chart .rangeBar {
    446450    display: block;
  • trunk/Websites/perf.webkit.org/public/v2/index.html

    r179878 r179913  
    178178                            selectedPoints=selectedPoints
    179179                            markedPoints=markedPoints
     180                            showFullYAxis=showFullYAxis
    180181                            zoom="zoomed"}}
    181182                    {{else}}
  • trunk/Websites/perf.webkit.org/public/v2/interactive-chart.js

    r179878 r179913  
    7777        }
    7878
     79        var isInteractive = this.get('interactive');
    7980        if (this.get('showYAxis')) {
    8081            this._yAxis = d3.svg.axis().scale(this._y).orient("left").ticks(6).tickFormat(chartData.formatter);
    81             this._yAxisLabels = svg.append("g")
    82                 .attr("class", "y axis");
     82           
     83            this._yAxisLabels = svg.append('g').attr('class', 'y axis' + (isInteractive ? ' interactive' : ''));
     84            if (isInteractive) {
     85                var self = this;
     86                this._yAxisLabels.on('click', function () { self.toggleProperty('showFullYAxis'); });
     87            }
    8388        }
    8489
     
    124129        }
    125130
    126         var foregroundClass = this._movingAverageTimeSeries ? '' : ' foreground';
     131        var movingAverageIsVisible = this._movingAverageTimeSeries && !chartData.hideMovingAverage;
     132        var foregroundClass = movingAverageIsVisible ? '' : ' foreground';
    127133        this._areas.push(this._clippedContainer
    128134            .append("path")
     
    142148                .attr("r", this.get('chartPointRadius') || 1));
    143149
    144         if (this._movingAverageTimeSeries) {
     150        if (movingAverageIsVisible) {
    145151            this._paths.push(this._clippedContainer
    146152                .append("path")
    147153                .datum(this._movingAverageTimeSeries.series())
    148154                .attr("class", "movingAverage"));
    149             this._areas.push(this._clippedContainer
    150                 .append("path")
    151                 .datum(this._movingAverageTimeSeries.series())
    152                 .attr("class", "envelope"));
    153         }
    154 
    155         if (this.get('interactive')) {
     155
     156            if (!chartData.hideEnvelope) {
     157                this._areas.push(this._clippedContainer
     158                    .append("path")
     159                    .datum(this._movingAverageTimeSeries.series())
     160                    .attr("class", "envelope"));
     161            }
     162        }
     163
     164        if (isInteractive) {
    156165            this._currentItemLine = this._clippedContainer
    157166                .append("line")
     
    194203        if (!xDomain)
    195204            xDomain = intrinsicXDomain;
    196         var currentDomain = this._x.domain();
    197         if (currentDomain && App.domainsAreEqual(currentDomain, xDomain))
     205        var yDomain = this._computeYAxisDomain(xDomain[0], xDomain[1]);
     206
     207        var currentXDomain = this._x.domain();
     208        var currentYDomain = this._y.domain();
     209        if (currentXDomain && App.domainsAreEqual(currentXDomain, xDomain)
     210            && currentYDomain && App.domainsAreEqual(currentYDomain, yDomain))
    198211            return currentDomain;
    199212
    200         var yDomain = this._computeYAxisDomain(xDomain[0], xDomain[1]);
    201213        this._x.domain(xDomain);
    202214        this._y.domain(yDomain);
     
    340352    _minMaxForAllTimeSeries: function (startTime, endTime)
    341353    {
    342         var currentRange = this._currentTimeSeries.minMaxForTimeRange(startTime, endTime);
     354        var shouldShowFullYAxis = this.get('showFullYAxis');
     355        var mainTimeSeries = this._movingAverageTimeSeries && !shouldShowFullYAxis ? this._movingAverageTimeSeries : this._currentTimeSeries;
     356        var currentRange = mainTimeSeries.minMaxForTimeRange(startTime, endTime);
     357        if (shouldShowFullYAxis)
     358            currentRange[0] = Math.min(0, currentRange[0]);
     359
    343360        var baselineRange = this._baselineTimeSeries ? this._baselineTimeSeries.minMaxForTimeRange(startTime, endTime) : [Number.MAX_VALUE, Number.MIN_VALUE];
    344361        var targetRange = this._targetTimeSeries ? this._targetTimeSeries.minMaxForTimeRange(startTime, endTime) : [Number.MAX_VALUE, Number.MIN_VALUE];
    345         var movingAverageRange = this._movingAverageTimeSeries ? this._movingAverageTimeSeries.minMaxForTimeRange(startTime, endTime) : [Number.MAX_VALUE, Number.MIN_VALUE];
    346362        return [
    347             Math.min(currentRange[0], baselineRange[0], targetRange[0], movingAverageRange[0]),
    348             Math.max(currentRange[1], baselineRange[1], targetRange[1], movingAverageRange[1]),
     363            Math.min(currentRange[0], baselineRange[0], targetRange[0]),
     364            Math.max(currentRange[1], baselineRange[1], targetRange[1]),
    349365        ];
    350366    },
     
    362378
    363379        this._relayoutDataAndAxes(selection);
    364     }.observes('domain'),
     380    }.observes('domain', 'showFullYAxis'),
    365381    _selectionChanged: function ()
    366382    {
  • trunk/Websites/perf.webkit.org/public/v2/js/statistics.js

    r179878 r179913  
    105105            label: 'Simple Moving Average',
    106106            parameterList: [
    107                 {label: "Backward window size", value: 5, min: 2, step: 1},
    108                 {label: "Forward window size", value: 3, min: 0, step: 1}
     107                {label: "Backward window size", value: 8, min: 2, step: 1},
     108                {label: "Forward window size", value: 4, min: 0, step: 1}
    109109            ],
    110110            execute: function (backwardWindowSize, forwardWindowSize, values) {
Note: See TracChangeset for help on using the changeset viewer.