1 // Copyright 2020 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef CC_METRICS_FRAME_SEQUENCE_METRICS_H_ 6 #define CC_METRICS_FRAME_SEQUENCE_METRICS_H_ 7 8 #include <memory> 9 10 #include "base/callback.h" 11 #include "base/optional.h" 12 #include "base/trace_event/traced_value.h" 13 #include "cc/cc_export.h" 14 15 namespace cc { 16 class ThroughputUkmReporter; 17 class JankMetrics; 18 19 enum class FrameSequenceTrackerType { 20 // Used as an enum for metrics. DO NOT reorder or delete values. Rather, 21 // add them at the end and increment kMaxType. 22 kCompositorAnimation = 0, 23 kMainThreadAnimation = 1, 24 kPinchZoom = 2, 25 kRAF = 3, 26 kTouchScroll = 4, 27 kVideo = 6, 28 kWheelScroll = 7, 29 kScrollbarScroll = 8, 30 kCustom = 9, // Note that the metrics for kCustom are not reported on UMA, 31 // and instead are dispatched back to the LayerTreeHostClient. 32 kCanvasAnimation = 10, 33 kJSAnimation = 11, 34 kMaxType 35 }; 36 37 class CC_EXPORT FrameSequenceMetrics { 38 public: 39 FrameSequenceMetrics(FrameSequenceTrackerType type, 40 ThroughputUkmReporter* ukm_reporter); 41 ~FrameSequenceMetrics(); 42 43 FrameSequenceMetrics(const FrameSequenceMetrics&) = delete; 44 FrameSequenceMetrics& operator=(const FrameSequenceMetrics&) = delete; 45 46 enum class ThreadType { kMain, kCompositor, kUnknown }; 47 48 struct ThroughputData { 49 static std::unique_ptr<base::trace_event::TracedValue> ToTracedValue( 50 const ThroughputData& impl, 51 const ThroughputData& main, 52 ThreadType effective_thred); 53 54 static bool CanReportHistogram(FrameSequenceMetrics* metrics, 55 ThreadType thread_type, 56 const ThroughputData& data); 57 58 // Returns the dropped throughput in percent 59 static int ReportDroppedFramePercentHistogram(FrameSequenceMetrics* metrics, 60 ThreadType thread_type, 61 int metric_index, 62 const ThroughputData& data); 63 64 // Returns the missed deadline throughput in percent 65 static int ReportMissedDeadlineFramePercentHistogram( 66 FrameSequenceMetrics* metrics, 67 ThreadType thread_type, 68 int metric_index, 69 const ThroughputData& data); 70 MergeThroughputData71 void Merge(const ThroughputData& data) { 72 frames_expected += data.frames_expected; 73 frames_produced += data.frames_produced; 74 frames_ontime += data.frames_ontime; 75 #if DCHECK_IS_ON() 76 frames_processed += data.frames_processed; 77 frames_received += data.frames_received; 78 #endif 79 } 80 DroppedFramePercentThroughputData81 int DroppedFramePercent() const { 82 if (frames_expected == 0) 83 return 0; 84 return std::ceil(100 * (frames_expected - frames_produced) / 85 static_cast<double>(frames_expected)); 86 } 87 MissedDeadlineFramePercentThroughputData88 int MissedDeadlineFramePercent() const { 89 if (frames_produced == 0) 90 return 0; 91 return std::ceil(100 * (frames_produced - frames_ontime) / 92 static_cast<double>(frames_produced)); 93 } 94 95 // Tracks the number of frames that were expected to be shown during this 96 // frame-sequence. 97 uint32_t frames_expected = 0; 98 99 // Tracks the number of frames that were actually presented to the user 100 // during this frame-sequence. 101 uint32_t frames_produced = 0; 102 103 // Tracks the number of frames that were actually presented to the user 104 // that didn't miss the vsync deadline during this frame-sequence. 105 uint32_t frames_ontime = 0; 106 107 #if DCHECK_IS_ON() 108 // Tracks the number of frames that is either submitted or reported as no 109 // damage. 110 uint32_t frames_processed = 0; 111 112 // Tracks the number of begin-frames that are received. 113 uint32_t frames_received = 0; 114 #endif 115 }; 116 117 void SetScrollingThread(ThreadType thread); 118 119 struct CustomReportData { 120 uint32_t frames_expected = 0; 121 uint32_t frames_produced = 0; 122 uint32_t jank_count = 0; 123 }; 124 using CustomReporter = base::OnceCallback<void(const CustomReportData& data)>; 125 // Sets reporter callback for kCustom typed sequence. 126 void SetCustomReporter(CustomReporter custom_reporter); 127 128 // Returns the 'effective thread' for the metrics (i.e. the thread most 129 // relevant for this metric). 130 ThreadType GetEffectiveThread() const; 131 132 void Merge(std::unique_ptr<FrameSequenceMetrics> metrics); 133 bool HasEnoughDataForReporting() const; 134 bool HasDataLeftForReporting() const; 135 // Report related metrics: throughput, checkboarding... 136 void ReportMetrics(); 137 impl_throughput()138 ThroughputData& impl_throughput() { return impl_throughput_; } main_throughput()139 ThroughputData& main_throughput() { return main_throughput_; } add_checkerboarded_frames(int64_t frames)140 void add_checkerboarded_frames(int64_t frames) { 141 frames_checkerboarded_ += frames; 142 } frames_checkerboarded()143 uint32_t frames_checkerboarded() const { return frames_checkerboarded_; } 144 type()145 FrameSequenceTrackerType type() const { return type_; } ukm_reporter()146 ThroughputUkmReporter* ukm_reporter() const { 147 return throughput_ukm_reporter_; 148 } 149 150 // Must be called before destructor. 151 void ReportLeftoverData(); 152 153 void AdoptTrace(FrameSequenceMetrics* adopt_from); 154 void AdvanceTrace(base::TimeTicks timestamp); 155 156 void ComputeJank(FrameSequenceMetrics::ThreadType thread_type, 157 uint32_t frame_token, 158 base::TimeTicks presentation_time, 159 base::TimeDelta frame_interval); 160 161 void NotifySubmitForJankReporter(FrameSequenceMetrics::ThreadType thread_type, 162 uint32_t frame_token, 163 uint32_t sequence_number); 164 165 void NotifyNoUpdateForJankReporter( 166 FrameSequenceMetrics::ThreadType thread_type, 167 uint32_t sequence_number, 168 base::TimeDelta frame_interval); 169 170 private: 171 const FrameSequenceTrackerType type_; 172 173 // Tracks some data to generate useful trace events. 174 struct TraceData { 175 explicit TraceData(FrameSequenceMetrics* metrics); 176 ~TraceData(); 177 FrameSequenceMetrics* metrics; 178 base::TimeTicks last_timestamp = base::TimeTicks::Now(); 179 int frame_count = 0; 180 bool enabled = false; 181 void* trace_id = nullptr; 182 183 void Advance(base::TimeTicks new_timestamp); 184 void Terminate(); 185 } trace_data_{this}; 186 187 // Pointer to the reporter owned by the FrameSequenceTrackerCollection. 188 ThroughputUkmReporter* const throughput_ukm_reporter_; 189 190 ThroughputData impl_throughput_; 191 ThroughputData main_throughput_; 192 193 ThreadType scrolling_thread_ = ThreadType::kUnknown; 194 195 // Tracks the number of produced frames that had some amount of 196 // checkerboarding, and how many frames showed such checkerboarded frames. 197 uint32_t frames_checkerboarded_ = 0; 198 199 // Callback invoked to report metrics for kCustom typed sequence. 200 CustomReporter custom_reporter_; 201 202 std::unique_ptr<JankMetrics> jank_reporter_; 203 }; 204 205 } // namespace cc 206 207 #endif // CC_METRICS_FRAME_SEQUENCE_METRICS_H_ 208