Commit 74f8ec2a authored by Xiyuan Xia's avatar Xiyuan Xia Committed by Commit Bot

Add ThroughputTracker api to ui::Compositor

RequestNewThroughputTracker creates a ThroughputTracker to track
throughput of ui::Compositor. Each ThroughputTracker is assigned
a per-compositor unique sequence id. The sequence id will be used
on impl side to create a kCustom typed cc::FrameSequenceTracker.

When a tracker is started, stopped or canceled, an entry is created
in AnimationHost to store the pending start/stop info of the id.
This info is pushed to impl side along with other properties.

Bug: 1021774
Change-Id: I8cf8b4051bc68054c199d510083abf7bd41cf6e0
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2008001Reviewed-by: default avatarRobert Flack <flackr@chromium.org>
Reviewed-by: default avatarSadrul Chowdhury <sadrul@chromium.org>
Commit-Queue: Xiyuan Xia <xiyuan@chromium.org>
Cr-Commit-Position: refs/heads/master@{#757853}
parent 8e231fe0
......@@ -305,6 +305,12 @@ void AnimationHost::PushPropertiesToImplThread(AnimationHost* host_impl) {
host_impl->main_thread_animations_count_ = main_thread_animations_count_;
host_impl->current_frame_had_raf_ = current_frame_had_raf_;
host_impl->next_frame_has_pending_raf_ = next_frame_has_pending_raf_;
// The pending info list is cleared in LayerTreeHostImpl::CommitComplete
// and should be empty when pushing properties.
DCHECK(host_impl->pending_throughput_tracker_infos_.empty());
host_impl->pending_throughput_tracker_infos_ =
TakePendingThroughputTrackerInfos();
}
scoped_refptr<ElementAnimations>
......@@ -802,4 +808,24 @@ bool AnimationHost::NextFrameHasPendingRAF() const {
return next_frame_has_pending_raf_;
}
AnimationHost::PendingThroughputTrackerInfos
AnimationHost::TakePendingThroughputTrackerInfos() {
PendingThroughputTrackerInfos infos =
std::move(pending_throughput_tracker_infos_);
pending_throughput_tracker_infos_ = {};
return infos;
}
void AnimationHost::StartThroughputTracking(
TrackedAnimationSequenceId sequence_id) {
pending_throughput_tracker_infos_.push_back({sequence_id, true});
SetNeedsPushProperties();
}
void AnimationHost::StopThroughputTracking(
TrackedAnimationSequenceId sequnece_id) {
pending_throughput_tracker_infos_.push_back({sequnece_id, false});
SetNeedsPushProperties();
}
} // namespace cc
......@@ -212,6 +212,12 @@ class CC_ANIMATION_EXPORT AnimationHost : public MutatorHost,
bool HasCustomPropertyAnimations() const override;
bool CurrentFrameHadRAF() const override;
bool NextFrameHasPendingRAF() const override;
PendingThroughputTrackerInfos TakePendingThroughputTrackerInfos() override;
// Starts/stops throughput tracking represented by |sequence_id|.
void StartThroughputTracking(TrackedAnimationSequenceId sequence_id);
void StopThroughputTracking(TrackedAnimationSequenceId sequnece_id);
void SetAnimationCounts(size_t total_animations_count,
bool current_frame_had_raf,
bool next_frame_has_pending_raf);
......@@ -268,6 +274,8 @@ class CC_ANIMATION_EXPORT AnimationHost : public MutatorHost,
bool current_frame_had_raf_ = false;
bool next_frame_has_pending_raf_ = false;
PendingThroughputTrackerInfos pending_throughput_tracker_infos_;
base::WeakPtrFactory<AnimationHost> weak_factory_{this};
};
......
......@@ -102,6 +102,8 @@ class MockMutatorHost : public MutatorHost {
MOCK_CONST_METHOD0(HasCustomPropertyAnimations, bool());
MOCK_CONST_METHOD0(CurrentFrameHadRAF, bool());
MOCK_CONST_METHOD0(NextFrameHasPendingRAF, bool());
MOCK_METHOD0(TakePendingThroughputTrackerInfos,
PendingThroughputTrackerInfos());
};
} // namespace cc
......
......@@ -515,6 +515,10 @@ void LayerTreeHostImpl::CommitComplete() {
frame_trackers_.StartSequence(
FrameSequenceTrackerType::kMainThreadAnimation);
}
// TODO(crbug.com/1021774): Start/stop custom FrameSequenceTracker based on
// pending info.
auto ignored = mutator_host_->TakePendingThroughputTrackerInfos();
}
void LayerTreeHostImpl::UpdateSyncTreeAfterCommitOrImplSideInvalidation() {
......
......@@ -6,6 +6,7 @@
#define CC_TREES_MUTATOR_HOST_H_
#include <memory>
#include <vector>
#include "base/callback_forward.h"
#include "base/time/time.h"
......@@ -39,7 +40,7 @@ const float kNotScaled = 0;
// MutatorHostClient interface.
class MutatorHost {
public:
virtual ~MutatorHost() {}
virtual ~MutatorHost() = default;
virtual std::unique_ptr<MutatorHost> CreateImplInstance(
bool supports_impl_scrolling) const = 0;
......@@ -163,11 +164,24 @@ class MutatorHost {
virtual bool HasCustomPropertyAnimations() const = 0;
virtual bool CurrentFrameHadRAF() const = 0;
virtual bool NextFrameHasPendingRAF() const = 0;
using TrackedAnimationSequenceId = size_t;
struct PendingThroughputTrackerInfo {
// Id of a tracked animation sequence.
TrackedAnimationSequenceId id = 0u;
// True means the tracking for |id| is pending to start and false means
// the tracking is pending to stop.
bool start = false;
};
// Takes info of throughput trackers that are pending start or stop.
using PendingThroughputTrackerInfos =
std::vector<PendingThroughputTrackerInfo>;
virtual PendingThroughputTrackerInfos TakePendingThroughputTrackerInfos() = 0;
};
class MutatorEvents {
public:
virtual ~MutatorEvents() {}
virtual ~MutatorEvents() = default;
virtual bool IsEmpty() const = 0;
};
......
......@@ -76,6 +76,9 @@ jumbo_component("compositor") {
"scoped_animation_duration_scale_mode.h",
"scoped_layer_animation_settings.cc",
"scoped_layer_animation_settings.h",
"throughput_tracker.cc",
"throughput_tracker.h",
"throughput_tracker_host.h",
"transform_animation_curve_adapter.cc",
"transform_animation_curve_adapter.h",
"transform_recorder.cc",
......
......@@ -695,6 +695,25 @@ void Compositor::OnFrameTokenChanged(uint32_t frame_token) {
NOTREACHED();
}
void Compositor::StartThroughputTracker(
TrackerId tracker_id,
ThroughputTrackerHost::ReportCallback callback) {
DCHECK(!base::Contains(throughput_tracker_map_, tracker_id));
throughput_tracker_map_[tracker_id] = std::move(callback);
animation_host_->StartThroughputTracking(tracker_id);
}
void Compositor::StopThroughtputTracker(TrackerId tracker_id) {
DCHECK(base::Contains(throughput_tracker_map_, tracker_id));
animation_host_->StopThroughputTracking(tracker_id);
}
void Compositor::CancelThroughtputTracker(TrackerId tracker_id) {
DCHECK(base::Contains(throughput_tracker_map_, tracker_id));
StopThroughtputTracker(tracker_id);
throughput_tracker_map_.erase(tracker_id);
}
#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
void Compositor::OnCompleteSwapWithNewSize(const gfx::Size& size) {
for (auto& observer : observer_list_)
......@@ -722,4 +741,8 @@ void Compositor::RequestPresentationTimeForNextFrame(
host_->RequestPresentationTimeForNextFrame(std::move(callback));
}
ThroughputTracker Compositor::RequestNewThroughputTracker() {
return ThroughputTracker(next_throughput_tracker_id_++, this);
}
} // namespace ui
......@@ -11,6 +11,7 @@
#include <string>
#include "base/callback_forward.h"
#include "base/containers/flat_map.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/observer_list.h"
......@@ -33,6 +34,8 @@
#include "ui/compositor/compositor_lock.h"
#include "ui/compositor/compositor_observer.h"
#include "ui/compositor/layer_animator_collection.h"
#include "ui/compositor/throughput_tracker.h"
#include "ui/compositor/throughput_tracker_host.h"
#include "ui/gfx/display_color_spaces.h"
#include "ui/gfx/geometry/size.h"
#include "ui/gfx/geometry/vector2d.h"
......@@ -80,6 +83,7 @@ class Compositor;
class Layer;
class ScopedAnimationDurationScaleMode;
class ScrollInputHandler;
class ThroughputTracker;
struct PendingBeginFrameArgs;
constexpr int kCompositorLockTimeoutMs = 67;
......@@ -129,7 +133,8 @@ class COMPOSITOR_EXPORT ContextFactory {
// view hierarchy.
class COMPOSITOR_EXPORT Compositor : public cc::LayerTreeHostClient,
public cc::LayerTreeHostSingleThreadClient,
public viz::HostFrameSinkClient {
public viz::HostFrameSinkClient,
public ThroughputTrackerHost {
public:
Compositor(const viz::FrameSinkId& frame_sink_id,
ui::ContextFactory* context_factory,
......@@ -295,6 +300,9 @@ class COMPOSITOR_EXPORT Compositor : public cc::LayerTreeHostClient,
bool force,
base::OnceCallback<void(const viz::BeginFrameAck&)> callback);
// Creates a ThroughputTracker for tracking this Compositor.
ThroughputTracker RequestNewThroughputTracker();
// LayerTreeHostClient implementation.
void WillBeginMainFrame() override {}
void DidBeginMainFrame() override {}
......@@ -341,6 +349,13 @@ class COMPOSITOR_EXPORT Compositor : public cc::LayerTreeHostClient,
void OnFirstSurfaceActivation(const viz::SurfaceInfo& surface_info) override;
void OnFrameTokenChanged(uint32_t frame_token) override;
// ThroughputTrackerHost implementation.
void StartThroughputTracker(
TrackerId tracker_id,
ThroughputTrackerHost::ReportCallback callback) override;
void StopThroughtputTracker(TrackerId tracker_id) override;
void CancelThroughtputTracker(TrackerId tracker_id) override;
#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
void OnCompleteSwapWithNewSize(const gfx::Size& size);
#endif
......@@ -446,6 +461,11 @@ class COMPOSITOR_EXPORT Compositor : public cc::LayerTreeHostClient,
// Set in DisableSwapUntilResize and reset when a resize happens.
bool disabled_swap_until_resize_ = false;
TrackerId next_throughput_tracker_id_ = 1u;
using ThroughputTrackerMap =
base::flat_map<TrackerId, ThroughputTrackerHost::ReportCallback>;
ThroughputTrackerMap throughput_tracker_map_;
base::WeakPtrFactory<Compositor> context_creation_weak_ptr_factory_{this};
DISALLOW_COPY_AND_ASSIGN(Compositor);
......
......@@ -7,6 +7,7 @@
#include "base/macros.h"
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
#include "base/test/bind_test_util.h"
#include "base/test/task_environment.h"
#include "base/test/test_mock_time_task_runner.h"
#include "base/threading/thread_task_runner_handle.h"
......@@ -28,8 +29,8 @@ namespace {
class CompositorTest : public testing::Test {
public:
CompositorTest() {}
~CompositorTest() override {}
CompositorTest() = default;
~CompositorTest() override = default;
void SetUp() override {
context_factories_ = std::make_unique<TestContextFactories>(false);
......@@ -164,6 +165,71 @@ TEST_F(CompositorTestWithMockedTime,
compositor()->SetVisible(true);
}
TEST_F(CompositorTestWithMessageLoop, MoveThroughputTracker) {
// Move a not started instance.
{
auto tracker = compositor()->RequestNewThroughputTracker();
auto moved_tracker = std::move(tracker);
}
// Move a started instance.
{
auto tracker = compositor()->RequestNewThroughputTracker();
tracker.Start(base::BindLambdaForTesting(
[&](cc::FrameSequenceMetrics::ThroughputData throughput) {
// This should not be called since the tracking is auto canceled.
ADD_FAILURE();
}));
auto moved_tracker = std::move(tracker);
}
// Move a started instance and stop.
{
auto tracker = compositor()->RequestNewThroughputTracker();
tracker.Start(base::BindLambdaForTesting(
[&](cc::FrameSequenceMetrics::ThroughputData throughput) {
// May be called since Stop() is called.
}));
auto moved_tracker = std::move(tracker);
moved_tracker.Stop();
}
// Move a started instance and cancel.
{
auto tracker = compositor()->RequestNewThroughputTracker();
tracker.Start(base::BindLambdaForTesting(
[&](cc::FrameSequenceMetrics::ThroughputData throughput) {
// This should not be called since Cancel() is called.
ADD_FAILURE();
}));
auto moved_tracker = std::move(tracker);
moved_tracker.Cancel();
}
// Move a stopped instance.
{
auto tracker = compositor()->RequestNewThroughputTracker();
tracker.Start(base::BindLambdaForTesting(
[&](cc::FrameSequenceMetrics::ThroughputData throughput) {
// May be called since Stop() is called.
}));
tracker.Stop();
auto moved_tracker = std::move(tracker);
}
// Move a canceled instance.
{
auto tracker = compositor()->RequestNewThroughputTracker();
tracker.Start(base::BindLambdaForTesting(
[&](cc::FrameSequenceMetrics::ThroughputData throughput) {
// This should not be called since Cancel() is called.
ADD_FAILURE();
}));
tracker.Cancel();
auto moved_tracker = std::move(tracker);
}
}
#if defined(OS_WIN)
// TODO(crbug.com/608436): Flaky on windows trybots
#define MAYBE_CreateAndReleaseOutputSurface \
......
// 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/throughput_tracker.h"
#include <utility>
#include "base/callback.h"
#include "base/logging.h"
namespace ui {
ThroughputTracker::ThroughputTracker(TrackerId id, ThroughputTrackerHost* host)
: id_(id), host_(host) {
DCHECK(host_);
}
ThroughputTracker::ThroughputTracker(ThroughputTracker&& other) {
*this = std::move(other);
}
ThroughputTracker& ThroughputTracker::operator=(ThroughputTracker&& other) {
id_ = other.id_;
host_ = other.host_;
started_ = other.started_;
other.id_ = kInvalidId;
other.host_ = nullptr;
other.started_ = false;
return *this;
}
ThroughputTracker::~ThroughputTracker() {
if (started_)
Cancel();
}
void ThroughputTracker::Start(ThroughputTrackerHost::ReportCallback callback) {
started_ = true;
host_->StartThroughputTracker(id_, std::move(callback));
}
void ThroughputTracker::Stop() {
started_ = false;
host_->StopThroughtputTracker(id_);
}
void ThroughputTracker::Cancel() {
started_ = false;
host_->CancelThroughtputTracker(id_);
}
} // 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_THROUGHPUT_TRACKER_H_
#define UI_COMPOSITOR_THROUGHPUT_TRACKER_H_
#include "base/callback_forward.h"
#include "ui/compositor/compositor_export.h"
#include "ui/compositor/throughput_tracker_host.h"
namespace ui {
class Compositor;
class ThroughputTrackerHost;
// A class to track the throughput of Compositor. The tracking is identified by
// an id. The id is passed into impl side and be used as the sequence id to
// create and stop a kCustom typed cc::FrameSequenceTracker. The class is
// move-only to have only one holder of the id. When ThroughputTracker is
// destroyed with an active tracking, the tracking will be canceled and report
// callback will not be invoked.
class COMPOSITOR_EXPORT ThroughputTracker {
public:
using TrackerId = ThroughputTrackerHost::TrackerId;
// Move only.
ThroughputTracker(ThroughputTracker&& other);
ThroughputTracker& operator=(ThroughputTracker&& other);
~ThroughputTracker();
// Starts tracking Compositor and provides a callback for reporting. The
// throughput data collection starts after the next commit.
void Start(ThroughputTrackerHost::ReportCallback callback);
// Stops tracking. The supplied callback will be invoked when the data
// collection finishes after the next frame presentation. Note that no data
// will be reported if Stop() is not called,
void Stop();
// Cancels tracking. The supplied callback will not be invoked.
void Cancel();
private:
friend class Compositor;
// Private since it should only be created via Compositor's
// RequestNewThroughputTracker call.
ThroughputTracker(TrackerId id, ThroughputTrackerHost* host);
static const TrackerId kInvalidId = 0u;
TrackerId id_ = kInvalidId;
ThroughputTrackerHost* host_ = nullptr;
bool started_ = false;
};
} // namespace ui
#endif // UI_COMPOSITOR_THROUGHPUT_TRACKER_H_
// 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_THROUGHPUT_TRACKER_HOST_H_
#define UI_COMPOSITOR_THROUGHPUT_TRACKER_HOST_H_
#include "base/callback_forward.h"
#include "cc/metrics/frame_sequence_tracker.h"
#include "ui/compositor/compositor_export.h"
namespace ui {
// An interface for ThroughputTracker to call its host.
class COMPOSITOR_EXPORT ThroughputTrackerHost {
public:
using TrackerId = size_t;
virtual ~ThroughputTrackerHost() = default;
// Starts the tracking for the given tracker id. |callback| is invoked after
// the tracker is stopped and the throughput data is collected.
using ReportCallback = base::OnceCallback<void(
const cc::FrameSequenceMetrics::ThroughputData throughput)>;
virtual void StartThroughputTracker(TrackerId tracker_id,
ReportCallback callback) = 0;
// Stops the tracking for the given tracker id.
virtual void StopThroughtputTracker(TrackerId tracker_id) = 0;
// Cancels the tracking for the given tracker id.
virtual void CancelThroughtputTracker(TrackerId tracker_id) = 0;
};
} // namespace ui
#endif // UI_COMPOSITOR_THROUGHPUT_TRACKER_HOST_H_
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