computeStats method
Extracts useful statistics out of this timeseries.
See TimeseriesStats for more details.
Implementation
TimeseriesStats computeStats() {
final int finalWarmUpFrameCount = warmUpFrameCount;
assert(finalWarmUpFrameCount >= 0 && finalWarmUpFrameCount < count);
// The first few values we simply discard and never look at. They're from the warm-up phase.
final List<double> warmUpValues =
_allValues.sublist(0, finalWarmUpFrameCount);
// Values we analyze.
final List<double> candidateValues =
_allValues.sublist(finalWarmUpFrameCount);
// The average that includes outliers.
final double dirtyAverage = _computeAverage(name, candidateValues);
// The standard deviation that includes outliers.
final double dirtyStandardDeviation =
_computeStandardDeviationForPopulation(name, candidateValues);
// Any value that's higher than this is considered an outlier.
final double outlierCutOff = dirtyAverage + dirtyStandardDeviation;
// Candidates with outliers removed.
final Iterable<double> cleanValues =
candidateValues.where((double value) => value <= outlierCutOff);
// Outlier candidates.
final Iterable<double> outliers =
candidateValues.where((double value) => value > outlierCutOff);
// Final statistics.
final double cleanAverage = _computeAverage(name, cleanValues);
final double standardDeviation =
_computeStandardDeviationForPopulation(name, cleanValues);
final double noise =
cleanAverage > 0.0 ? standardDeviation / cleanAverage : 0.0;
// Compute outlier average. If there are no outliers the outlier average is
// the same as clean value average. In other words, in a perfect benchmark
// with no noise the difference between average and outlier average is zero,
// which the best possible outcome. Noise produces a positive difference
// between the two.
final double outlierAverage =
outliers.isNotEmpty ? _computeAverage(name, outliers) : cleanAverage;
// Compute percentile values (e.g. p50, p90, p95).
final Map<double, double> percentiles = computePercentiles(
name,
PercentileMetricComputation.percentilesAsDoubles,
candidateValues,
);
final List<AnnotatedSample> annotatedValues = <AnnotatedSample>[
for (final double warmUpValue in warmUpValues)
AnnotatedSample(
magnitude: warmUpValue,
isOutlier: warmUpValue > outlierCutOff,
isWarmUpValue: true,
),
for (final double candidate in candidateValues)
AnnotatedSample(
magnitude: candidate,
isOutlier: candidate > outlierCutOff,
isWarmUpValue: false,
),
];
return TimeseriesStats(
name: name,
average: cleanAverage,
outlierCutOff: outlierCutOff,
outlierAverage: outlierAverage,
standardDeviation: standardDeviation,
noise: noise,
percentiles: percentiles,
cleanSampleCount: cleanValues.length,
outlierSampleCount: outliers.length,
samples: annotatedValues,
);
}