Commit ca3ee459 authored by Mitsuru Oshima's avatar Mitsuru Oshima Committed by Chromium LUCI CQ

TotalAnimationThroughputReporter

This class measures the throughput from the time first animation
is started on a compositor, to the time last animation ended.

This is useful to measure the total animation throughput during
a transition that has many animations applied such as login, overview
etc.

Bug: 1150492
Test: covered by unittest

Change-Id: Id0bfec6e57403b7f1ebe5a8068ae095b1412bc7d
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2550366
Commit-Queue: Mitsuru Oshima <oshima@chromium.org>
Reviewed-by: default avatarRobert Flack <flackr@chromium.org>
Cr-Commit-Position: refs/heads/master@{#833625}
parent edb72404
......@@ -69,6 +69,8 @@ component("compositor") {
"throughput_tracker.cc",
"throughput_tracker.h",
"throughput_tracker_host.h",
"total_animation_throughput_reporter.cc",
"total_animation_throughput_reporter.h",
"transform_animation_curve_adapter.cc",
"transform_animation_curve_adapter.h",
"transform_recorder.cc",
......@@ -238,6 +240,7 @@ test("compositor_unittests") {
"layer_owner_unittest.cc",
"layer_unittest.cc",
"run_all_unittests.cc",
"total_animation_throughput_reporter_unittest.cc",
"transform_animation_curve_adapter_unittest.cc",
]
......
......@@ -576,13 +576,23 @@ bool Compositor::HasObserver(const CompositorObserver* observer) const {
}
void Compositor::AddAnimationObserver(CompositorAnimationObserver* observer) {
if (!animation_observer_list_.has_observers()) {
for (auto& obs : observer_list_)
obs.OnFirstAnimationStarted(this);
}
animation_observer_list_.AddObserver(observer);
host_->SetNeedsAnimate();
}
void Compositor::RemoveAnimationObserver(
CompositorAnimationObserver* observer) {
if (!animation_observer_list_.HasObserver(observer))
return;
animation_observer_list_.RemoveObserver(observer);
if (!animation_observer_list_.has_observers()) {
for (auto& obs : observer_list_)
obs.OnLastAnimationEnded(this);
}
}
bool Compositor::HasAnimationObserver(
......
......@@ -409,6 +409,7 @@ class COMPOSITOR_EXPORT Compositor : public cc::LayerTreeHostClient,
private:
friend class base::RefCounted<Compositor>;
friend class TotalAnimationThroughputReporter;
// Called when collected metrics for the tracker of |tracker_id| is ready.
void ReportMetricsForTracker(
......
......@@ -60,6 +60,9 @@ class COMPOSITOR_EXPORT CompositorObserver {
virtual void OnDidPresentCompositorFrame(
uint32_t frame_token,
const gfx::PresentationFeedback& feedback) {}
virtual void OnFirstAnimationStarted(Compositor* compositor) {}
virtual void OnLastAnimationEnded(Compositor* compositor) {}
};
} // namespace ui
......
// Copyright 2020 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/compositor/total_animation_throughput_reporter.h"
#include "base/logging.h"
#include "ui/compositor/compositor.h"
namespace ui {
TotalAnimationThroughputReporter::TotalAnimationThroughputReporter(
ui::Compositor* compositor,
ReportOnceCallback once_callback,
bool should_delete)
: TotalAnimationThroughputReporter(compositor,
ReportRepeatingCallback(),
std::move(once_callback),
should_delete) {}
TotalAnimationThroughputReporter::TotalAnimationThroughputReporter(
ui::Compositor* compositor,
ReportRepeatingCallback repeating_callback)
: TotalAnimationThroughputReporter(compositor,
repeating_callback,
ReportOnceCallback(),
/*should_delete=*/false) {}
TotalAnimationThroughputReporter::~TotalAnimationThroughputReporter() {
if (throughput_tracker_)
throughput_tracker_->Cancel();
if (compositor_)
compositor_->RemoveObserver(this);
}
void TotalAnimationThroughputReporter::OnFirstAnimationStarted(
ui::Compositor* compositor) {
throughput_tracker_ = compositor->RequestNewThroughputTracker();
throughput_tracker_->Start(base::BindRepeating(
&TotalAnimationThroughputReporter::Report, ptr_factory_.GetWeakPtr()));
}
void TotalAnimationThroughputReporter::OnLastAnimationEnded(
ui::Compositor* compositor) {
throughput_tracker_->Stop();
throughput_tracker_.reset();
}
void TotalAnimationThroughputReporter::OnCompositingShuttingDown(
ui::Compositor* compositor) {
if (throughput_tracker_) {
throughput_tracker_->Cancel();
throughput_tracker_.reset();
}
compositor->RemoveObserver(this);
compositor_ = nullptr;
if (should_delete_)
delete this;
}
TotalAnimationThroughputReporter::TotalAnimationThroughputReporter(
ui::Compositor* compositor,
ReportRepeatingCallback repeating_callback,
ReportOnceCallback once_callback,
bool should_delete)
: compositor_(compositor),
report_repeating_callback_(repeating_callback),
report_once_callback_(std::move(once_callback)),
should_delete_(should_delete) {
DCHECK_NE(report_repeating_callback_.is_null(),
report_once_callback_.is_null());
compositor_->AddObserver(this);
if (compositor->animation_observer_list_.has_observers())
OnFirstAnimationStarted(compositor_);
}
void TotalAnimationThroughputReporter::Report(
const cc::FrameSequenceMetrics::CustomReportData& data) {
if (!report_once_callback_.is_null()) {
compositor_->RemoveObserver(this);
std::move(report_once_callback_).Run(data);
if (should_delete_)
delete this;
return;
}
if (!report_repeating_callback_.is_null())
report_repeating_callback_.Run(data);
}
} // namespace ui
// Copyright 2020 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.
#ifndef UI_COMPOSITOR_TOTAL_ANIMATION_THROUGHPUT_REPORTER_H_
#define UI_COMPOSITOR_TOTAL_ANIMATION_THROUGHPUT_REPORTER_H_
#include <memory>
#include "base/callback_forward.h"
#include "base/memory/weak_ptr.h"
#include "base/optional.h"
#include "cc/metrics/frame_sequence_metrics.h"
#include "ui/compositor/compositor_export.h"
#include "ui/compositor/compositor_observer.h"
#include "ui/compositor/throughput_tracker.h"
namespace ui {
// Reports cc::FrameSequenceMetrics::ThroughputData between the first animation
// start and the last animation ends on a compositor.
//
// Please see AnimationThroughputReporter for the definition of the throughput
// and jack metrics.
//
// See also docs/speed/graphics_metrics_definitions.md.
//
// cc::FrameSequenceMetrics::CustomReportData contains the numbers of produced
// frames, expected frames and jank count.
//
// The tracking starts when the first animation observer is added to the
// compositor, then stopped when the last animation observer is removed. The
// report callback is invoked on the next begin frame if there is enough data.
// Since this observes multiple animations, aborting one of animations will
// not cancel the tracking, and the data will be reported as normal.
class COMPOSITOR_EXPORT TotalAnimationThroughputReporter
: public CompositorObserver {
public:
using ReportOnceCallback = base::OnceCallback<void(
const cc::FrameSequenceMetrics::CustomReportData& data)>;
using ReportRepeatingCallback = base::RepeatingCallback<void(
const cc::FrameSequenceMetrics::CustomReportData& data)>;
// Create a TotalAnimationThroughputReporter that observes
// the total animation throughput just once. If |should_delete|
// is true, then the object will be deleted after callback is
// invoked.
TotalAnimationThroughputReporter(Compositor* compositor,
ReportOnceCallback callback,
bool should_delete);
// Create a persistent TotalAnimationThroughputReporter, which
// will call the callback every time the last animation is finished.
TotalAnimationThroughputReporter(Compositor* compositor,
ReportRepeatingCallback callback);
TotalAnimationThroughputReporter(const TotalAnimationThroughputReporter&) =
delete;
TotalAnimationThroughputReporter& operator=(
const TotalAnimationThroughputReporter&) = delete;
~TotalAnimationThroughputReporter() override;
// CompositorObserver:
void OnFirstAnimationStarted(Compositor* compositor) override;
void OnLastAnimationEnded(Compositor* compositor) override;
void OnCompositingShuttingDown(Compositor* compositor) override;
bool IsMeasuringForTesting() const { return bool{throughput_tracker_}; }
private:
TotalAnimationThroughputReporter(Compositor* compositor,
ReportRepeatingCallback repeating_callback,
ReportOnceCallback once_callback,
bool should_delete);
void Report(const cc::FrameSequenceMetrics::CustomReportData& data);
Compositor* compositor_;
ReportRepeatingCallback report_repeating_callback_;
ReportOnceCallback report_once_callback_;
bool should_delete_ = false;
base::Optional<ThroughputTracker> throughput_tracker_;
base::WeakPtrFactory<TotalAnimationThroughputReporter> ptr_factory_{this};
};
} // namespace ui
#endif // UI_COMPOSITOR_TOTAL_ANIMATION_THROUGHPUT_REPORTER_H_
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment