https://bugs.webkit.org/show_bug.cgi?id=141487
Reviewed by Chris Dumez.
Revise the y-axis range adjustment algorithm in r179913. Instead of showing the entire moving average,
show the current time series excluding points in the series outside the moving average envelope.
* public/v2/app.js:
(App.Pane._computeChartData): Don't deal with missing moving average or enveloping strategy here.
(App.Pane._computeMovingAverageAndOutliers): Set isOutliner to true on all data points in the current
time series if the point lies outside the moving average envelope. Don't expose the moving average or
the envelope computed for this purpose if they're not set by the user.
* public/v2/data.js:
(TimeSeries.prototype.minMaxForTimeRange): Takes a boolean argument, ignoreOutlier. When the flag is set
to true, min/max computation will ignore any point in the series with non-falsy "isOutliner" property.
* public/v2/interactive-chart.js:
(App.InteractiveChartComponent._constructGraphIfPossible): Unsupport hideMovingAverage and hideEnvelope.
(App.InteractiveChartComponent._computeYAxisDomain): Removed the commented out code. Also moved the code
to deal with showFullYAxis here.
(App.InteractiveChartComponent._minMaxForAllTimeSeries): Rewrote the code. Takes ignoreOutliners as an
argument instead of directly inspecting showFullYAxis.
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@179965
268f45cc-cd09-0410-ab3c-
d52691b4dbfc
+2015-02-11 Ryosuke Niwa <rniwa@webkit.org>
+
+ New perf dashboard shows too much space around interesting data points
+ https://bugs.webkit.org/show_bug.cgi?id=141487
+
+ Reviewed by Chris Dumez.
+
+ Revise the y-axis range adjustment algorithm in r179913. Instead of showing the entire moving average,
+ show the current time series excluding points in the series outside the moving average envelope.
+
+ * public/v2/app.js:
+ (App.Pane._computeChartData): Don't deal with missing moving average or enveloping strategy here.
+ (App.Pane._computeMovingAverageAndOutliers): Set isOutliner to true on all data points in the current
+ time series if the point lies outside the moving average envelope. Don't expose the moving average or
+ the envelope computed for this purpose if they're not set by the user.
+
+ * public/v2/data.js:
+ (TimeSeries.prototype.minMaxForTimeRange): Takes a boolean argument, ignoreOutlier. When the flag is set
+ to true, min/max computation will ignore any point in the series with non-falsy "isOutliner" property.
+
+ * public/v2/interactive-chart.js:
+ (App.InteractiveChartComponent._constructGraphIfPossible): Unsupport hideMovingAverage and hideEnvelope.
+ (App.InteractiveChartComponent._computeYAxisDomain): Removed the commented out code. Also moved the code
+ to deal with showFullYAxis here.
+ (App.InteractiveChartComponent._minMaxForAllTimeSeries): Rewrote the code. Takes ignoreOutliners as an
+ argument instead of directly inspecting showFullYAxis.
+
2015-02-10 Ryosuke Niwa <rniwa@webkit.org>
New perf dashboard shouldn't always show outliners
var envelopingStrategy = this.get('chosenEnvelopingStrategy');
this._updateStrategyConfigIfNeeded(envelopingStrategy, 'envelopingConfig');
- if (!movingAverageStrategy || !movingAverageStrategy.execute) {
- movingAverageStrategy = Statistics.MovingAverageStrategies[0];
- chartData.hideMovingAverage = true;
- }
- if (!envelopingStrategy || !envelopingStrategy.execute) {
- envelopingStrategy = Statistics.EnvelopingStrategies[0];
- chartData.hideEnvelope = true;
- }
-
- chartData.movingAverage = this._computeMovingAverage(chartData, movingAverageStrategy, envelopingStrategy);
+ chartData.movingAverage = this._computeMovingAverageAndOutliers(chartData, movingAverageStrategy, envelopingStrategy);
this.set('chartData', chartData);
}.observes('chosenMovingAverageStrategy', 'chosenMovingAverageStrategy.parameterList.@each.value',
'chosenEnvelopingStrategy', 'chosenEnvelopingStrategy.parameterList.@each.value'),
- _computeMovingAverage: function (chartData, movingAverageStrategy, envelopingStrategy)
+ _computeMovingAverageAndOutliers: function (chartData, movingAverageStrategy, envelopingStrategy)
{
var currentTimeSeriesData = chartData.current.series();
- var movingAverageValues = this._executeStrategy(movingAverageStrategy, currentTimeSeriesData);
+ var movingAverageIsSetByUser = movingAverageStrategy && movingAverageStrategy.execute;
+ var movingAverageValues = this._executeStrategy(
+ movingAverageIsSetByUser ? movingAverageStrategy : Statistics.MovingAverageStrategies[0], currentTimeSeriesData);
if (!movingAverageValues)
return null;
- var envelopeDelta = this._executeStrategy(envelopingStrategy, currentTimeSeriesData, [movingAverageValues]);
+ var envelopeIsSetByUser = envelopingStrategy && envelopingStrategy.execute;
+ var envelopeDelta = this._executeStrategy(envelopeIsSetByUser ? envelopingStrategy : Statistics.EnvelopingStrategies[0],
+ currentTimeSeriesData, [movingAverageValues]);
- return new TimeSeries(currentTimeSeriesData.map(function (point, index) {
- var value = movingAverageValues[index];
- return {
- measurement: point.measurement,
- time: point.time,
- value: value,
- interval: envelopeDelta !== null ? [value - envelopeDelta, value + envelopeDelta] : null,
- }
- }));
+ for (var i = 0; i < currentTimeSeriesData.length; i++) {
+ var currentValue = currentTimeSeriesData[i].value;
+ var movingAverageValue = movingAverageValues[i];
+ if (currentValue < movingAverageValue - envelopeDelta || movingAverageValue + envelopeDelta < currentValue)
+ currentTimeSeriesData[i].isOutlier = true;
+ }
+ if (!envelopeIsSetByUser)
+ envelopeDelta = null;
+
+ if (movingAverageIsSetByUser) {
+ return new TimeSeries(currentTimeSeriesData.map(function (point, index) {
+ var value = movingAverageValues[index];
+ return {
+ measurement: point.measurement,
+ time: point.time,
+ value: value,
+ interval: envelopeDelta !== null ? [value - envelopeDelta, value + envelopeDelta] : null,
+ }
+ }));
+ }
},
_executeStrategy: function (strategy, currentTimeSeriesData, additionalArguments)
{
return this._series.slice(startPoint.seriesIndex, endPoint.seriesIndex + 1);
}
-TimeSeries.prototype.minMaxForTimeRange = function (startTime, endTime)
+TimeSeries.prototype.minMaxForTimeRange = function (startTime, endTime, ignoreOutlier)
{
var data = this._series;
var i = 0;
var max = Number.MIN_VALUE;
for (; i < data.length; i++) {
var point = data[i];
+ if (point.isOutlier && ignoreOutlier)
+ continue;
var currentMin = point.interval ? point.interval[0] : point.value;
var currentMax = point.interval ? point.interval[1] : point.value;
.attr("class", "target"));
}
- var movingAverageIsVisible = this._movingAverageTimeSeries && !chartData.hideMovingAverage;
+ var movingAverageIsVisible = this._movingAverageTimeSeries;
var foregroundClass = movingAverageIsVisible ? '' : ' foreground';
this._areas.push(this._clippedContainer
.append("path")
.datum(this._movingAverageTimeSeries.series())
.attr("class", "movingAverage"));
- if (!chartData.hideEnvelope) {
- this._areas.push(this._clippedContainer
- .append("path")
- .datum(this._movingAverageTimeSeries.series())
- .attr("class", "envelope"));
- }
+ this._areas.push(this._clippedContainer
+ .append("path")
+ .datum(this._movingAverageTimeSeries.series())
+ .attr("class", "envelope"));
}
if (isInteractive) {
},
_computeYAxisDomain: function (startTime, endTime)
{
- var range = this._minMaxForAllTimeSeries(startTime, endTime);
+ var shouldShowFullYAxis = this.get('showFullYAxis');
+ var range = this._minMaxForAllTimeSeries(startTime, endTime, !shouldShowFullYAxis);
var min = range[0];
var max = range[1];
if (max < min)
min = max = 0;
+ else if (shouldShowFullYAxis)
+ min = Math.min(min, 0);
var diff = max - min;
var margin = diff * 0.05;
yExtent = [min - margin, max + margin];
-// if (yMin !== undefined)
-// yExtent[0] = parseInt(yMin);
return yExtent;
},
- _minMaxForAllTimeSeries: function (startTime, endTime)
+ _minMaxForAllTimeSeries: function (startTime, endTime, ignoreOutliners)
{
- var shouldShowFullYAxis = this.get('showFullYAxis');
- var mainTimeSeries = this._movingAverageTimeSeries && !shouldShowFullYAxis ? this._movingAverageTimeSeries : this._currentTimeSeries;
- var currentRange = mainTimeSeries.minMaxForTimeRange(startTime, endTime);
- if (shouldShowFullYAxis)
- currentRange[0] = Math.min(0, currentRange[0]);
-
- var baselineRange = this._baselineTimeSeries ? this._baselineTimeSeries.minMaxForTimeRange(startTime, endTime) : [Number.MAX_VALUE, Number.MIN_VALUE];
- var targetRange = this._targetTimeSeries ? this._targetTimeSeries.minMaxForTimeRange(startTime, endTime) : [Number.MAX_VALUE, Number.MIN_VALUE];
- return [
- Math.min(currentRange[0], baselineRange[0], targetRange[0]),
- Math.max(currentRange[1], baselineRange[1], targetRange[1]),
- ];
+ var seriesList = [this._currentTimeSeries, this._movingAverageTimeSeries, this._baselineTimeSeries, this._targetTimeSeries];
+ var min = Infinity;
+ var max = -Infinity;
+ for (var i = 0; i < seriesList.length; i++) {
+ if (seriesList[i]) {
+ var minMax = seriesList[i].minMaxForTimeRange(startTime, endTime, ignoreOutliners);
+ min = Math.min(min, minMax[0]);
+ max = Math.max(max, minMax[1]);
+ }
+ }
+ return [min, max];
},
_currentSelection: function ()
{