1 // Copyright 2020 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #ifndef CC_METRICS_FRAME_SEQUENCE_METRICS_H_
6 #define CC_METRICS_FRAME_SEQUENCE_METRICS_H_
12 #include "base/callback.h"
13 #include "base/check.h"
14 #include "base/memory/raw_ptr.h"
15 #include "base/trace_event/traced_value.h"
16 #include "cc/cc_export.h"
17 #include "cc/metrics/frame_info.h"
20 struct BeginFrameArgs;
24 class ThroughputUkmReporter;
28 enum class FrameSequenceTrackerType {
29 // Used as an enum for metrics. DO NOT reorder or delete values. Rather,
30 // add them at the end and increment kMaxType.
31 kCompositorAnimation = 0,
32 kMainThreadAnimation = 1,
39 kCustom = 9, // Note that the metrics for kCustom are not reported on UMA,
40 // and instead are dispatched back to the LayerTreeHostClient.
41 kCanvasAnimation = 10,
43 kSETMainThreadAnimation = 12,
44 kSETCompositorAnimation = 13,
48 using ActiveTrackers =
49 std::bitset<static_cast<size_t>(FrameSequenceTrackerType::kMaxType)>;
51 inline bool IsScrollActive(const ActiveTrackers& trackers) {
53 static_cast<size_t>(FrameSequenceTrackerType::kWheelScroll)) ||
55 static_cast<size_t>(FrameSequenceTrackerType::kTouchScroll)) ||
57 static_cast<size_t>(FrameSequenceTrackerType::kScrollbarScroll));
60 inline bool HasMainThreadAnimation(const ActiveTrackers& trackers) {
61 return trackers.test(static_cast<size_t>(
62 FrameSequenceTrackerType::kMainThreadAnimation)) ||
64 static_cast<size_t>(FrameSequenceTrackerType::kCanvasAnimation)) ||
66 static_cast<size_t>(FrameSequenceTrackerType::kJSAnimation)) ||
67 trackers.test(static_cast<size_t>(FrameSequenceTrackerType::kRAF));
70 inline bool HasCompositorThreadAnimation(const ActiveTrackers& trackers) {
72 static_cast<size_t>(FrameSequenceTrackerType::kCompositorAnimation));
75 class CC_EXPORT FrameSequenceMetrics {
77 FrameSequenceMetrics(FrameSequenceTrackerType type,
78 ThroughputUkmReporter* ukm_reporter);
79 ~FrameSequenceMetrics();
81 FrameSequenceMetrics(const FrameSequenceMetrics&) = delete;
82 FrameSequenceMetrics& operator=(const FrameSequenceMetrics&) = delete;
84 struct ThroughputData {
85 static std::unique_ptr<base::trace_event::TracedValue> ToTracedValue(
86 const ThroughputData& impl,
87 const ThroughputData& main,
88 FrameInfo::SmoothEffectDrivingThread effective_thred);
90 static bool CanReportHistogram(
91 FrameSequenceMetrics* metrics,
92 FrameInfo::SmoothEffectDrivingThread thread_type,
93 const ThroughputData& data);
95 // Returns the dropped throughput in percent
96 static int ReportDroppedFramePercentHistogram(
97 FrameSequenceMetrics* metrics,
98 FrameInfo::SmoothEffectDrivingThread thread_type,
100 const ThroughputData& data);
102 // Returns the missed deadline throughput in percent
103 static int ReportMissedDeadlineFramePercentHistogram(
104 FrameSequenceMetrics* metrics,
105 FrameInfo::SmoothEffectDrivingThread thread_type,
107 const ThroughputData& data);
109 static void ReportCheckerboardingHistogram(
110 FrameSequenceMetrics* metrics,
111 FrameInfo::SmoothEffectDrivingThread thread_type,
114 void Merge(const ThroughputData& data) {
115 frames_expected += data.frames_expected;
116 frames_produced += data.frames_produced;
117 frames_ontime += data.frames_ontime;
119 frames_processed += data.frames_processed;
120 frames_received += data.frames_received;
124 int DroppedFramePercent() const {
125 if (frames_expected == 0)
127 return std::ceil(100 * (frames_expected - frames_produced) /
128 static_cast<double>(frames_expected));
131 int MissedDeadlineFramePercent() const {
132 if (frames_produced == 0)
134 return std::ceil(100 * (frames_produced - frames_ontime) /
135 static_cast<double>(frames_produced));
138 // Tracks the number of frames that were expected to be shown during this
140 uint32_t frames_expected = 0;
142 // Tracks the number of frames that were actually presented to the user
143 // during this frame-sequence.
144 uint32_t frames_produced = 0;
146 // Tracks the number of frames that were actually presented to the user
147 // that didn't miss the vsync deadline during this frame-sequence.
148 uint32_t frames_ontime = 0;
151 // Tracks the number of frames that is either submitted or reported as no
153 uint32_t frames_processed = 0;
155 // Tracks the number of begin-frames that are received.
156 uint32_t frames_received = 0;
160 void SetScrollingThread(FrameInfo::SmoothEffectDrivingThread thread);
162 struct CustomReportData {
163 uint32_t frames_expected = 0;
164 uint32_t frames_produced = 0;
167 using CustomReporter = base::OnceCallback<void(const CustomReportData& data)>;
168 // Sets reporter callback for kCustom typed sequence.
169 void SetCustomReporter(CustomReporter custom_reporter);
171 // Returns the 'effective thread' for the metrics (i.e. the thread most
172 // relevant for this metric).
173 FrameInfo::SmoothEffectDrivingThread GetEffectiveThread() const;
175 void Merge(std::unique_ptr<FrameSequenceMetrics> metrics);
176 bool HasEnoughDataForReporting() const;
177 bool HasDataLeftForReporting() const;
178 // Report related metrics: throughput, checkboarding...
179 void ReportMetrics();
181 void AddSortedFrame(const viz::BeginFrameArgs& args,
182 const FrameInfo& frame_info);
184 ThroughputData& impl_throughput() { return impl_throughput_; }
185 ThroughputData& main_throughput() { return main_throughput_; }
186 void add_checkerboarded_frames(int64_t frames) {
187 frames_checkerboarded_ += frames;
189 uint32_t frames_checkerboarded() const { return frames_checkerboarded_; }
191 FrameSequenceTrackerType type() const { return type_; }
192 ThroughputUkmReporter* ukm_reporter() const {
193 return throughput_ukm_reporter_;
196 // Must be called before destructor.
197 void ReportLeftoverData();
199 void AdoptTrace(FrameSequenceMetrics* adopt_from);
200 void AdvanceTrace(base::TimeTicks timestamp);
202 void ComputeJank(FrameInfo::SmoothEffectDrivingThread thread_type,
203 uint32_t frame_token,
204 base::TimeTicks presentation_time,
205 base::TimeDelta frame_interval);
207 void NotifySubmitForJankReporter(
208 FrameInfo::SmoothEffectDrivingThread thread_type,
209 uint32_t frame_token,
210 uint32_t sequence_number);
212 void NotifyNoUpdateForJankReporter(
213 FrameInfo::SmoothEffectDrivingThread thread_type,
214 uint32_t sequence_number,
215 base::TimeDelta frame_interval);
218 const FrameSequenceTrackerType type_;
220 // Tracks some data to generate useful trace events.
222 explicit TraceData(FrameSequenceMetrics* metrics);
224 raw_ptr<FrameSequenceMetrics> metrics;
225 base::TimeTicks last_timestamp = base::TimeTicks::Now();
227 bool enabled = false;
228 raw_ptr<void> trace_id = nullptr;
230 void Advance(base::TimeTicks new_timestamp,
236 // Pointer to the reporter owned by the FrameSequenceTrackerCollection.
237 const raw_ptr<ThroughputUkmReporter> throughput_ukm_reporter_;
239 // Track state for measuring the PercentDroppedFrames v2 metrics.
241 uint32_t frames_expected = 0;
242 uint32_t frames_dropped = 0;
245 // Track state for measuring the PercentDroppedFrames v3 metrics.
247 uint32_t frames_expected = 0;
248 uint32_t frames_dropped = 0;
251 ThroughputData impl_throughput_;
252 ThroughputData main_throughput_;
254 FrameInfo::SmoothEffectDrivingThread scrolling_thread_ =
255 FrameInfo::SmoothEffectDrivingThread::kUnknown;
257 // Tracks the number of produced frames that had some amount of
258 // checkerboarding, and how many frames showed such checkerboarded frames.
259 uint32_t frames_checkerboarded_ = 0;
261 // Callback invoked to report metrics for kCustom typed sequence.
262 CustomReporter custom_reporter_;
264 std::unique_ptr<JankMetrics> jank_reporter_;
267 bool ShouldReportForAnimation(FrameSequenceTrackerType sequence_type,
268 FrameInfo::SmoothEffectDrivingThread thread_type);
270 bool ShouldReportForInteraction(
271 FrameSequenceTrackerType sequence_type,
272 FrameInfo::SmoothEffectDrivingThread reporting_thread_type,
273 FrameInfo::SmoothEffectDrivingThread metrics_effective_thread_type);
277 #endif // CC_METRICS_FRAME_SEQUENCE_METRICS_H_