1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267
|
// Copyright 2019 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CC_METRICS_COMPOSITOR_FRAME_REPORTING_CONTROLLER_H_
#define CC_METRICS_COMPOSITOR_FRAME_REPORTING_CONTROLLER_H_
#include <array>
#include <map>
#include <memory>
#include <vector>
#include "base/containers/circular_deque.h"
#include "base/memory/raw_ptr.h"
#include "base/time/default_tick_clock.h"
#include "base/time/time.h"
#include "cc/cc_export.h"
#include "cc/metrics/compositor_frame_reporter.h"
#include "cc/metrics/event_metrics.h"
#include "cc/metrics/frame_sequence_metrics.h"
#include "cc/metrics/frame_sorter.h"
#include "cc/metrics/predictor_jank_tracker.h"
#include "cc/metrics/scroll_jank_dropped_frame_tracker.h"
#include "services/metrics/public/cpp/ukm_source_id.h"
namespace ukm {
class UkmRecorder;
}
namespace viz {
struct FrameTimingDetails;
}
namespace cc {
class EventLatencyTracker;
struct BeginMainFrameMetrics;
struct FrameInfo;
// This is used for managing simultaneous CompositorFrameReporter instances
// in the case that the compositor has high latency. Calling one of the
// event functions will begin recording the time of the corresponding
// phase and trace it. If the frame is eventually submitted, then the
// recorded times of each phase will be reported in UMA.
// See CompositorFrameReporter.
class CC_EXPORT CompositorFrameReportingController {
public:
// Used as indices for accessing CompositorFrameReporters.
enum PipelineStage {
kBeginImplFrame = 0,
kBeginMainFrame,
kReadyToCommit,
kCommit,
kActivate,
kNumPipelineStages
};
CompositorFrameReportingController(bool should_report_histograms,
bool should_report_ukm,
int layer_tree_host_id);
virtual ~CompositorFrameReportingController();
CompositorFrameReportingController(
const CompositorFrameReportingController&) = delete;
CompositorFrameReportingController& operator=(
const CompositorFrameReportingController&) = delete;
// Events to signal Beginning/Ending of phases.
virtual void WillBeginImplFrame(const viz::BeginFrameArgs& args);
virtual void WillBeginMainFrame(const viz::BeginFrameArgs& args);
virtual void BeginMainFrameAborted(const viz::BeginFrameId& id,
CommitEarlyOutReason reason);
virtual void WillInvalidateOnImplSide();
virtual void WillCommit();
virtual void DidCommit();
virtual void WillActivate();
virtual void DidActivate();
virtual void DidSubmitCompositorFrame(
SubmitInfo& submit_info,
const viz::BeginFrameId& current_frame_id,
const viz::BeginFrameId& last_activated_frame_id);
virtual void DidNotProduceFrame(const viz::BeginFrameId& id,
FrameSkippedReason skip_reason);
virtual void OnFinishImplFrame(const viz::BeginFrameId& id);
virtual void DidPresentCompositorFrame(
uint32_t frame_token,
const viz::FrameTimingDetails& details);
void OnStoppedRequestingBeginFrames();
void NotifyReadyToCommit(std::unique_ptr<BeginMainFrameMetrics> details);
void InitializeUkmManager(std::unique_ptr<ukm::UkmRecorder> recorder);
void SetSourceId(ukm::SourceId source_id);
void set_tick_clock(const base::TickClock* tick_clock) {
DCHECK(tick_clock);
tick_clock_ = tick_clock;
}
std::array<std::unique_ptr<CompositorFrameReporter>,
PipelineStage::kNumPipelineStages>&
ReportersForTesting() {
return reporters_;
}
void SetFrameSorter(FrameSorter* frame_sorter) {
global_trackers_.frame_sorter = frame_sorter;
}
void SetFrameSequenceTrackerCollection(
FrameSequenceTrackerCollection* frame_sequence_trackers) {
if (global_trackers_.frame_sorter) {
global_trackers_.frame_sorter->AddObserver(frame_sequence_trackers);
}
global_trackers_.frame_sequence_trackers = frame_sequence_trackers;
}
void ClearFrameSequenceTrackerCollection() {
if (global_trackers_.frame_sorter &&
global_trackers_.frame_sequence_trackers) {
global_trackers_.frame_sorter->RemoveObserver(
global_trackers_.frame_sequence_trackers);
}
global_trackers_.frame_sequence_trackers = nullptr;
}
void set_event_latency_tracker(EventLatencyTracker* event_latency_tracker) {
global_trackers_.event_latency_tracker = event_latency_tracker;
}
void BeginMainFrameStarted(base::TimeTicks begin_main_frame_start_time) {
begin_main_frame_start_time_ = begin_main_frame_start_time;
}
void SetNeedsRasterPropertiesAnimated(bool needs_raster_properties_animated) {
needs_raster_properties_animated_ = needs_raster_properties_animated;
}
bool HasReporterAt(PipelineStage stage) const;
void SetVisible(bool visible);
protected:
struct SubmittedCompositorFrame {
uint32_t frame_token;
std::unique_ptr<CompositorFrameReporter> reporter;
SubmittedCompositorFrame();
SubmittedCompositorFrame(uint32_t frame_token,
std::unique_ptr<CompositorFrameReporter> reporter);
SubmittedCompositorFrame(SubmittedCompositorFrame&& other);
~SubmittedCompositorFrame();
};
base::TimeTicks Now() const;
bool next_activate_has_invalidation() const {
return next_activate_has_invalidation_;
}
private:
using SmoothThread = CompositorFrameReporter::SmoothThread;
using SmoothEffectDrivingThread =
CompositorFrameReporter::SmoothEffectDrivingThread;
void AdvanceReporterStage(PipelineStage start, PipelineStage target);
bool CanSubmitImplFrame(const viz::BeginFrameId& id) const;
bool CanSubmitMainFrame(const viz::BeginFrameId& id) const;
std::unique_ptr<CompositorFrameReporter> RestoreReporterAtBeginImpl(
const viz::BeginFrameId& id);
// Checks whether there are reporters containing updates from the main
// thread, and returns a pointer to that reporter (if any). Otherwise
// returns nullptr.
CompositorFrameReporter* GetOutstandingUpdatesFromMain(
const viz::BeginFrameId& id) const;
// If the display-compositor skips over some frames (e.g. when the gpu is
// busy, or the client is non-responsive), then it will not issue any
// |BeginFrameArgs| for those frames. However, |CompositorFrameReporter|
// instances should still be created for these frames. The following
// functions accomplish this.
void ProcessSkippedFramesIfNecessary(const viz::BeginFrameArgs& args);
void MaybePassEventMetricsFromDroppedFrames(
CompositorFrameReporter& reporter,
uint32_t frame_token,
bool next_reporter_from_same_frame);
void StoreEventMetricsFromDroppedFrames(CompositorFrameReporter& reporter,
uint32_t frame_token);
void CreateReportersForDroppedFrames(
const viz::BeginFrameArgs& old_args,
const viz::BeginFrameArgs& new_args) const;
// The arg is a reference to the unique_ptr, because depending on the state
// that reporter is in, its ownership might be pass or not.
void SetPartialUpdateDeciderWhenWaitingOnMain(
std::unique_ptr<CompositorFrameReporter>& reporter);
const bool should_report_histograms_;
const int layer_tree_host_id_;
viz::BeginFrameId last_submitted_frame_id_;
bool next_activate_has_invalidation_ = false;
// Must outlive `reporters_` and `submitted_compositor_frames_` (which also
// have reporters), since destroying the reporters can flush frames to
// `global_trackers_`.
GlobalMetricsTrackers global_trackers_;
// The latency reporter passed to each CompositorFrameReporter. Owned here
// because it must be common among all reporters.
// DO NOT reorder this line and the ones below. The latency_ukm_reporter_
// must outlive the objects in |submitted_compositor_frames_|.
std::unique_ptr<LatencyUkmReporter> latency_ukm_reporter_;
std::unique_ptr<PredictorJankTracker> predictor_jank_tracker_;
std::unique_ptr<ScrollJankDroppedFrameTracker>
scroll_jank_dropped_frame_tracker_;
std::unique_ptr<ScrollJankUkmReporter> scroll_jank_ukm_reporter_;
std::array<std::unique_ptr<CompositorFrameReporter>,
PipelineStage::kNumPipelineStages>
reporters_;
// Mapping of frame token to pipeline reporter for submitted compositor
// frames.
// DO NOT reorder this line and the one above. The latency_ukm_reporter_
// must outlive the objects in |submitted_compositor_frames_|.
base::circular_deque<SubmittedCompositorFrame> submitted_compositor_frames_;
// Contains information about the latest frame that was started, and the state
// during that frame. This is used to process skipped frames, as well as
// making sure a CompositorFrameReporter object for a delayed main-frame is
// created with the correct state.
struct {
viz::BeginFrameArgs args;
FrameInfo::SmoothEffectDrivingThread scrolling_thread =
FrameInfo::SmoothEffectDrivingThread::kUnknown;
ActiveTrackers active_trackers;
SmoothThread smooth_thread = SmoothThread::kSmoothNone;
} last_started_compositor_frame_;
base::TimeTicks begin_main_frame_start_time_;
raw_ptr<const base::TickClock> tick_clock_ =
base::DefaultTickClock::GetInstance();
// When a frame with events metrics fails to be presented, its events metrics
// will be added to this map. The first following presented frame will get
// these metrics and report them. The key of map is submission frame token.
// Frame token is chosen over BeginFrameId as key due to the fact that frames
// can drop while a long running main still eventually presents, in which
// cases its more appropriate to check against frame_token instead of
// BeginFrameId.
std::map<uint32_t, EventMetricsSet> events_metrics_from_dropped_frames_;
// Reporting controller needs to track transition of the page from invisible
// to visible in order to discard EventsMetrics impacted by duration of page
// being invisible
bool visible_ = true;
bool waiting_for_did_present_after_visible_ = false;
// Indicates whether or not we expect the next frame to contain an animation
// which requires impl invalidation.
bool needs_raster_properties_animated_ = false;
};
} // namespace cc
#endif // CC_METRICS_COMPOSITOR_FRAME_REPORTING_CONTROLLER_H_
|