blob: ac550c80a4f693a4df350c608be3f0c6778b278e [file] [log] [blame]
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <cstdint>
#include <memory>
#include <vector>
#include "base/macros.h"
#include "base/trace_event/trace_event_argument.h"
#include "ui/latency/fixed_point.h"
#include "ui/latency/histograms.h"
#include "ui/latency/windowed_analyzer.h"
namespace ui {
// Used to communicate fraction of time the value of a metric was greater than
// or equal to the threshold.
struct ThresholdResult {
double threshold = 0.0;
double ge_fraction = 0.0;
struct StreamAnalysis {
double mean;
double rms;
double smr;
double std_dev;
double variance_of_roots;
std::vector<ThresholdResult> thresholds;
PercentileResults percentiles;
size_t worst_sample_count = 0;
FrameRegionResult worst_mean;
FrameRegionResult worst_rms;
FrameRegionResult worst_smr;
void AsValueInto(base::trace_event::TracedValue* state) const;
namespace frame_metrics {
// The StreamAnalyzerClient interface is currently the same as
// WindowedAnalyzerClient and can rely on the same implementation.
using StreamAnalyzerClient = WindowedAnalyzerClient;
// Tracks the overall mean, RMS, and SMR for a metric and also owns
// the Histogram and WindowedAnalyzer.
class StreamAnalyzer {
StreamAnalyzer(const StreamAnalyzerClient* client,
const SharedWindowedAnalyzerClient* shared_client,
std::vector<uint32_t> thresholds,
std::unique_ptr<Histogram> histogram);
// Resets all statistics and history.
void Reset();
// Resets the statistics without throwing away recent sample history in the
// WindowedAnalyzer.
void StartNewReportPeriod();
// To play well with the histogram range, |value| should be within the
// range [0,64000000]. If the units are milliseconds, that's 64 seconds.
// Otherwise, the histogram will clip the result.
// |weight| may be the duration the frame was active in microseconds
// or it may be 1 in case every frame is to be weighed equally.
void AddSample(const uint32_t value, const uint32_t weight);
// The mean, root-mean-squared, and squared-mean-root of all samples
// received since the last call to StartNewReportPeriod().
// The units are the same as the values added in AddSample().
double ComputeMean() const;
double ComputeRMS() const;
double ComputeSMR() const;
// StdDev calculates the standard deviation of all values in the stream.
// The units are the same as the values added in AddSample().
// The work to track this is the same as RMS, so we effectively get this for
// free. Given two of the Mean, RMS, and StdDev, we can calculate the third.
double ComputeStdDev() const;
// VarianceOfRoots calculates the variance of all square roots of values.
// The units end up being the same as the values added in AddSample().
// The work to track this is the same as SMR.
// Given two of the Mean, SMR, and VarianceOfRoots, we can calculate the
// third. Note: We don't track something like RootStdDevOfSquares since it
// would be difficult to track values raised to the fourth power.
// TODO(brianderon): Remove VarianceOfRoots if it's not useful.
double ComputeVarianceOfRoots() const;
// Thresholds returns a percentile for threshold values given to the
// constructor. This is useful for tracking improvements in really good
// sources, but it's dynamic range is limited, which prevents it from
// detecting improvements in sources where most of the frames are "bad".
std::vector<ThresholdResult> ComputeThresholds() const;
// CalculatePercentiles returns a value for certain percentiles.
// It is only an estimate, since the values are calculated from a histogram
// rather than from the entire history of actual values.
// This is useful for tracking improvements even in really bad sources
// since it's dynamic range includes all possible values.
PercentileResults ComputePercentiles() const;
// Expose the WindowedAnalyzer as const to make it's accessors
// available directly.
const WindowedAnalyzer& window() const { return windowed_analyzer_; }
void ComputeSummary(StreamAnalysis* results) const;
double VarianceHelper(double accum, double square_accum) const;
struct ThresholdState {
explicit ThresholdState(uint32_t value) : threshold(value) {}
void ResetAccumulators();
uint32_t threshold;
uint32_t ge_weight = 0;
uint32_t lt_weight = 0;
const StreamAnalyzerClient* const client_;
std::vector<ThresholdState> thresholds_;
std::unique_ptr<Histogram> histogram_;
WindowedAnalyzer windowed_analyzer_;
uint64_t total_weight_ = 0;
uint64_t accumulator_ = 0;
uint64_t root_accumulator_ = 0;
Accumulator96b square_accumulator_;
} // namespace frame_metrics
} // namespace ui