blob: cd718d87a4d0a4f30bc5a962e9bbdd59eb27738b [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 "ui/latency/windowed_analyzer.h"
#include "ui/latency/frame_metrics.h"
namespace ui {
void FrameRegionResult::AsValueInto(
base::trace_event::TracedValue* state) const {
// We don't report sample_count, since that is reported at a higher level.
state->SetDouble("value", value);
state->SetDouble("start", window_begin.since_origin().InMillisecondsF());
state->SetDouble("duration", (window_end - window_begin).InMillisecondsF());
}
namespace frame_metrics {
WindowedAnalyzer::WindowedAnalyzer(
const WindowedAnalyzerClient* client,
const SharedWindowedAnalyzerClient* shared_client)
: client_(client), shared_client_(shared_client) {
window_queue_.reserve(shared_client->max_window_size);
}
WindowedAnalyzer::~WindowedAnalyzer() = default;
void WindowedAnalyzer::ResetWorstValues() {
results_.reset();
}
void WindowedAnalyzer::ResetHistory() {
total_weight_ = 0;
accumulator_ = 0;
root_accumulator_ = 0;
square_accumulator_ = Accumulator96b();
window_queue_.resize(0);
}
void WindowedAnalyzer::AddSample(uint32_t value,
uint32_t weight,
uint64_t weighted_value,
uint64_t weighted_root,
const Accumulator96b& weighted_square) {
DCHECK_GT(weight, 0u);
DCHECK_EQ(weighted_value, static_cast<uint64_t>(weight) * value);
// Remove old values from the accumulators.
if (window_queue_.size() >= shared_client_->max_window_size) {
const uint32_t old_value = window_queue_.front().value;
const uint32_t old_weight = window_queue_.front().weight;
window_queue_.pop_front();
// Re-calculate some of the old values here. Although squared and root are
// passed in, we've only stored the original value to reduce memory usage.
total_weight_ -= old_weight;
accumulator_ -= static_cast<uint64_t>(old_weight) * old_value;
// Casting the whole rhs is important to ensure rounding happens at a place
// equivalent to when it was added.
root_accumulator_ -=
static_cast<uint64_t>(old_weight * FrameMetrics::FastApproximateSqrt(
static_cast<uint64_t>(old_value)
<< kFixedPointRootShift));
square_accumulator_.Subtract(Accumulator96b(old_value, old_weight));
}
// Verify overflow isn't an issue.
// square_accumulator_ has DCHECKs internally, so we don't worry about
// checking that here.
DCHECK_LT(weighted_value,
std::numeric_limits<decltype(accumulator_)>::max() - accumulator_);
DCHECK_LT(weighted_root,
std::numeric_limits<decltype(root_accumulator_)>::max() -
root_accumulator_);
DCHECK_LT(weight, std::numeric_limits<decltype(total_weight_)>::max() -
total_weight_);
window_queue_.push_back({value, weight});
total_weight_ += weight;
accumulator_ += weighted_value;
root_accumulator_ += weighted_root;
square_accumulator_.Add(weighted_square);
if (window_queue_.size() >= shared_client_->max_window_size) {
bool initialize_results = !results_;
if (initialize_results)
results_.emplace();
UpdateWorst(accumulator_, &results_->mean, initialize_results);
UpdateWorst(root_accumulator_, &results_->root, initialize_results);
UpdateWorst(square_accumulator_, &results_->square, initialize_results);
}
}
FrameRegionResult WindowedAnalyzer::ComputeWorstMean() const {
FrameRegionResult result;
if (results_) {
result = results_->mean;
} else {
UpdateWorst(accumulator_, &result, true);
}
result.value = client_->TransformResult(result.value);
return result;
}
FrameRegionResult WindowedAnalyzer::ComputeWorstRMS() const {
FrameRegionResult result;
if (results_) {
result = results_->square;
} else {
UpdateWorst(square_accumulator_, &result, true);
}
result.value =
client_->TransformResult(FrameMetrics::FastApproximateSqrt(result.value));
return result;
}
FrameRegionResult WindowedAnalyzer::ComputeWorstSMR() const {
FrameRegionResult result;
if (results_) {
result = results_->root;
} else {
UpdateWorst(root_accumulator_, &result, true);
}
result.value = client_->TransformResult((result.value * result.value) /
kFixedPointRootMultiplier);
return result;
}
} // namespace frame_metrics
} // namespace ui