Sadrul Habib Chowdhury | ab4d350f | 2019-07-13 00:17:37 | [diff] [blame] | 1 | // Copyright 2019 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 | |
behdad | 5fb48ea2 | 2019-08-12 18:15:36 | [diff] [blame] | 5 | #include "cc/metrics/frame_sequence_tracker.h" |
Sadrul Habib Chowdhury | ab4d350f | 2019-07-13 00:17:37 | [diff] [blame] | 6 | |
Sadrul Habib Chowdhury | db3d7be7 | 2019-07-13 03:27:32 | [diff] [blame] | 7 | #include "base/metrics/histogram.h" |
| 8 | #include "base/metrics/histogram_macros.h" |
Sadrul Habib Chowdhury | 40a4d8c | 2019-09-05 03:02:31 | [diff] [blame] | 9 | #include "base/stl_util.h" |
Sadrul Habib Chowdhury | db3d7be7 | 2019-07-13 03:27:32 | [diff] [blame] | 10 | #include "base/strings/strcat.h" |
Sadrul Habib Chowdhury | ab4d350f | 2019-07-13 00:17:37 | [diff] [blame] | 11 | #include "base/trace_event/trace_event.h" |
| 12 | #include "base/trace_event/traced_value.h" |
behdad | e9ae6e1 | 2019-08-20 23:02:25 | [diff] [blame] | 13 | #include "cc/metrics/compositor_frame_reporting_controller.h" |
Xida Chen | 4ede1d69 | 2019-11-22 18:00:48 | [diff] [blame] | 14 | #include "cc/metrics/throughput_ukm_reporter.h" |
| 15 | #include "cc/trees/ukm_manager.h" |
Sadrul Habib Chowdhury | ab4d350f | 2019-07-13 00:17:37 | [diff] [blame] | 16 | #include "components/viz/common/frame_sinks/begin_frame_args.h" |
| 17 | #include "components/viz/common/quads/compositor_frame_metadata.h" |
| 18 | #include "ui/gfx/presentation_feedback.h" |
| 19 | |
Mingjing Zhang | 2879aa89 | 2019-11-01 02:54:54 | [diff] [blame] | 20 | // This macro is used with DCHECK to provide addition debug info. |
Mingjing Zhang | 9431496 | 2019-11-05 02:59:20 | [diff] [blame] | 21 | #if DCHECK_IS_ON() |
Mingjing Zhang | c0ce541 | 2019-11-07 22:00:07 | [diff] [blame] | 22 | #define TRACKER_TRACE_STREAM frame_sequence_trace_ |
behdad | a108d81 | 2019-11-20 17:22:39 | [diff] [blame] | 23 | #define TRACKER_DCHECK_MSG \ |
| 24 | " in " << GetFrameSequenceTrackerTypeName(static_cast<int>(this->type_)) \ |
| 25 | << " tracker: " << frame_sequence_trace_.str() << " (" \ |
Mingjing Zhang | c0ce541 | 2019-11-07 22:00:07 | [diff] [blame] | 26 | << frame_sequence_trace_.str().size() << ")"; |
Mingjing Zhang | 9431496 | 2019-11-05 02:59:20 | [diff] [blame] | 27 | #else |
Mingjing Zhang | c0ce541 | 2019-11-07 22:00:07 | [diff] [blame] | 28 | #define TRACKER_TRACE_STREAM EAT_STREAM_PARAMETERS |
Mingjing Zhang | 9431496 | 2019-11-05 02:59:20 | [diff] [blame] | 29 | #define TRACKER_DCHECK_MSG "" |
| 30 | #endif |
Mingjing Zhang | 2879aa89 | 2019-11-01 02:54:54 | [diff] [blame] | 31 | |
Sadrul Habib Chowdhury | ab4d350f | 2019-07-13 00:17:37 | [diff] [blame] | 32 | namespace cc { |
| 33 | |
behdad | a108d81 | 2019-11-20 17:22:39 | [diff] [blame] | 34 | const char* FrameSequenceTracker::GetFrameSequenceTrackerTypeName( |
| 35 | int type_index) { |
| 36 | switch (type_index) { |
| 37 | case static_cast<int>(FrameSequenceTrackerType::kCompositorAnimation): |
| 38 | return "CompositorAnimation"; |
| 39 | case static_cast<int>(FrameSequenceTrackerType::kMainThreadAnimation): |
| 40 | return "MainThreadAnimation"; |
| 41 | case static_cast<int>(FrameSequenceTrackerType::kPinchZoom): |
| 42 | return "PinchZoom"; |
| 43 | case static_cast<int>(FrameSequenceTrackerType::kRAF): |
| 44 | return "RAF"; |
| 45 | case static_cast<int>(FrameSequenceTrackerType::kTouchScroll): |
| 46 | return "TouchScroll"; |
| 47 | case static_cast<int>(FrameSequenceTrackerType::kUniversal): |
| 48 | return "Universal"; |
| 49 | case static_cast<int>(FrameSequenceTrackerType::kVideo): |
| 50 | return "Video"; |
| 51 | case static_cast<int>(FrameSequenceTrackerType::kWheelScroll): |
| 52 | return "WheelScroll"; |
| 53 | default: |
| 54 | return ""; |
| 55 | } |
| 56 | } |
Xida Chen | 78ba8b7 | 2019-08-30 14:49:25 | [diff] [blame] | 57 | |
Sadrul Habib Chowdhury | db3d7be7 | 2019-07-13 03:27:32 | [diff] [blame] | 58 | namespace { |
| 59 | |
Sadrul Habib Chowdhury | 590a32f | 2019-12-06 20:08:45 | [diff] [blame] | 60 | // Avoid reporting any throughput metric for sequences that do not have a |
| 61 | // sufficient number of frames. |
| 62 | constexpr int kMinFramesForThroughputMetric = 100; |
Sadrul Habib Chowdhury | 40a4d8c | 2019-09-05 03:02:31 | [diff] [blame] | 63 | |
behdad | a108d81 | 2019-11-20 17:22:39 | [diff] [blame] | 64 | constexpr int kBuiltinSequenceNum = FrameSequenceTrackerType::kMaxType + 1; |
Xida Chen | f8afda3 | 2019-09-25 01:46:07 | [diff] [blame] | 65 | constexpr int kMaximumHistogramIndex = 3 * kBuiltinSequenceNum; |
Sadrul Habib Chowdhury | db3d7be7 | 2019-07-13 03:27:32 | [diff] [blame] | 66 | |
Sadrul Habib Chowdhury | d4e8f4a | 2019-12-13 15:10:27 | [diff] [blame] | 67 | int GetIndexForMetric(FrameSequenceMetrics::ThreadType thread_type, |
Xida Chen | 4ede1d69 | 2019-11-22 18:00:48 | [diff] [blame] | 68 | FrameSequenceTrackerType type) { |
Sadrul Habib Chowdhury | d4e8f4a | 2019-12-13 15:10:27 | [diff] [blame] | 69 | if (thread_type == FrameSequenceMetrics::ThreadType::kMain) |
Xida Chen | f8afda3 | 2019-09-25 01:46:07 | [diff] [blame] | 70 | return static_cast<int>(type); |
Sadrul Habib Chowdhury | d4e8f4a | 2019-12-13 15:10:27 | [diff] [blame] | 71 | if (thread_type == FrameSequenceMetrics::ThreadType::kCompositor) |
Xida Chen | f8afda3 | 2019-09-25 01:46:07 | [diff] [blame] | 72 | return static_cast<int>(type + kBuiltinSequenceNum); |
| 73 | return static_cast<int>(type + 2 * kBuiltinSequenceNum); |
Sadrul Habib Chowdhury | db3d7be7 | 2019-07-13 03:27:32 | [diff] [blame] | 74 | } |
| 75 | |
Sadrul Habib Chowdhury | 4bba3d0 | 2019-09-06 02:33:27 | [diff] [blame] | 76 | std::string GetCheckerboardingHistogramName(FrameSequenceTrackerType type) { |
behdad | a108d81 | 2019-11-20 17:22:39 | [diff] [blame] | 77 | return base::StrCat({"Graphics.Smoothness.Checkerboarding.", |
| 78 | FrameSequenceTracker::GetFrameSequenceTrackerTypeName( |
| 79 | static_cast<int>(type))}); |
Sadrul Habib Chowdhury | 4bba3d0 | 2019-09-06 02:33:27 | [diff] [blame] | 80 | } |
| 81 | |
| 82 | std::string GetThroughputHistogramName(FrameSequenceTrackerType type, |
| 83 | const char* thread_name) { |
behdad | a108d81 | 2019-11-20 17:22:39 | [diff] [blame] | 84 | return base::StrCat({"Graphics.Smoothness.Throughput.", thread_name, ".", |
| 85 | FrameSequenceTracker::GetFrameSequenceTrackerTypeName( |
| 86 | static_cast<int>(type))}); |
Sadrul Habib Chowdhury | 4bba3d0 | 2019-09-06 02:33:27 | [diff] [blame] | 87 | } |
| 88 | |
| 89 | std::string GetFrameSequenceLengthHistogramName(FrameSequenceTrackerType type) { |
behdad | a108d81 | 2019-11-20 17:22:39 | [diff] [blame] | 90 | return base::StrCat({"Graphics.Smoothness.FrameSequenceLength.", |
| 91 | FrameSequenceTracker::GetFrameSequenceTrackerTypeName( |
| 92 | static_cast<int>(type))}); |
Sadrul Habib Chowdhury | 4bba3d0 | 2019-09-06 02:33:27 | [diff] [blame] | 93 | } |
| 94 | |
Sadrul Habib Chowdhury | 3ebe0382 | 2019-12-16 18:29:20 | [diff] [blame] | 95 | bool ShouldReportForAnimation(FrameSequenceTrackerType sequence_type, |
| 96 | FrameSequenceMetrics::ThreadType thread_type) { |
| 97 | if (sequence_type == FrameSequenceTrackerType::kCompositorAnimation) |
| 98 | return thread_type == FrameSequenceMetrics::ThreadType::kCompositor; |
| 99 | |
| 100 | if (sequence_type == FrameSequenceTrackerType::kMainThreadAnimation || |
| 101 | sequence_type == FrameSequenceTrackerType::kRAF) |
| 102 | return thread_type == FrameSequenceMetrics::ThreadType::kMain; |
| 103 | |
| 104 | return false; |
| 105 | } |
| 106 | |
| 107 | bool ShouldReportForInteraction(FrameSequenceTrackerType sequence_type, |
| 108 | FrameSequenceMetrics::ThreadType thread_type) { |
| 109 | // For touch/wheel scroll, the slower thread is the one we want to report. For |
| 110 | // pinch-zoom, it's the compositor-thread. |
| 111 | if (sequence_type == FrameSequenceTrackerType::kTouchScroll || |
| 112 | sequence_type == FrameSequenceTrackerType::kWheelScroll) |
| 113 | return thread_type == FrameSequenceMetrics::ThreadType::kSlower; |
| 114 | |
| 115 | if (sequence_type == FrameSequenceTrackerType::kPinchZoom) |
| 116 | return thread_type == FrameSequenceMetrics::ThreadType::kCompositor; |
| 117 | |
| 118 | return false; |
| 119 | } |
| 120 | |
Sadrul Habib Chowdhury | db3d7be7 | 2019-07-13 03:27:32 | [diff] [blame] | 121 | } // namespace |
| 122 | |
Sadrul Habib Chowdhury | ab4d350f | 2019-07-13 00:17:37 | [diff] [blame] | 123 | //////////////////////////////////////////////////////////////////////////////// |
Sadrul Habib Chowdhury | c537f2f4 | 2019-12-05 19:52:28 | [diff] [blame] | 124 | // FrameSequenceMetrics |
| 125 | |
| 126 | FrameSequenceMetrics::FrameSequenceMetrics(FrameSequenceTrackerType type, |
| 127 | UkmManager* ukm_manager, |
| 128 | ThroughputUkmReporter* ukm_reporter) |
| 129 | : type_(type), |
| 130 | ukm_manager_(ukm_manager), |
| 131 | throughput_ukm_reporter_(ukm_reporter) { |
| 132 | TRACE_EVENT_ASYNC_BEGIN1( |
| 133 | "cc,benchmark", "FrameSequenceTracker", this, "name", |
| 134 | FrameSequenceTracker::GetFrameSequenceTrackerTypeName( |
| 135 | static_cast<int>(type_))); |
| 136 | } |
| 137 | |
| 138 | FrameSequenceMetrics::~FrameSequenceMetrics() { |
Sadrul Habib Chowdhury | 590a32f | 2019-12-06 20:08:45 | [diff] [blame] | 139 | if (HasDataLeftForReporting()) |
| 140 | ReportMetrics(); |
| 141 | } |
| 142 | |
| 143 | void FrameSequenceMetrics::Merge( |
| 144 | std::unique_ptr<FrameSequenceMetrics> metrics) { |
| 145 | DCHECK_EQ(type_, metrics->type_); |
| 146 | impl_throughput_.Merge(metrics->impl_throughput_); |
| 147 | main_throughput_.Merge(metrics->main_throughput_); |
| 148 | frames_checkerboarded_ += metrics->frames_checkerboarded_; |
| 149 | |
| 150 | // Reset the state of |metrics| before destroying it, so that it doesn't end |
| 151 | // up reporting the metrics. |
| 152 | metrics->impl_throughput_ = {}; |
| 153 | metrics->main_throughput_ = {}; |
| 154 | metrics->frames_checkerboarded_ = 0; |
| 155 | } |
| 156 | |
| 157 | bool FrameSequenceMetrics::HasEnoughDataForReporting() const { |
| 158 | return impl_throughput_.frames_expected >= kMinFramesForThroughputMetric || |
| 159 | main_throughput_.frames_expected >= kMinFramesForThroughputMetric; |
| 160 | } |
| 161 | |
| 162 | bool FrameSequenceMetrics::HasDataLeftForReporting() const { |
| 163 | return impl_throughput_.frames_expected > 0 || |
| 164 | main_throughput_.frames_expected > 0; |
| 165 | } |
| 166 | |
| 167 | void FrameSequenceMetrics::ReportMetrics() { |
Sadrul Habib Chowdhury | c537f2f4 | 2019-12-05 19:52:28 | [diff] [blame] | 168 | DCHECK_LE(impl_throughput_.frames_produced, impl_throughput_.frames_expected); |
| 169 | DCHECK_LE(main_throughput_.frames_produced, main_throughput_.frames_expected); |
Sadrul Habib Chowdhury | c537f2f4 | 2019-12-05 19:52:28 | [diff] [blame] | 170 | TRACE_EVENT_ASYNC_END2( |
| 171 | "cc,benchmark", "FrameSequenceTracker", this, "args", |
| 172 | ThroughputData::ToTracedValue(impl_throughput_, main_throughput_), |
| 173 | "checkerboard", frames_checkerboarded_); |
Sadrul Habib Chowdhury | c537f2f4 | 2019-12-05 19:52:28 | [diff] [blame] | 174 | |
Sadrul Habib Chowdhury | c537f2f4 | 2019-12-05 19:52:28 | [diff] [blame] | 175 | // Report the throughput metrics. |
| 176 | base::Optional<int> impl_throughput_percent = ThroughputData::ReportHistogram( |
Sadrul Habib Chowdhury | d4e8f4a | 2019-12-13 15:10:27 | [diff] [blame] | 177 | type_, ThreadType::kCompositor, |
| 178 | GetIndexForMetric(FrameSequenceMetrics::ThreadType::kCompositor, type_), |
Sadrul Habib Chowdhury | c537f2f4 | 2019-12-05 19:52:28 | [diff] [blame] | 179 | impl_throughput_); |
| 180 | base::Optional<int> main_throughput_percent = ThroughputData::ReportHistogram( |
Sadrul Habib Chowdhury | d4e8f4a | 2019-12-13 15:10:27 | [diff] [blame] | 181 | type_, ThreadType::kMain, |
| 182 | GetIndexForMetric(FrameSequenceMetrics::ThreadType::kMain, type_), |
Sadrul Habib Chowdhury | c537f2f4 | 2019-12-05 19:52:28 | [diff] [blame] | 183 | main_throughput_); |
| 184 | |
| 185 | base::Optional<ThroughputData> slower_throughput; |
| 186 | base::Optional<int> slower_throughput_percent; |
| 187 | if (impl_throughput_percent && |
| 188 | (!main_throughput_percent || |
| 189 | impl_throughput_percent.value() <= main_throughput_percent.value())) { |
| 190 | slower_throughput = impl_throughput_; |
| 191 | } |
| 192 | if (main_throughput_percent && |
| 193 | (!impl_throughput_percent || |
| 194 | main_throughput_percent.value() < impl_throughput_percent.value())) { |
| 195 | slower_throughput = main_throughput_; |
| 196 | } |
| 197 | if (slower_throughput.has_value()) { |
| 198 | slower_throughput_percent = ThroughputData::ReportHistogram( |
Sadrul Habib Chowdhury | d4e8f4a | 2019-12-13 15:10:27 | [diff] [blame] | 199 | type_, ThreadType::kSlower, |
| 200 | GetIndexForMetric(FrameSequenceMetrics::ThreadType::kSlower, type_), |
Sadrul Habib Chowdhury | c537f2f4 | 2019-12-05 19:52:28 | [diff] [blame] | 201 | slower_throughput.value()); |
| 202 | DCHECK(slower_throughput_percent.has_value()); |
| 203 | } |
| 204 | |
| 205 | // slower_throughput has value indicates that we have reported UMA. |
| 206 | if (slower_throughput.has_value() && ukm_manager_ && |
| 207 | throughput_ukm_reporter_) { |
| 208 | throughput_ukm_reporter_->ReportThroughputUkm( |
| 209 | ukm_manager_, slower_throughput_percent, impl_throughput_percent, |
| 210 | main_throughput_percent, type_); |
| 211 | } |
| 212 | |
| 213 | // Report the checkerboarding metrics. |
| 214 | if (impl_throughput_.frames_expected >= kMinFramesForThroughputMetric) { |
| 215 | const int checkerboarding_percent = static_cast<int>( |
| 216 | 100 * frames_checkerboarded_ / impl_throughput_.frames_expected); |
| 217 | STATIC_HISTOGRAM_POINTER_GROUP( |
| 218 | GetCheckerboardingHistogramName(type_), type_, |
| 219 | FrameSequenceTrackerType::kMaxType, Add(checkerboarding_percent), |
| 220 | base::LinearHistogram::FactoryGet( |
| 221 | GetCheckerboardingHistogramName(type_), 1, 100, 101, |
| 222 | base::HistogramBase::kUmaTargetedHistogramFlag)); |
Sadrul Habib Chowdhury | 590a32f | 2019-12-06 20:08:45 | [diff] [blame] | 223 | frames_checkerboarded_ = 0; |
Sadrul Habib Chowdhury | c537f2f4 | 2019-12-05 19:52:28 | [diff] [blame] | 224 | } |
Sadrul Habib Chowdhury | 590a32f | 2019-12-06 20:08:45 | [diff] [blame] | 225 | |
| 226 | // Reset the metrics that have already been reported. |
| 227 | if (impl_throughput_percent.has_value()) |
| 228 | impl_throughput_ = {}; |
| 229 | if (main_throughput_percent.has_value()) |
| 230 | main_throughput_ = {}; |
Sadrul Habib Chowdhury | c537f2f4 | 2019-12-05 19:52:28 | [diff] [blame] | 231 | } |
| 232 | |
| 233 | //////////////////////////////////////////////////////////////////////////////// |
Sadrul Habib Chowdhury | ab4d350f | 2019-07-13 00:17:37 | [diff] [blame] | 234 | // FrameSequenceTrackerCollection |
| 235 | |
behdad | e9ae6e1 | 2019-08-20 23:02:25 | [diff] [blame] | 236 | FrameSequenceTrackerCollection::FrameSequenceTrackerCollection( |
Sadrul Habib Chowdhury | 43dd14a | 2019-09-18 20:13:37 | [diff] [blame] | 237 | bool is_single_threaded, |
behdad | e9ae6e1 | 2019-08-20 23:02:25 | [diff] [blame] | 238 | CompositorFrameReportingController* compositor_frame_reporting_controller) |
Sadrul Habib Chowdhury | 43dd14a | 2019-09-18 20:13:37 | [diff] [blame] | 239 | : is_single_threaded_(is_single_threaded), |
| 240 | compositor_frame_reporting_controller_( |
Xida Chen | 4ede1d69 | 2019-11-22 18:00:48 | [diff] [blame] | 241 | compositor_frame_reporting_controller), |
| 242 | throughput_ukm_reporter_(std::make_unique<ThroughputUkmReporter>()) {} |
Xida Chen | bad8e2b | 2019-08-27 18:19:37 | [diff] [blame] | 243 | |
Sadrul Habib Chowdhury | ab4d350f | 2019-07-13 00:17:37 | [diff] [blame] | 244 | FrameSequenceTrackerCollection::~FrameSequenceTrackerCollection() { |
Xida Chen | bad8e2b | 2019-08-27 18:19:37 | [diff] [blame] | 245 | frame_trackers_.clear(); |
Sadrul Habib Chowdhury | ab4d350f | 2019-07-13 00:17:37 | [diff] [blame] | 246 | removal_trackers_.clear(); |
Sadrul Habib Chowdhury | ab4d350f | 2019-07-13 00:17:37 | [diff] [blame] | 247 | } |
| 248 | |
Xida Chen | bad8e2b | 2019-08-27 18:19:37 | [diff] [blame] | 249 | void FrameSequenceTrackerCollection::StartSequence( |
| 250 | FrameSequenceTrackerType type) { |
Sadrul Habib Chowdhury | 43dd14a | 2019-09-18 20:13:37 | [diff] [blame] | 251 | if (is_single_threaded_) |
| 252 | return; |
Xida Chen | bad8e2b | 2019-08-27 18:19:37 | [diff] [blame] | 253 | if (frame_trackers_.contains(type)) |
| 254 | return; |
Xida Chen | 4ede1d69 | 2019-11-22 18:00:48 | [diff] [blame] | 255 | auto tracker = base::WrapUnique(new FrameSequenceTracker( |
| 256 | type, ukm_manager_, throughput_ukm_reporter_.get())); |
Xida Chen | bad8e2b | 2019-08-27 18:19:37 | [diff] [blame] | 257 | frame_trackers_[type] = std::move(tracker); |
behdad | e9ae6e1 | 2019-08-20 23:02:25 | [diff] [blame] | 258 | |
Mingjing Zhang | 2aa30ae | 2019-08-28 17:36:43 | [diff] [blame] | 259 | if (compositor_frame_reporting_controller_) |
| 260 | compositor_frame_reporting_controller_->AddActiveTracker(type); |
Sadrul Habib Chowdhury | ab4d350f | 2019-07-13 00:17:37 | [diff] [blame] | 261 | } |
| 262 | |
Xida Chen | bad8e2b | 2019-08-27 18:19:37 | [diff] [blame] | 263 | void FrameSequenceTrackerCollection::StopSequence( |
| 264 | FrameSequenceTrackerType type) { |
| 265 | if (!frame_trackers_.contains(type)) |
Sadrul Habib Chowdhury | ab4d350f | 2019-07-13 00:17:37 | [diff] [blame] | 266 | return; |
behdad | e9ae6e1 | 2019-08-20 23:02:25 | [diff] [blame] | 267 | |
Xida Chen | bad8e2b | 2019-08-27 18:19:37 | [diff] [blame] | 268 | std::unique_ptr<FrameSequenceTracker> tracker = |
| 269 | std::move(frame_trackers_[type]); |
Mingjing Zhang | 2aa30ae | 2019-08-28 17:36:43 | [diff] [blame] | 270 | |
| 271 | if (compositor_frame_reporting_controller_) |
| 272 | compositor_frame_reporting_controller_->RemoveActiveTracker(tracker->type_); |
| 273 | |
Xida Chen | bad8e2b | 2019-08-27 18:19:37 | [diff] [blame] | 274 | frame_trackers_.erase(type); |
Sadrul Habib Chowdhury | ab4d350f | 2019-07-13 00:17:37 | [diff] [blame] | 275 | tracker->ScheduleTerminate(); |
| 276 | removal_trackers_.push_back(std::move(tracker)); |
| 277 | } |
| 278 | |
| 279 | void FrameSequenceTrackerCollection::ClearAll() { |
Xida Chen | bad8e2b | 2019-08-27 18:19:37 | [diff] [blame] | 280 | frame_trackers_.clear(); |
Sadrul Habib Chowdhury | ab4d350f | 2019-07-13 00:17:37 | [diff] [blame] | 281 | removal_trackers_.clear(); |
Sadrul Habib Chowdhury | ab4d350f | 2019-07-13 00:17:37 | [diff] [blame] | 282 | } |
| 283 | |
| 284 | void FrameSequenceTrackerCollection::NotifyBeginImplFrame( |
| 285 | const viz::BeginFrameArgs& args) { |
Xida Chen | 1102307b | 2019-10-11 17:03:15 | [diff] [blame] | 286 | RecreateTrackers(args); |
| 287 | for (auto& tracker : frame_trackers_) |
Xida Chen | bad8e2b | 2019-08-27 18:19:37 | [diff] [blame] | 288 | tracker.second->ReportBeginImplFrame(args); |
Sadrul Habib Chowdhury | ab4d350f | 2019-07-13 00:17:37 | [diff] [blame] | 289 | } |
| 290 | |
| 291 | void FrameSequenceTrackerCollection::NotifyBeginMainFrame( |
| 292 | const viz::BeginFrameArgs& args) { |
Xida Chen | 1102307b | 2019-10-11 17:03:15 | [diff] [blame] | 293 | for (auto& tracker : frame_trackers_) |
Xida Chen | bad8e2b | 2019-08-27 18:19:37 | [diff] [blame] | 294 | tracker.second->ReportBeginMainFrame(args); |
Sadrul Habib Chowdhury | ab4d350f | 2019-07-13 00:17:37 | [diff] [blame] | 295 | } |
| 296 | |
| 297 | void FrameSequenceTrackerCollection::NotifyImplFrameCausedNoDamage( |
| 298 | const viz::BeginFrameAck& ack) { |
Xida Chen | bad8e2b | 2019-08-27 18:19:37 | [diff] [blame] | 299 | for (auto& tracker : frame_trackers_) { |
| 300 | tracker.second->ReportImplFrameCausedNoDamage(ack); |
Sadrul Habib Chowdhury | ab4d350f | 2019-07-13 00:17:37 | [diff] [blame] | 301 | } |
| 302 | } |
| 303 | |
| 304 | void FrameSequenceTrackerCollection::NotifyMainFrameCausedNoDamage( |
| 305 | const viz::BeginFrameArgs& args) { |
Xida Chen | bad8e2b | 2019-08-27 18:19:37 | [diff] [blame] | 306 | for (auto& tracker : frame_trackers_) { |
| 307 | tracker.second->ReportMainFrameCausedNoDamage(args); |
Sadrul Habib Chowdhury | ab4d350f | 2019-07-13 00:17:37 | [diff] [blame] | 308 | } |
| 309 | } |
| 310 | |
| 311 | void FrameSequenceTrackerCollection::NotifyPauseFrameProduction() { |
Xida Chen | bad8e2b | 2019-08-27 18:19:37 | [diff] [blame] | 312 | for (auto& tracker : frame_trackers_) |
| 313 | tracker.second->PauseFrameProduction(); |
Sadrul Habib Chowdhury | ab4d350f | 2019-07-13 00:17:37 | [diff] [blame] | 314 | } |
| 315 | |
| 316 | void FrameSequenceTrackerCollection::NotifySubmitFrame( |
| 317 | uint32_t frame_token, |
Sadrul Habib Chowdhury | 40a4d8c | 2019-09-05 03:02:31 | [diff] [blame] | 318 | bool has_missing_content, |
Sadrul Habib Chowdhury | ab4d350f | 2019-07-13 00:17:37 | [diff] [blame] | 319 | const viz::BeginFrameAck& ack, |
| 320 | const viz::BeginFrameArgs& origin_args) { |
Xida Chen | bad8e2b | 2019-08-27 18:19:37 | [diff] [blame] | 321 | for (auto& tracker : frame_trackers_) { |
Sadrul Habib Chowdhury | 40a4d8c | 2019-09-05 03:02:31 | [diff] [blame] | 322 | tracker.second->ReportSubmitFrame(frame_token, has_missing_content, ack, |
| 323 | origin_args); |
Sadrul Habib Chowdhury | ab4d350f | 2019-07-13 00:17:37 | [diff] [blame] | 324 | } |
| 325 | } |
| 326 | |
Sadrul Habib Chowdhury | 7fe10ea | 2019-12-11 01:59:29 | [diff] [blame] | 327 | void FrameSequenceTrackerCollection::NotifyFrameEnd( |
| 328 | const viz::BeginFrameArgs& args) { |
| 329 | for (auto& tracker : frame_trackers_) { |
| 330 | tracker.second->ReportFrameEnd(args); |
| 331 | } |
| 332 | } |
| 333 | |
Sadrul Habib Chowdhury | ab4d350f | 2019-07-13 00:17:37 | [diff] [blame] | 334 | void FrameSequenceTrackerCollection::NotifyFramePresented( |
| 335 | uint32_t frame_token, |
| 336 | const gfx::PresentationFeedback& feedback) { |
Xida Chen | bad8e2b | 2019-08-27 18:19:37 | [diff] [blame] | 337 | for (auto& tracker : frame_trackers_) |
| 338 | tracker.second->ReportFramePresented(frame_token, feedback); |
Sadrul Habib Chowdhury | ab4d350f | 2019-07-13 00:17:37 | [diff] [blame] | 339 | |
Xida Chen | a4f48f939 | 2019-08-30 16:53:24 | [diff] [blame] | 340 | for (auto& tracker : removal_trackers_) |
| 341 | tracker->ReportFramePresented(frame_token, feedback); |
| 342 | |
Sadrul Habib Chowdhury | 590a32f | 2019-12-06 20:08:45 | [diff] [blame] | 343 | for (auto& tracker : removal_trackers_) { |
| 344 | if (tracker->termination_status() == |
| 345 | FrameSequenceTracker::TerminationStatus::kReadyForTermination) { |
| 346 | // The tracker is ready to be terminated. Take the metrics from the |
| 347 | // tracker, merge with any outstanding metrics from previous trackers of |
| 348 | // the same type. If there are enough frames to report the metrics, then |
| 349 | // report the metrics and destroy it. Otherwise, retain it to be merged |
| 350 | // with follow-up sequences. |
| 351 | auto metrics = tracker->TakeMetrics(); |
| 352 | if (accumulated_metrics_.contains(tracker->type())) { |
| 353 | metrics->Merge(std::move(accumulated_metrics_[tracker->type()])); |
| 354 | accumulated_metrics_.erase(tracker->type()); |
| 355 | } |
| 356 | if (metrics->HasEnoughDataForReporting()) |
| 357 | metrics->ReportMetrics(); |
| 358 | if (metrics->HasDataLeftForReporting()) |
| 359 | accumulated_metrics_[tracker->type()] = std::move(metrics); |
| 360 | } |
| 361 | } |
| 362 | |
Sadrul Habib Chowdhury | ab4d350f | 2019-07-13 00:17:37 | [diff] [blame] | 363 | // Destroy the trackers that are ready to be terminated. |
| 364 | base::EraseIf( |
| 365 | removal_trackers_, |
| 366 | [](const std::unique_ptr<FrameSequenceTracker>& tracker) { |
| 367 | return tracker->termination_status() == |
| 368 | FrameSequenceTracker::TerminationStatus::kReadyForTermination; |
| 369 | }); |
| 370 | } |
| 371 | |
Xida Chen | 1102307b | 2019-10-11 17:03:15 | [diff] [blame] | 372 | void FrameSequenceTrackerCollection::RecreateTrackers( |
| 373 | const viz::BeginFrameArgs& args) { |
| 374 | std::vector<FrameSequenceTrackerType> recreate_trackers; |
| 375 | for (const auto& tracker : frame_trackers_) { |
| 376 | if (tracker.second->ShouldReportMetricsNow(args)) |
| 377 | recreate_trackers.push_back(tracker.first); |
| 378 | } |
| 379 | |
| 380 | for (const auto& tracker_type : recreate_trackers) { |
| 381 | // StopSequence put the tracker in the |removal_trackers_|, which will |
| 382 | // report its throughput data when its frame is presented. |
| 383 | StopSequence(tracker_type); |
| 384 | // The frame sequence is still active, so create a new tracker to keep |
| 385 | // tracking this sequence. |
| 386 | StartSequence(tracker_type); |
| 387 | } |
| 388 | } |
| 389 | |
Xida Chen | bad8e2b | 2019-08-27 18:19:37 | [diff] [blame] | 390 | FrameSequenceTracker* FrameSequenceTrackerCollection::GetTrackerForTesting( |
| 391 | FrameSequenceTrackerType type) { |
| 392 | if (!frame_trackers_.contains(type)) |
| 393 | return nullptr; |
| 394 | return frame_trackers_[type].get(); |
Sadrul Habib Chowdhury | ab4d350f | 2019-07-13 00:17:37 | [diff] [blame] | 395 | } |
| 396 | |
Xida Chen | 4ede1d69 | 2019-11-22 18:00:48 | [diff] [blame] | 397 | void FrameSequenceTrackerCollection::SetUkmManager(UkmManager* manager) { |
| 398 | DCHECK(frame_trackers_.empty()); |
| 399 | ukm_manager_ = manager; |
| 400 | } |
| 401 | |
Sadrul Habib Chowdhury | ab4d350f | 2019-07-13 00:17:37 | [diff] [blame] | 402 | //////////////////////////////////////////////////////////////////////////////// |
| 403 | // FrameSequenceTracker |
| 404 | |
Xida Chen | 4ede1d69 | 2019-11-22 18:00:48 | [diff] [blame] | 405 | FrameSequenceTracker::FrameSequenceTracker( |
| 406 | FrameSequenceTrackerType type, |
| 407 | UkmManager* manager, |
| 408 | ThroughputUkmReporter* throughput_ukm_reporter) |
Sadrul Habib Chowdhury | 590a32f | 2019-12-06 20:08:45 | [diff] [blame] | 409 | : type_(type), |
| 410 | metrics_( |
| 411 | std::make_unique<FrameSequenceMetrics>(type, |
| 412 | manager, |
| 413 | throughput_ukm_reporter)) { |
Sadrul Habib Chowdhury | db3d7be7 | 2019-07-13 03:27:32 | [diff] [blame] | 414 | DCHECK_LT(type_, FrameSequenceTrackerType::kMaxType); |
Sadrul Habib Chowdhury | ab4d350f | 2019-07-13 00:17:37 | [diff] [blame] | 415 | } |
| 416 | |
| 417 | FrameSequenceTracker::~FrameSequenceTracker() { |
Xida Chen | f8afda3 | 2019-09-25 01:46:07 | [diff] [blame] | 418 | } |
Sadrul Habib Chowdhury | 40a4d8c | 2019-09-05 03:02:31 | [diff] [blame] | 419 | |
Xida Chen | bfab97a | 2019-12-18 04:49:56 | [diff] [blame] | 420 | void FrameSequenceTracker::ReportMetricsForTesting() { |
Sadrul Habib Chowdhury | 590a32f | 2019-12-06 20:08:45 | [diff] [blame] | 421 | metrics_->ReportMetrics(); |
Sadrul Habib Chowdhury | ab4d350f | 2019-07-13 00:17:37 | [diff] [blame] | 422 | } |
| 423 | |
| 424 | void FrameSequenceTracker::ReportBeginImplFrame( |
| 425 | const viz::BeginFrameArgs& args) { |
| 426 | if (termination_status_ != TerminationStatus::kActive) |
| 427 | return; |
| 428 | |
behdad | 2adc423 | 2019-12-18 18:11:39 | [diff] [blame^] | 429 | if (ShouldIgnoreBeginFrameSource(args.frame_id.source_id)) |
Sadrul Habib Chowdhury | 2391917 | 2019-07-22 23:58:50 | [diff] [blame] | 430 | return; |
Sadrul Habib Chowdhury | dc34c8b | 2019-12-16 18:39:13 | [diff] [blame] | 431 | |
Sadrul Habib Chowdhury | 7fe10ea | 2019-12-11 01:59:29 | [diff] [blame] | 432 | #if DCHECK_IS_ON() |
| 433 | DCHECK(!is_inside_frame_) << TRACKER_DCHECK_MSG; |
| 434 | is_inside_frame_ = true; |
Sadrul Habib Chowdhury | 2391917 | 2019-07-22 23:58:50 | [diff] [blame] | 435 | |
Xida Chen | d56033c | 2019-12-05 13:31:41 | [diff] [blame] | 436 | if (args.type == viz::BeginFrameArgs::NORMAL) |
behdad | 2adc423 | 2019-12-18 18:11:39 | [diff] [blame^] | 437 | impl_frames_.insert(args.frame_id); |
Xida Chen | d56033c | 2019-12-05 13:31:41 | [diff] [blame] | 438 | #endif |
behdad | 2adc423 | 2019-12-18 18:11:39 | [diff] [blame^] | 439 | TRACKER_TRACE_STREAM << "b(" << args.frame_id.sequence_number << ")"; |
| 440 | UpdateTrackedFrameData(&begin_impl_frame_data_, args.frame_id.source_id, |
| 441 | args.frame_id.sequence_number); |
Sadrul Habib Chowdhury | c537f2f4 | 2019-12-05 19:52:28 | [diff] [blame] | 442 | impl_throughput().frames_expected += |
Sadrul Habib Chowdhury | ab4d350f | 2019-07-13 00:17:37 | [diff] [blame] | 443 | begin_impl_frame_data_.previous_sequence_delta; |
Xida Chen | 1102307b | 2019-10-11 17:03:15 | [diff] [blame] | 444 | |
| 445 | if (first_frame_timestamp_.is_null()) |
| 446 | first_frame_timestamp_ = args.frame_time; |
Sadrul Habib Chowdhury | ab4d350f | 2019-07-13 00:17:37 | [diff] [blame] | 447 | } |
| 448 | |
| 449 | void FrameSequenceTracker::ReportBeginMainFrame( |
| 450 | const viz::BeginFrameArgs& args) { |
| 451 | if (termination_status_ != TerminationStatus::kActive) |
| 452 | return; |
| 453 | |
behdad | 2adc423 | 2019-12-18 18:11:39 | [diff] [blame^] | 454 | if (ShouldIgnoreBeginFrameSource(args.frame_id.source_id)) |
Sadrul Habib Chowdhury | 2391917 | 2019-07-22 23:58:50 | [diff] [blame] | 455 | return; |
| 456 | |
behdad | 2adc423 | 2019-12-18 18:11:39 | [diff] [blame^] | 457 | if (ShouldIgnoreSequence(args.frame_id.sequence_number)) |
Xida Chen | d56033c | 2019-12-05 13:31:41 | [diff] [blame] | 458 | return; |
| 459 | |
| 460 | #if DCHECK_IS_ON() |
| 461 | if (args.type == viz::BeginFrameArgs::NORMAL) { |
behdad | 2adc423 | 2019-12-18 18:11:39 | [diff] [blame^] | 462 | DCHECK(impl_frames_.contains(args.frame_id)); |
Xida Chen | d56033c | 2019-12-05 13:31:41 | [diff] [blame] | 463 | } |
| 464 | #endif |
| 465 | |
Mingjing Zhang | c0ce541 | 2019-11-07 22:00:07 | [diff] [blame] | 466 | TRACKER_TRACE_STREAM << 'B'; |
| 467 | TRACKER_TRACE_STREAM << "(" << begin_main_frame_data_.previous_sequence << "," |
behdad | 2adc423 | 2019-12-18 18:11:39 | [diff] [blame^] | 468 | << args.frame_id.sequence_number << ")"; |
| 469 | UpdateTrackedFrameData(&begin_main_frame_data_, args.frame_id.source_id, |
| 470 | args.frame_id.sequence_number); |
Sadrul Habib Chowdhury | 1b9fea6a | 2019-12-18 02:26:02 | [diff] [blame] | 471 | if (!first_received_main_sequence_ || |
behdad | 2adc423 | 2019-12-18 18:11:39 | [diff] [blame^] | 472 | first_received_main_sequence_ <= last_no_main_damage_sequence_) |
| 473 | first_received_main_sequence_ = args.frame_id.sequence_number; |
Sadrul Habib Chowdhury | c537f2f4 | 2019-12-05 19:52:28 | [diff] [blame] | 474 | main_throughput().frames_expected += |
Sadrul Habib Chowdhury | ab4d350f | 2019-07-13 00:17:37 | [diff] [blame] | 475 | begin_main_frame_data_.previous_sequence_delta; |
| 476 | } |
| 477 | |
| 478 | void FrameSequenceTracker::ReportSubmitFrame( |
| 479 | uint32_t frame_token, |
Sadrul Habib Chowdhury | 40a4d8c | 2019-09-05 03:02:31 | [diff] [blame] | 480 | bool has_missing_content, |
Sadrul Habib Chowdhury | ab4d350f | 2019-07-13 00:17:37 | [diff] [blame] | 481 | const viz::BeginFrameAck& ack, |
| 482 | const viz::BeginFrameArgs& origin_args) { |
Xida Chen | d56033c | 2019-12-05 13:31:41 | [diff] [blame] | 483 | if (termination_status_ != TerminationStatus::kActive || |
behdad | 2adc423 | 2019-12-18 18:11:39 | [diff] [blame^] | 484 | ShouldIgnoreBeginFrameSource(ack.frame_id.source_id) || |
| 485 | ShouldIgnoreSequence(ack.frame_id.sequence_number)) { |
Xida Chen | d56033c | 2019-12-05 13:31:41 | [diff] [blame] | 486 | ignored_frame_tokens_.insert(frame_token); |
Sadrul Habib Chowdhury | ab4d350f | 2019-07-13 00:17:37 | [diff] [blame] | 487 | return; |
| 488 | } |
| 489 | |
Sadrul Habib Chowdhury | 7fe10ea | 2019-12-11 01:59:29 | [diff] [blame] | 490 | #if DCHECK_IS_ON() |
| 491 | DCHECK(is_inside_frame_) << TRACKER_DCHECK_MSG; |
| 492 | #endif |
Sadrul Habib Chowdhury | ab4d350f | 2019-07-13 00:17:37 | [diff] [blame] | 493 | if (first_submitted_frame_ == 0) |
| 494 | first_submitted_frame_ = frame_token; |
| 495 | last_submitted_frame_ = frame_token; |
| 496 | |
Sadrul Habib Chowdhury | 70d2fed | 2019-12-12 22:56:57 | [diff] [blame] | 497 | TRACKER_TRACE_STREAM << 's'; |
Sadrul Habib Chowdhury | dc34c8b | 2019-12-16 18:39:13 | [diff] [blame] | 498 | const bool main_changes_after_sequence_started = |
| 499 | first_received_main_sequence_ && |
behdad | 2adc423 | 2019-12-18 18:11:39 | [diff] [blame^] | 500 | origin_args.frame_id.sequence_number >= first_received_main_sequence_; |
Sadrul Habib Chowdhury | dc34c8b | 2019-12-16 18:39:13 | [diff] [blame] | 501 | const bool main_changes_include_new_changes = |
| 502 | last_submitted_main_sequence_ == 0 || |
behdad | 2adc423 | 2019-12-18 18:11:39 | [diff] [blame^] | 503 | origin_args.frame_id.sequence_number > last_submitted_main_sequence_; |
Sadrul Habib Chowdhury | dc34c8b | 2019-12-16 18:39:13 | [diff] [blame] | 504 | const bool main_change_had_no_damage = |
| 505 | last_no_main_damage_sequence_ != 0 && |
behdad | 2adc423 | 2019-12-18 18:11:39 | [diff] [blame^] | 506 | origin_args.frame_id.sequence_number == last_no_main_damage_sequence_; |
Mingjing Zhang | 9431496 | 2019-11-05 02:59:20 | [diff] [blame] | 507 | |
behdad | 2adc423 | 2019-12-18 18:11:39 | [diff] [blame^] | 508 | if (!ShouldIgnoreBeginFrameSource(origin_args.frame_id.source_id) && |
Sadrul Habib Chowdhury | dc34c8b | 2019-12-16 18:39:13 | [diff] [blame] | 509 | main_changes_after_sequence_started && main_changes_include_new_changes && |
| 510 | !main_change_had_no_damage) { |
| 511 | TRACKER_TRACE_STREAM << 'S'; |
| 512 | |
behdad | 2adc423 | 2019-12-18 18:11:39 | [diff] [blame^] | 513 | last_submitted_main_sequence_ = origin_args.frame_id.sequence_number; |
Sadrul Habib Chowdhury | dc34c8b | 2019-12-16 18:39:13 | [diff] [blame] | 514 | main_frames_.push_back(frame_token); |
| 515 | DCHECK_GE(main_throughput().frames_expected, main_frames_.size()) |
| 516 | << TRACKER_DCHECK_MSG; |
Sadrul Habib Chowdhury | ab4d350f | 2019-07-13 00:17:37 | [diff] [blame] | 517 | } |
Sadrul Habib Chowdhury | 40a4d8c | 2019-09-05 03:02:31 | [diff] [blame] | 518 | |
| 519 | if (has_missing_content) { |
| 520 | checkerboarding_.frames.push_back(frame_token); |
| 521 | } |
Sadrul Habib Chowdhury | ab4d350f | 2019-07-13 00:17:37 | [diff] [blame] | 522 | } |
| 523 | |
Sadrul Habib Chowdhury | 7fe10ea | 2019-12-11 01:59:29 | [diff] [blame] | 524 | void FrameSequenceTracker::ReportFrameEnd(const viz::BeginFrameArgs& args) { |
| 525 | #if DCHECK_IS_ON() |
| 526 | if (termination_status_ != TerminationStatus::kActive) |
| 527 | return; |
| 528 | |
behdad | 2adc423 | 2019-12-18 18:11:39 | [diff] [blame^] | 529 | if (ShouldIgnoreBeginFrameSource(args.frame_id.source_id)) |
Sadrul Habib Chowdhury | 7fe10ea | 2019-12-11 01:59:29 | [diff] [blame] | 530 | return; |
| 531 | |
behdad | 2adc423 | 2019-12-18 18:11:39 | [diff] [blame^] | 532 | if (ShouldIgnoreSequence(args.frame_id.sequence_number)) { |
Sadrul Habib Chowdhury | 7fe10ea | 2019-12-11 01:59:29 | [diff] [blame] | 533 | is_inside_frame_ = false; |
| 534 | return; |
| 535 | } |
| 536 | |
behdad | 2adc423 | 2019-12-18 18:11:39 | [diff] [blame^] | 537 | TRACKER_TRACE_STREAM << "e(" << args.frame_id.sequence_number << ")"; |
Sadrul Habib Chowdhury | 7fe10ea | 2019-12-11 01:59:29 | [diff] [blame] | 538 | DCHECK(is_inside_frame_) << TRACKER_DCHECK_MSG; |
| 539 | is_inside_frame_ = false; |
| 540 | #endif |
| 541 | } |
| 542 | |
Sadrul Habib Chowdhury | ab4d350f | 2019-07-13 00:17:37 | [diff] [blame] | 543 | void FrameSequenceTracker::ReportFramePresented( |
| 544 | uint32_t frame_token, |
| 545 | const gfx::PresentationFeedback& feedback) { |
| 546 | const bool frame_token_acks_last_frame = |
| 547 | frame_token == last_submitted_frame_ || |
| 548 | viz::FrameTokenGT(frame_token, last_submitted_frame_); |
| 549 | |
| 550 | // Update termination status if this is scheduled for termination, and it is |
| 551 | // not waiting for any frames, or it has received the presentation-feedback |
| 552 | // for the latest frame it is tracking. |
| 553 | if (termination_status_ == TerminationStatus::kScheduledForTermination && |
| 554 | (last_submitted_frame_ == 0 || frame_token_acks_last_frame)) { |
| 555 | termination_status_ = TerminationStatus::kReadyForTermination; |
| 556 | } |
| 557 | |
| 558 | if (first_submitted_frame_ == 0 || |
| 559 | viz::FrameTokenGT(first_submitted_frame_, frame_token)) { |
| 560 | // We are getting presentation feedback for frames that were submitted |
| 561 | // before this sequence started. So ignore these. |
| 562 | return; |
| 563 | } |
| 564 | |
Xida Chen | d56033c | 2019-12-05 13:31:41 | [diff] [blame] | 565 | if (ignored_frame_tokens_.contains(frame_token)) |
| 566 | return; |
| 567 | |
Mingjing Zhang | c0ce541 | 2019-11-07 22:00:07 | [diff] [blame] | 568 | TRACKER_TRACE_STREAM << 'P'; |
Mingjing Zhang | 9431496 | 2019-11-05 02:59:20 | [diff] [blame] | 569 | |
Sadrul Habib Chowdhury | 40a4d8c | 2019-09-05 03:02:31 | [diff] [blame] | 570 | TRACE_EVENT_ASYNC_STEP_INTO_WITH_TIMESTAMP0( |
Sadrul Habib Chowdhury | 590a32f | 2019-12-06 20:08:45 | [diff] [blame] | 571 | "cc,benchmark", "FrameSequenceTracker", metrics_.get(), "FramePresented", |
Sadrul Habib Chowdhury | 40a4d8c | 2019-09-05 03:02:31 | [diff] [blame] | 572 | feedback.timestamp); |
Sadrul Habib Chowdhury | ab4d350f | 2019-07-13 00:17:37 | [diff] [blame] | 573 | const bool was_presented = !feedback.timestamp.is_null(); |
| 574 | if (was_presented && last_submitted_frame_) { |
Sadrul Habib Chowdhury | c537f2f4 | 2019-12-05 19:52:28 | [diff] [blame] | 575 | DCHECK_LT(impl_throughput().frames_produced, |
| 576 | impl_throughput().frames_expected) |
Mingjing Zhang | 2879aa89 | 2019-11-01 02:54:54 | [diff] [blame] | 577 | << TRACKER_DCHECK_MSG; |
Sadrul Habib Chowdhury | c537f2f4 | 2019-12-05 19:52:28 | [diff] [blame] | 578 | ++impl_throughput().frames_produced; |
Sadrul Habib Chowdhury | ab4d350f | 2019-07-13 00:17:37 | [diff] [blame] | 579 | |
| 580 | if (frame_token_acks_last_frame) |
| 581 | last_submitted_frame_ = 0; |
| 582 | } |
| 583 | |
| 584 | while (!main_frames_.empty() && |
| 585 | !viz::FrameTokenGT(main_frames_.front(), frame_token)) { |
| 586 | if (was_presented && main_frames_.front() == frame_token) { |
Sadrul Habib Chowdhury | c537f2f4 | 2019-12-05 19:52:28 | [diff] [blame] | 587 | DCHECK_LT(main_throughput().frames_produced, |
| 588 | main_throughput().frames_expected) |
Mingjing Zhang | 9431496 | 2019-11-05 02:59:20 | [diff] [blame] | 589 | << TRACKER_DCHECK_MSG; |
Sadrul Habib Chowdhury | c537f2f4 | 2019-12-05 19:52:28 | [diff] [blame] | 590 | ++main_throughput().frames_produced; |
Sadrul Habib Chowdhury | ab4d350f | 2019-07-13 00:17:37 | [diff] [blame] | 591 | } |
| 592 | main_frames_.pop_front(); |
| 593 | } |
Sadrul Habib Chowdhury | 40a4d8c | 2019-09-05 03:02:31 | [diff] [blame] | 594 | |
| 595 | if (was_presented) { |
| 596 | if (checkerboarding_.last_frame_had_checkerboarding) { |
Mingjing Zhang | 2879aa89 | 2019-11-01 02:54:54 | [diff] [blame] | 597 | DCHECK(!checkerboarding_.last_frame_timestamp.is_null()) |
| 598 | << TRACKER_DCHECK_MSG; |
| 599 | DCHECK(!feedback.timestamp.is_null()) << TRACKER_DCHECK_MSG; |
Sadrul Habib Chowdhury | 40a4d8c | 2019-09-05 03:02:31 | [diff] [blame] | 600 | |
| 601 | // |feedback.timestamp| is the timestamp when the latest frame was |
| 602 | // presented. |checkerboarding_.last_frame_timestamp| is the timestamp |
| 603 | // when the previous frame (which had checkerboarding) was presented. Use |
| 604 | // |feedback.interval| to compute the number of vsyncs that have passed |
| 605 | // between the two frames (since that is how many times the user saw that |
| 606 | // checkerboarded frame). |
| 607 | base::TimeDelta difference = |
| 608 | feedback.timestamp - checkerboarding_.last_frame_timestamp; |
| 609 | const auto& interval = feedback.interval.is_zero() |
| 610 | ? viz::BeginFrameArgs::DefaultInterval() |
| 611 | : feedback.interval; |
Mingjing Zhang | 2879aa89 | 2019-11-01 02:54:54 | [diff] [blame] | 612 | DCHECK(!interval.is_zero()) << TRACKER_DCHECK_MSG; |
Sadrul Habib Chowdhury | 40a4d8c | 2019-09-05 03:02:31 | [diff] [blame] | 613 | constexpr base::TimeDelta kEpsilon = base::TimeDelta::FromMilliseconds(1); |
| 614 | int64_t frames = (difference + kEpsilon) / interval; |
Sadrul Habib Chowdhury | 590a32f | 2019-12-06 20:08:45 | [diff] [blame] | 615 | metrics_->add_checkerboarded_frames(frames); |
Sadrul Habib Chowdhury | 40a4d8c | 2019-09-05 03:02:31 | [diff] [blame] | 616 | } |
| 617 | |
| 618 | const bool frame_had_checkerboarding = |
| 619 | base::Contains(checkerboarding_.frames, frame_token); |
| 620 | checkerboarding_.last_frame_had_checkerboarding = frame_had_checkerboarding; |
| 621 | checkerboarding_.last_frame_timestamp = feedback.timestamp; |
| 622 | } |
| 623 | |
| 624 | while (!checkerboarding_.frames.empty() && |
| 625 | !viz::FrameTokenGT(checkerboarding_.frames.front(), frame_token)) { |
| 626 | checkerboarding_.frames.pop_front(); |
| 627 | } |
Sadrul Habib Chowdhury | ab4d350f | 2019-07-13 00:17:37 | [diff] [blame] | 628 | } |
| 629 | |
| 630 | void FrameSequenceTracker::ReportImplFrameCausedNoDamage( |
| 631 | const viz::BeginFrameAck& ack) { |
| 632 | if (termination_status_ != TerminationStatus::kActive) |
| 633 | return; |
| 634 | |
behdad | 2adc423 | 2019-12-18 18:11:39 | [diff] [blame^] | 635 | if (ShouldIgnoreBeginFrameSource(ack.frame_id.source_id)) |
Sadrul Habib Chowdhury | 2391917 | 2019-07-22 23:58:50 | [diff] [blame] | 636 | return; |
| 637 | |
Sadrul Habib Chowdhury | ab4d350f | 2019-07-13 00:17:37 | [diff] [blame] | 638 | // It is possible that this is called before a begin-impl-frame has been |
| 639 | // dispatched for this frame-sequence. In such cases, ignore this call. |
behdad | 2adc423 | 2019-12-18 18:11:39 | [diff] [blame^] | 640 | if (ShouldIgnoreSequence(ack.frame_id.sequence_number)) |
Sadrul Habib Chowdhury | ab4d350f | 2019-07-13 00:17:37 | [diff] [blame] | 641 | return; |
Xida Chen | d56033c | 2019-12-05 13:31:41 | [diff] [blame] | 642 | |
Mingjing Zhang | c0ce541 | 2019-11-07 22:00:07 | [diff] [blame] | 643 | TRACKER_TRACE_STREAM << 'n'; |
Sadrul Habib Chowdhury | c537f2f4 | 2019-12-05 19:52:28 | [diff] [blame] | 644 | DCHECK_GT(impl_throughput().frames_expected, 0u) << TRACKER_DCHECK_MSG; |
| 645 | DCHECK_GT(impl_throughput().frames_expected, |
| 646 | impl_throughput().frames_produced) |
Mingjing Zhang | 2879aa89 | 2019-11-01 02:54:54 | [diff] [blame] | 647 | << TRACKER_DCHECK_MSG; |
Sadrul Habib Chowdhury | c537f2f4 | 2019-12-05 19:52:28 | [diff] [blame] | 648 | --impl_throughput().frames_expected; |
Sadrul Habib Chowdhury | ab4d350f | 2019-07-13 00:17:37 | [diff] [blame] | 649 | |
behdad | 2adc423 | 2019-12-18 18:11:39 | [diff] [blame^] | 650 | if (begin_impl_frame_data_.previous_sequence == ack.frame_id.sequence_number) |
Sadrul Habib Chowdhury | ab4d350f | 2019-07-13 00:17:37 | [diff] [blame] | 651 | begin_impl_frame_data_.previous_sequence = 0; |
| 652 | } |
| 653 | |
| 654 | void FrameSequenceTracker::ReportMainFrameCausedNoDamage( |
| 655 | const viz::BeginFrameArgs& args) { |
| 656 | if (termination_status_ != TerminationStatus::kActive) |
| 657 | return; |
| 658 | |
behdad | 2adc423 | 2019-12-18 18:11:39 | [diff] [blame^] | 659 | if (ShouldIgnoreBeginFrameSource(args.frame_id.source_id)) |
Sadrul Habib Chowdhury | 2391917 | 2019-07-22 23:58:50 | [diff] [blame] | 660 | return; |
| 661 | |
behdad | 2adc423 | 2019-12-18 18:11:39 | [diff] [blame^] | 662 | if (ShouldIgnoreSequence(args.frame_id.sequence_number)) |
Xida Chen | d56033c | 2019-12-05 13:31:41 | [diff] [blame] | 663 | return; |
Sadrul Habib Chowdhury | ab4d350f | 2019-07-13 00:17:37 | [diff] [blame] | 664 | |
Mingjing Zhang | c0ce541 | 2019-11-07 22:00:07 | [diff] [blame] | 665 | TRACKER_TRACE_STREAM << 'N'; |
| 666 | TRACKER_TRACE_STREAM << "(" << begin_main_frame_data_.previous_sequence << "," |
behdad | 2adc423 | 2019-12-18 18:11:39 | [diff] [blame^] | 667 | << args.frame_id.sequence_number << ")"; |
Sadrul Habib Chowdhury | c537f2f4 | 2019-12-05 19:52:28 | [diff] [blame] | 668 | DCHECK_GT(main_throughput().frames_expected, 0u) << TRACKER_DCHECK_MSG; |
| 669 | DCHECK_GT(main_throughput().frames_expected, |
| 670 | main_throughput().frames_produced) |
Mingjing Zhang | 2879aa89 | 2019-11-01 02:54:54 | [diff] [blame] | 671 | << TRACKER_DCHECK_MSG; |
behdad | 2adc423 | 2019-12-18 18:11:39 | [diff] [blame^] | 672 | last_no_main_damage_sequence_ = args.frame_id.sequence_number; |
Sadrul Habib Chowdhury | c537f2f4 | 2019-12-05 19:52:28 | [diff] [blame] | 673 | --main_throughput().frames_expected; |
| 674 | DCHECK_GE(main_throughput().frames_expected, main_frames_.size()) |
Mingjing Zhang | 2879aa89 | 2019-11-01 02:54:54 | [diff] [blame] | 675 | << TRACKER_DCHECK_MSG; |
Sadrul Habib Chowdhury | ab4d350f | 2019-07-13 00:17:37 | [diff] [blame] | 676 | |
behdad | 2adc423 | 2019-12-18 18:11:39 | [diff] [blame^] | 677 | if (begin_main_frame_data_.previous_sequence == args.frame_id.sequence_number) |
Sadrul Habib Chowdhury | ab4d350f | 2019-07-13 00:17:37 | [diff] [blame] | 678 | begin_main_frame_data_.previous_sequence = 0; |
| 679 | } |
| 680 | |
| 681 | void FrameSequenceTracker::PauseFrameProduction() { |
| 682 | // Reset the states, so that the tracker ignores the vsyncs until the next |
| 683 | // received begin-frame. |
| 684 | begin_impl_frame_data_ = {0, 0, 0}; |
| 685 | begin_main_frame_data_ = {0, 0, 0}; |
| 686 | } |
| 687 | |
| 688 | void FrameSequenceTracker::UpdateTrackedFrameData(TrackedFrameData* frame_data, |
| 689 | uint64_t source_id, |
| 690 | uint64_t sequence_number) { |
| 691 | if (frame_data->previous_sequence && |
| 692 | frame_data->previous_source == source_id) { |
Mingjing Zhang | 0ccb625d | 2019-11-20 17:50:20 | [diff] [blame] | 693 | uint32_t current_latency = sequence_number - frame_data->previous_sequence; |
Sadrul Habib Chowdhury | 70d2fed | 2019-12-12 22:56:57 | [diff] [blame] | 694 | DCHECK_GT(current_latency, 0u); |
Sadrul Habib Chowdhury | ab4d350f | 2019-07-13 00:17:37 | [diff] [blame] | 695 | frame_data->previous_sequence_delta = current_latency; |
| 696 | } else { |
| 697 | frame_data->previous_sequence_delta = 1; |
| 698 | } |
| 699 | frame_data->previous_source = source_id; |
| 700 | frame_data->previous_sequence = sequence_number; |
| 701 | } |
| 702 | |
Sadrul Habib Chowdhury | 2391917 | 2019-07-22 23:58:50 | [diff] [blame] | 703 | bool FrameSequenceTracker::ShouldIgnoreBeginFrameSource( |
| 704 | uint64_t source_id) const { |
| 705 | if (begin_impl_frame_data_.previous_source == 0) |
| 706 | return false; |
| 707 | return source_id != begin_impl_frame_data_.previous_source; |
| 708 | } |
| 709 | |
Xida Chen | d56033c | 2019-12-05 13:31:41 | [diff] [blame] | 710 | // This check ensures that when ReportBeginMainFrame, or ReportSubmitFrame, or |
| 711 | // ReportFramePresented is called for a particular arg, the ReportBeginImplFrame |
| 712 | // is been called already. |
| 713 | bool FrameSequenceTracker::ShouldIgnoreSequence( |
| 714 | uint64_t sequence_number) const { |
| 715 | return begin_impl_frame_data_.previous_sequence == 0 || |
| 716 | sequence_number < begin_impl_frame_data_.previous_sequence; |
| 717 | } |
| 718 | |
Sadrul Habib Chowdhury | ab4d350f | 2019-07-13 00:17:37 | [diff] [blame] | 719 | std::unique_ptr<base::trace_event::TracedValue> |
Sadrul Habib Chowdhury | c537f2f4 | 2019-12-05 19:52:28 | [diff] [blame] | 720 | FrameSequenceMetrics::ThroughputData::ToTracedValue( |
Sadrul Habib Chowdhury | ab4d350f | 2019-07-13 00:17:37 | [diff] [blame] | 721 | const ThroughputData& impl, |
| 722 | const ThroughputData& main) { |
| 723 | auto dict = std::make_unique<base::trace_event::TracedValue>(); |
| 724 | dict->SetInteger("impl-frames-produced", impl.frames_produced); |
| 725 | dict->SetInteger("impl-frames-expected", impl.frames_expected); |
| 726 | dict->SetInteger("main-frames-produced", main.frames_produced); |
| 727 | dict->SetInteger("main-frames-expected", main.frames_expected); |
| 728 | return dict; |
| 729 | } |
| 730 | |
Xida Chen | 1102307b | 2019-10-11 17:03:15 | [diff] [blame] | 731 | bool FrameSequenceTracker::ShouldReportMetricsNow( |
| 732 | const viz::BeginFrameArgs& args) const { |
Sadrul Habib Chowdhury | 590a32f | 2019-12-06 20:08:45 | [diff] [blame] | 733 | return metrics_->HasEnoughDataForReporting() && |
| 734 | !first_frame_timestamp_.is_null() && |
| 735 | args.frame_time - first_frame_timestamp_ >= time_delta_to_report_; |
| 736 | } |
| 737 | |
| 738 | std::unique_ptr<FrameSequenceMetrics> FrameSequenceTracker::TakeMetrics() { |
| 739 | return std::move(metrics_); |
Xida Chen | 1102307b | 2019-10-11 17:03:15 | [diff] [blame] | 740 | } |
| 741 | |
Sadrul Habib Chowdhury | c537f2f4 | 2019-12-05 19:52:28 | [diff] [blame] | 742 | base::Optional<int> FrameSequenceMetrics::ThroughputData::ReportHistogram( |
Sadrul Habib Chowdhury | db3d7be7 | 2019-07-13 03:27:32 | [diff] [blame] | 743 | FrameSequenceTrackerType sequence_type, |
Sadrul Habib Chowdhury | d4e8f4a | 2019-12-13 15:10:27 | [diff] [blame] | 744 | ThreadType thread_type, |
Sadrul Habib Chowdhury | db3d7be7 | 2019-07-13 03:27:32 | [diff] [blame] | 745 | int metric_index, |
| 746 | const ThroughputData& data) { |
| 747 | DCHECK_LT(sequence_type, FrameSequenceTrackerType::kMaxType); |
| 748 | |
Sadrul Habib Chowdhury | 6c17e5f | 2019-07-26 16:57:10 | [diff] [blame] | 749 | STATIC_HISTOGRAM_POINTER_GROUP( |
Sadrul Habib Chowdhury | 4bba3d0 | 2019-09-06 02:33:27 | [diff] [blame] | 750 | GetFrameSequenceLengthHistogramName(sequence_type), sequence_type, |
| 751 | FrameSequenceTrackerType::kMaxType, Add(data.frames_expected), |
Sadrul Habib Chowdhury | 6c17e5f | 2019-07-26 16:57:10 | [diff] [blame] | 752 | base::Histogram::FactoryGet( |
Sadrul Habib Chowdhury | 4bba3d0 | 2019-09-06 02:33:27 | [diff] [blame] | 753 | GetFrameSequenceLengthHistogramName(sequence_type), 1, 1000, 50, |
Sadrul Habib Chowdhury | 6c17e5f | 2019-07-26 16:57:10 | [diff] [blame] | 754 | base::HistogramBase::kUmaTargetedHistogramFlag)); |
Sadrul Habib Chowdhury | db3d7be7 | 2019-07-13 03:27:32 | [diff] [blame] | 755 | |
Sadrul Habib Chowdhury | db3d7be7 | 2019-07-13 03:27:32 | [diff] [blame] | 756 | if (data.frames_expected < kMinFramesForThroughputMetric) |
Xida Chen | f8afda3 | 2019-09-25 01:46:07 | [diff] [blame] | 757 | return base::nullopt; |
Sadrul Habib Chowdhury | db3d7be7 | 2019-07-13 03:27:32 | [diff] [blame] | 758 | |
Sadrul Habib Chowdhury | db3d7be7 | 2019-07-13 03:27:32 | [diff] [blame] | 759 | const int percent = |
| 760 | static_cast<int>(100 * data.frames_produced / data.frames_expected); |
Sadrul Habib Chowdhury | 3ebe0382 | 2019-12-16 18:29:20 | [diff] [blame] | 761 | |
| 762 | const bool is_animation = |
| 763 | ShouldReportForAnimation(sequence_type, thread_type); |
| 764 | const bool is_interaction = |
| 765 | ShouldReportForInteraction(sequence_type, thread_type); |
| 766 | |
| 767 | if (is_animation) { |
| 768 | UMA_HISTOGRAM_PERCENTAGE("Graphics.Smoothness.Throughput.AllAnimations", |
| 769 | percent); |
| 770 | } |
| 771 | |
| 772 | if (is_interaction) { |
| 773 | UMA_HISTOGRAM_PERCENTAGE("Graphics.Smoothness.Throughput.AllInteractions", |
| 774 | percent); |
| 775 | } |
| 776 | |
| 777 | if (is_animation || is_interaction) { |
| 778 | UMA_HISTOGRAM_PERCENTAGE("Graphics.Smoothness.Throughput.AllSequences", |
| 779 | percent); |
| 780 | } |
| 781 | |
Sadrul Habib Chowdhury | d4e8f4a | 2019-12-13 15:10:27 | [diff] [blame] | 782 | const char* thread_name = |
| 783 | thread_type == ThreadType::kCompositor |
| 784 | ? "CompositorThread" |
| 785 | : thread_type == ThreadType::kMain ? "MainThread" : "SlowerThread"; |
Sadrul Habib Chowdhury | db3d7be7 | 2019-07-13 03:27:32 | [diff] [blame] | 786 | STATIC_HISTOGRAM_POINTER_GROUP( |
Sadrul Habib Chowdhury | 4bba3d0 | 2019-09-06 02:33:27 | [diff] [blame] | 787 | GetThroughputHistogramName(sequence_type, thread_name), metric_index, |
| 788 | kMaximumHistogramIndex, Add(percent), |
Sadrul Habib Chowdhury | db3d7be7 | 2019-07-13 03:27:32 | [diff] [blame] | 789 | base::LinearHistogram::FactoryGet( |
Sadrul Habib Chowdhury | 4bba3d0 | 2019-09-06 02:33:27 | [diff] [blame] | 790 | GetThroughputHistogramName(sequence_type, thread_name), 1, 100, 101, |
| 791 | base::HistogramBase::kUmaTargetedHistogramFlag)); |
Xida Chen | f8afda3 | 2019-09-25 01:46:07 | [diff] [blame] | 792 | return percent; |
Sadrul Habib Chowdhury | db3d7be7 | 2019-07-13 03:27:32 | [diff] [blame] | 793 | } |
| 794 | |
Sadrul Habib Chowdhury | 40a4d8c | 2019-09-05 03:02:31 | [diff] [blame] | 795 | FrameSequenceTracker::CheckerboardingData::CheckerboardingData() = default; |
| 796 | FrameSequenceTracker::CheckerboardingData::~CheckerboardingData() = default; |
| 797 | |
Sadrul Habib Chowdhury | ab4d350f | 2019-07-13 00:17:37 | [diff] [blame] | 798 | } // namespace cc |