blob: 9fec811e43dede9535e3a64b73012d9603f1a51c [file] [log] [blame]
Sadrul Habib Chowdhuryab4d350f2019-07-13 00:17:371// 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
behdad5fb48ea22019-08-12 18:15:365#include "cc/metrics/frame_sequence_tracker.h"
Sadrul Habib Chowdhuryab4d350f2019-07-13 00:17:376
Sadrul Habib Chowdhurydb3d7be72019-07-13 03:27:327#include "base/metrics/histogram.h"
8#include "base/metrics/histogram_macros.h"
Sadrul Habib Chowdhury40a4d8c2019-09-05 03:02:319#include "base/stl_util.h"
Sadrul Habib Chowdhurydb3d7be72019-07-13 03:27:3210#include "base/strings/strcat.h"
Sadrul Habib Chowdhuryab4d350f2019-07-13 00:17:3711#include "base/trace_event/trace_event.h"
12#include "base/trace_event/traced_value.h"
behdade9ae6e12019-08-20 23:02:2513#include "cc/metrics/compositor_frame_reporting_controller.h"
Xida Chen4ede1d692019-11-22 18:00:4814#include "cc/metrics/throughput_ukm_reporter.h"
15#include "cc/trees/ukm_manager.h"
Sadrul Habib Chowdhuryab4d350f2019-07-13 00:17:3716#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 Zhang2879aa892019-11-01 02:54:5420// This macro is used with DCHECK to provide addition debug info.
Mingjing Zhang94314962019-11-05 02:59:2021#if DCHECK_IS_ON()
Mingjing Zhangc0ce5412019-11-07 22:00:0722#define TRACKER_TRACE_STREAM frame_sequence_trace_
behdada108d812019-11-20 17:22:3923#define TRACKER_DCHECK_MSG \
24 " in " << GetFrameSequenceTrackerTypeName(static_cast<int>(this->type_)) \
25 << " tracker: " << frame_sequence_trace_.str() << " (" \
Mingjing Zhangc0ce5412019-11-07 22:00:0726 << frame_sequence_trace_.str().size() << ")";
Mingjing Zhang94314962019-11-05 02:59:2027#else
Mingjing Zhangc0ce5412019-11-07 22:00:0728#define TRACKER_TRACE_STREAM EAT_STREAM_PARAMETERS
Mingjing Zhang94314962019-11-05 02:59:2029#define TRACKER_DCHECK_MSG ""
30#endif
Mingjing Zhang2879aa892019-11-01 02:54:5431
Sadrul Habib Chowdhuryab4d350f2019-07-13 00:17:3732namespace cc {
33
behdada108d812019-11-20 17:22:3934const 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 Chen78ba8b72019-08-30 14:49:2557
Sadrul Habib Chowdhurydb3d7be72019-07-13 03:27:3258namespace {
59
Sadrul Habib Chowdhury590a32f2019-12-06 20:08:4560// Avoid reporting any throughput metric for sequences that do not have a
61// sufficient number of frames.
62constexpr int kMinFramesForThroughputMetric = 100;
Sadrul Habib Chowdhury40a4d8c2019-09-05 03:02:3163
behdada108d812019-11-20 17:22:3964constexpr int kBuiltinSequenceNum = FrameSequenceTrackerType::kMaxType + 1;
Xida Chenf8afda32019-09-25 01:46:0765constexpr int kMaximumHistogramIndex = 3 * kBuiltinSequenceNum;
Sadrul Habib Chowdhurydb3d7be72019-07-13 03:27:3266
Sadrul Habib Chowdhuryd4e8f4a2019-12-13 15:10:2767int GetIndexForMetric(FrameSequenceMetrics::ThreadType thread_type,
Xida Chen4ede1d692019-11-22 18:00:4868 FrameSequenceTrackerType type) {
Sadrul Habib Chowdhuryd4e8f4a2019-12-13 15:10:2769 if (thread_type == FrameSequenceMetrics::ThreadType::kMain)
Xida Chenf8afda32019-09-25 01:46:0770 return static_cast<int>(type);
Sadrul Habib Chowdhuryd4e8f4a2019-12-13 15:10:2771 if (thread_type == FrameSequenceMetrics::ThreadType::kCompositor)
Xida Chenf8afda32019-09-25 01:46:0772 return static_cast<int>(type + kBuiltinSequenceNum);
73 return static_cast<int>(type + 2 * kBuiltinSequenceNum);
Sadrul Habib Chowdhurydb3d7be72019-07-13 03:27:3274}
75
Sadrul Habib Chowdhury4bba3d02019-09-06 02:33:2776std::string GetCheckerboardingHistogramName(FrameSequenceTrackerType type) {
behdada108d812019-11-20 17:22:3977 return base::StrCat({"Graphics.Smoothness.Checkerboarding.",
78 FrameSequenceTracker::GetFrameSequenceTrackerTypeName(
79 static_cast<int>(type))});
Sadrul Habib Chowdhury4bba3d02019-09-06 02:33:2780}
81
82std::string GetThroughputHistogramName(FrameSequenceTrackerType type,
83 const char* thread_name) {
behdada108d812019-11-20 17:22:3984 return base::StrCat({"Graphics.Smoothness.Throughput.", thread_name, ".",
85 FrameSequenceTracker::GetFrameSequenceTrackerTypeName(
86 static_cast<int>(type))});
Sadrul Habib Chowdhury4bba3d02019-09-06 02:33:2787}
88
89std::string GetFrameSequenceLengthHistogramName(FrameSequenceTrackerType type) {
behdada108d812019-11-20 17:22:3990 return base::StrCat({"Graphics.Smoothness.FrameSequenceLength.",
91 FrameSequenceTracker::GetFrameSequenceTrackerTypeName(
92 static_cast<int>(type))});
Sadrul Habib Chowdhury4bba3d02019-09-06 02:33:2793}
94
Sadrul Habib Chowdhury3ebe03822019-12-16 18:29:2095bool 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
107bool 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 Chowdhurydb3d7be72019-07-13 03:27:32121} // namespace
122
Sadrul Habib Chowdhuryab4d350f2019-07-13 00:17:37123////////////////////////////////////////////////////////////////////////////////
Sadrul Habib Chowdhuryc537f2f42019-12-05 19:52:28124// FrameSequenceMetrics
125
126FrameSequenceMetrics::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
138FrameSequenceMetrics::~FrameSequenceMetrics() {
Sadrul Habib Chowdhury590a32f2019-12-06 20:08:45139 if (HasDataLeftForReporting())
140 ReportMetrics();
141}
142
143void 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
157bool FrameSequenceMetrics::HasEnoughDataForReporting() const {
158 return impl_throughput_.frames_expected >= kMinFramesForThroughputMetric ||
159 main_throughput_.frames_expected >= kMinFramesForThroughputMetric;
160}
161
162bool FrameSequenceMetrics::HasDataLeftForReporting() const {
163 return impl_throughput_.frames_expected > 0 ||
164 main_throughput_.frames_expected > 0;
165}
166
167void FrameSequenceMetrics::ReportMetrics() {
Sadrul Habib Chowdhuryc537f2f42019-12-05 19:52:28168 DCHECK_LE(impl_throughput_.frames_produced, impl_throughput_.frames_expected);
169 DCHECK_LE(main_throughput_.frames_produced, main_throughput_.frames_expected);
Sadrul Habib Chowdhuryc537f2f42019-12-05 19:52:28170 TRACE_EVENT_ASYNC_END2(
171 "cc,benchmark", "FrameSequenceTracker", this, "args",
172 ThroughputData::ToTracedValue(impl_throughput_, main_throughput_),
173 "checkerboard", frames_checkerboarded_);
Sadrul Habib Chowdhuryc537f2f42019-12-05 19:52:28174
Sadrul Habib Chowdhuryc537f2f42019-12-05 19:52:28175 // Report the throughput metrics.
176 base::Optional<int> impl_throughput_percent = ThroughputData::ReportHistogram(
Sadrul Habib Chowdhuryd4e8f4a2019-12-13 15:10:27177 type_, ThreadType::kCompositor,
178 GetIndexForMetric(FrameSequenceMetrics::ThreadType::kCompositor, type_),
Sadrul Habib Chowdhuryc537f2f42019-12-05 19:52:28179 impl_throughput_);
180 base::Optional<int> main_throughput_percent = ThroughputData::ReportHistogram(
Sadrul Habib Chowdhuryd4e8f4a2019-12-13 15:10:27181 type_, ThreadType::kMain,
182 GetIndexForMetric(FrameSequenceMetrics::ThreadType::kMain, type_),
Sadrul Habib Chowdhuryc537f2f42019-12-05 19:52:28183 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 Chowdhuryd4e8f4a2019-12-13 15:10:27199 type_, ThreadType::kSlower,
200 GetIndexForMetric(FrameSequenceMetrics::ThreadType::kSlower, type_),
Sadrul Habib Chowdhuryc537f2f42019-12-05 19:52:28201 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 Chowdhury590a32f2019-12-06 20:08:45223 frames_checkerboarded_ = 0;
Sadrul Habib Chowdhuryc537f2f42019-12-05 19:52:28224 }
Sadrul Habib Chowdhury590a32f2019-12-06 20:08:45225
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 Chowdhuryc537f2f42019-12-05 19:52:28231}
232
233////////////////////////////////////////////////////////////////////////////////
Sadrul Habib Chowdhuryab4d350f2019-07-13 00:17:37234// FrameSequenceTrackerCollection
235
behdade9ae6e12019-08-20 23:02:25236FrameSequenceTrackerCollection::FrameSequenceTrackerCollection(
Sadrul Habib Chowdhury43dd14a2019-09-18 20:13:37237 bool is_single_threaded,
behdade9ae6e12019-08-20 23:02:25238 CompositorFrameReportingController* compositor_frame_reporting_controller)
Sadrul Habib Chowdhury43dd14a2019-09-18 20:13:37239 : is_single_threaded_(is_single_threaded),
240 compositor_frame_reporting_controller_(
Xida Chen4ede1d692019-11-22 18:00:48241 compositor_frame_reporting_controller),
242 throughput_ukm_reporter_(std::make_unique<ThroughputUkmReporter>()) {}
Xida Chenbad8e2b2019-08-27 18:19:37243
Sadrul Habib Chowdhuryab4d350f2019-07-13 00:17:37244FrameSequenceTrackerCollection::~FrameSequenceTrackerCollection() {
Xida Chenbad8e2b2019-08-27 18:19:37245 frame_trackers_.clear();
Sadrul Habib Chowdhuryab4d350f2019-07-13 00:17:37246 removal_trackers_.clear();
Sadrul Habib Chowdhuryab4d350f2019-07-13 00:17:37247}
248
Xida Chenbad8e2b2019-08-27 18:19:37249void FrameSequenceTrackerCollection::StartSequence(
250 FrameSequenceTrackerType type) {
Sadrul Habib Chowdhury43dd14a2019-09-18 20:13:37251 if (is_single_threaded_)
252 return;
Xida Chenbad8e2b2019-08-27 18:19:37253 if (frame_trackers_.contains(type))
254 return;
Xida Chen4ede1d692019-11-22 18:00:48255 auto tracker = base::WrapUnique(new FrameSequenceTracker(
256 type, ukm_manager_, throughput_ukm_reporter_.get()));
Xida Chenbad8e2b2019-08-27 18:19:37257 frame_trackers_[type] = std::move(tracker);
behdade9ae6e12019-08-20 23:02:25258
Mingjing Zhang2aa30ae2019-08-28 17:36:43259 if (compositor_frame_reporting_controller_)
260 compositor_frame_reporting_controller_->AddActiveTracker(type);
Sadrul Habib Chowdhuryab4d350f2019-07-13 00:17:37261}
262
Xida Chenbad8e2b2019-08-27 18:19:37263void FrameSequenceTrackerCollection::StopSequence(
264 FrameSequenceTrackerType type) {
265 if (!frame_trackers_.contains(type))
Sadrul Habib Chowdhuryab4d350f2019-07-13 00:17:37266 return;
behdade9ae6e12019-08-20 23:02:25267
Xida Chenbad8e2b2019-08-27 18:19:37268 std::unique_ptr<FrameSequenceTracker> tracker =
269 std::move(frame_trackers_[type]);
Mingjing Zhang2aa30ae2019-08-28 17:36:43270
271 if (compositor_frame_reporting_controller_)
272 compositor_frame_reporting_controller_->RemoveActiveTracker(tracker->type_);
273
Xida Chenbad8e2b2019-08-27 18:19:37274 frame_trackers_.erase(type);
Sadrul Habib Chowdhuryab4d350f2019-07-13 00:17:37275 tracker->ScheduleTerminate();
276 removal_trackers_.push_back(std::move(tracker));
277}
278
279void FrameSequenceTrackerCollection::ClearAll() {
Xida Chenbad8e2b2019-08-27 18:19:37280 frame_trackers_.clear();
Sadrul Habib Chowdhuryab4d350f2019-07-13 00:17:37281 removal_trackers_.clear();
Sadrul Habib Chowdhuryab4d350f2019-07-13 00:17:37282}
283
284void FrameSequenceTrackerCollection::NotifyBeginImplFrame(
285 const viz::BeginFrameArgs& args) {
Xida Chen1102307b2019-10-11 17:03:15286 RecreateTrackers(args);
287 for (auto& tracker : frame_trackers_)
Xida Chenbad8e2b2019-08-27 18:19:37288 tracker.second->ReportBeginImplFrame(args);
Sadrul Habib Chowdhuryab4d350f2019-07-13 00:17:37289}
290
291void FrameSequenceTrackerCollection::NotifyBeginMainFrame(
292 const viz::BeginFrameArgs& args) {
Xida Chen1102307b2019-10-11 17:03:15293 for (auto& tracker : frame_trackers_)
Xida Chenbad8e2b2019-08-27 18:19:37294 tracker.second->ReportBeginMainFrame(args);
Sadrul Habib Chowdhuryab4d350f2019-07-13 00:17:37295}
296
297void FrameSequenceTrackerCollection::NotifyImplFrameCausedNoDamage(
298 const viz::BeginFrameAck& ack) {
Xida Chenbad8e2b2019-08-27 18:19:37299 for (auto& tracker : frame_trackers_) {
300 tracker.second->ReportImplFrameCausedNoDamage(ack);
Sadrul Habib Chowdhuryab4d350f2019-07-13 00:17:37301 }
302}
303
304void FrameSequenceTrackerCollection::NotifyMainFrameCausedNoDamage(
305 const viz::BeginFrameArgs& args) {
Xida Chenbad8e2b2019-08-27 18:19:37306 for (auto& tracker : frame_trackers_) {
307 tracker.second->ReportMainFrameCausedNoDamage(args);
Sadrul Habib Chowdhuryab4d350f2019-07-13 00:17:37308 }
309}
310
311void FrameSequenceTrackerCollection::NotifyPauseFrameProduction() {
Xida Chenbad8e2b2019-08-27 18:19:37312 for (auto& tracker : frame_trackers_)
313 tracker.second->PauseFrameProduction();
Sadrul Habib Chowdhuryab4d350f2019-07-13 00:17:37314}
315
316void FrameSequenceTrackerCollection::NotifySubmitFrame(
317 uint32_t frame_token,
Sadrul Habib Chowdhury40a4d8c2019-09-05 03:02:31318 bool has_missing_content,
Sadrul Habib Chowdhuryab4d350f2019-07-13 00:17:37319 const viz::BeginFrameAck& ack,
320 const viz::BeginFrameArgs& origin_args) {
Xida Chenbad8e2b2019-08-27 18:19:37321 for (auto& tracker : frame_trackers_) {
Sadrul Habib Chowdhury40a4d8c2019-09-05 03:02:31322 tracker.second->ReportSubmitFrame(frame_token, has_missing_content, ack,
323 origin_args);
Sadrul Habib Chowdhuryab4d350f2019-07-13 00:17:37324 }
325}
326
Sadrul Habib Chowdhury7fe10ea2019-12-11 01:59:29327void FrameSequenceTrackerCollection::NotifyFrameEnd(
328 const viz::BeginFrameArgs& args) {
329 for (auto& tracker : frame_trackers_) {
330 tracker.second->ReportFrameEnd(args);
331 }
332}
333
Sadrul Habib Chowdhuryab4d350f2019-07-13 00:17:37334void FrameSequenceTrackerCollection::NotifyFramePresented(
335 uint32_t frame_token,
336 const gfx::PresentationFeedback& feedback) {
Xida Chenbad8e2b2019-08-27 18:19:37337 for (auto& tracker : frame_trackers_)
338 tracker.second->ReportFramePresented(frame_token, feedback);
Sadrul Habib Chowdhuryab4d350f2019-07-13 00:17:37339
Xida Chena4f48f9392019-08-30 16:53:24340 for (auto& tracker : removal_trackers_)
341 tracker->ReportFramePresented(frame_token, feedback);
342
Sadrul Habib Chowdhury590a32f2019-12-06 20:08:45343 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 Chowdhuryab4d350f2019-07-13 00:17:37363 // 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 Chen1102307b2019-10-11 17:03:15372void 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 Chenbad8e2b2019-08-27 18:19:37390FrameSequenceTracker* FrameSequenceTrackerCollection::GetTrackerForTesting(
391 FrameSequenceTrackerType type) {
392 if (!frame_trackers_.contains(type))
393 return nullptr;
394 return frame_trackers_[type].get();
Sadrul Habib Chowdhuryab4d350f2019-07-13 00:17:37395}
396
Xida Chen4ede1d692019-11-22 18:00:48397void FrameSequenceTrackerCollection::SetUkmManager(UkmManager* manager) {
398 DCHECK(frame_trackers_.empty());
399 ukm_manager_ = manager;
400}
401
Sadrul Habib Chowdhuryab4d350f2019-07-13 00:17:37402////////////////////////////////////////////////////////////////////////////////
403// FrameSequenceTracker
404
Xida Chen4ede1d692019-11-22 18:00:48405FrameSequenceTracker::FrameSequenceTracker(
406 FrameSequenceTrackerType type,
407 UkmManager* manager,
408 ThroughputUkmReporter* throughput_ukm_reporter)
Sadrul Habib Chowdhury590a32f2019-12-06 20:08:45409 : type_(type),
410 metrics_(
411 std::make_unique<FrameSequenceMetrics>(type,
412 manager,
413 throughput_ukm_reporter)) {
Sadrul Habib Chowdhurydb3d7be72019-07-13 03:27:32414 DCHECK_LT(type_, FrameSequenceTrackerType::kMaxType);
Sadrul Habib Chowdhuryab4d350f2019-07-13 00:17:37415}
416
417FrameSequenceTracker::~FrameSequenceTracker() {
Xida Chenf8afda32019-09-25 01:46:07418}
Sadrul Habib Chowdhury40a4d8c2019-09-05 03:02:31419
Xida Chenbfab97a2019-12-18 04:49:56420void FrameSequenceTracker::ReportMetricsForTesting() {
Sadrul Habib Chowdhury590a32f2019-12-06 20:08:45421 metrics_->ReportMetrics();
Sadrul Habib Chowdhuryab4d350f2019-07-13 00:17:37422}
423
424void FrameSequenceTracker::ReportBeginImplFrame(
425 const viz::BeginFrameArgs& args) {
426 if (termination_status_ != TerminationStatus::kActive)
427 return;
428
behdad2adc4232019-12-18 18:11:39429 if (ShouldIgnoreBeginFrameSource(args.frame_id.source_id))
Sadrul Habib Chowdhury23919172019-07-22 23:58:50430 return;
Sadrul Habib Chowdhurydc34c8b2019-12-16 18:39:13431
Sadrul Habib Chowdhury7fe10ea2019-12-11 01:59:29432#if DCHECK_IS_ON()
433 DCHECK(!is_inside_frame_) << TRACKER_DCHECK_MSG;
434 is_inside_frame_ = true;
Sadrul Habib Chowdhury23919172019-07-22 23:58:50435
Xida Chend56033c2019-12-05 13:31:41436 if (args.type == viz::BeginFrameArgs::NORMAL)
behdad2adc4232019-12-18 18:11:39437 impl_frames_.insert(args.frame_id);
Xida Chend56033c2019-12-05 13:31:41438#endif
behdad2adc4232019-12-18 18:11:39439 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 Chowdhuryc537f2f42019-12-05 19:52:28442 impl_throughput().frames_expected +=
Sadrul Habib Chowdhuryab4d350f2019-07-13 00:17:37443 begin_impl_frame_data_.previous_sequence_delta;
Xida Chen1102307b2019-10-11 17:03:15444
445 if (first_frame_timestamp_.is_null())
446 first_frame_timestamp_ = args.frame_time;
Sadrul Habib Chowdhuryab4d350f2019-07-13 00:17:37447}
448
449void FrameSequenceTracker::ReportBeginMainFrame(
450 const viz::BeginFrameArgs& args) {
451 if (termination_status_ != TerminationStatus::kActive)
452 return;
453
behdad2adc4232019-12-18 18:11:39454 if (ShouldIgnoreBeginFrameSource(args.frame_id.source_id))
Sadrul Habib Chowdhury23919172019-07-22 23:58:50455 return;
456
behdad2adc4232019-12-18 18:11:39457 if (ShouldIgnoreSequence(args.frame_id.sequence_number))
Xida Chend56033c2019-12-05 13:31:41458 return;
459
460#if DCHECK_IS_ON()
461 if (args.type == viz::BeginFrameArgs::NORMAL) {
behdad2adc4232019-12-18 18:11:39462 DCHECK(impl_frames_.contains(args.frame_id));
Xida Chend56033c2019-12-05 13:31:41463 }
464#endif
465
Mingjing Zhangc0ce5412019-11-07 22:00:07466 TRACKER_TRACE_STREAM << 'B';
467 TRACKER_TRACE_STREAM << "(" << begin_main_frame_data_.previous_sequence << ","
behdad2adc4232019-12-18 18:11:39468 << args.frame_id.sequence_number << ")";
469 UpdateTrackedFrameData(&begin_main_frame_data_, args.frame_id.source_id,
470 args.frame_id.sequence_number);
Sadrul Habib Chowdhury1b9fea6a2019-12-18 02:26:02471 if (!first_received_main_sequence_ ||
behdad2adc4232019-12-18 18:11:39472 first_received_main_sequence_ <= last_no_main_damage_sequence_)
473 first_received_main_sequence_ = args.frame_id.sequence_number;
Sadrul Habib Chowdhuryc537f2f42019-12-05 19:52:28474 main_throughput().frames_expected +=
Sadrul Habib Chowdhuryab4d350f2019-07-13 00:17:37475 begin_main_frame_data_.previous_sequence_delta;
476}
477
478void FrameSequenceTracker::ReportSubmitFrame(
479 uint32_t frame_token,
Sadrul Habib Chowdhury40a4d8c2019-09-05 03:02:31480 bool has_missing_content,
Sadrul Habib Chowdhuryab4d350f2019-07-13 00:17:37481 const viz::BeginFrameAck& ack,
482 const viz::BeginFrameArgs& origin_args) {
Xida Chend56033c2019-12-05 13:31:41483 if (termination_status_ != TerminationStatus::kActive ||
behdad2adc4232019-12-18 18:11:39484 ShouldIgnoreBeginFrameSource(ack.frame_id.source_id) ||
485 ShouldIgnoreSequence(ack.frame_id.sequence_number)) {
Xida Chend56033c2019-12-05 13:31:41486 ignored_frame_tokens_.insert(frame_token);
Sadrul Habib Chowdhuryab4d350f2019-07-13 00:17:37487 return;
488 }
489
Sadrul Habib Chowdhury7fe10ea2019-12-11 01:59:29490#if DCHECK_IS_ON()
491 DCHECK(is_inside_frame_) << TRACKER_DCHECK_MSG;
492#endif
Sadrul Habib Chowdhuryab4d350f2019-07-13 00:17:37493 if (first_submitted_frame_ == 0)
494 first_submitted_frame_ = frame_token;
495 last_submitted_frame_ = frame_token;
496
Sadrul Habib Chowdhury70d2fed2019-12-12 22:56:57497 TRACKER_TRACE_STREAM << 's';
Sadrul Habib Chowdhurydc34c8b2019-12-16 18:39:13498 const bool main_changes_after_sequence_started =
499 first_received_main_sequence_ &&
behdad2adc4232019-12-18 18:11:39500 origin_args.frame_id.sequence_number >= first_received_main_sequence_;
Sadrul Habib Chowdhurydc34c8b2019-12-16 18:39:13501 const bool main_changes_include_new_changes =
502 last_submitted_main_sequence_ == 0 ||
behdad2adc4232019-12-18 18:11:39503 origin_args.frame_id.sequence_number > last_submitted_main_sequence_;
Sadrul Habib Chowdhurydc34c8b2019-12-16 18:39:13504 const bool main_change_had_no_damage =
505 last_no_main_damage_sequence_ != 0 &&
behdad2adc4232019-12-18 18:11:39506 origin_args.frame_id.sequence_number == last_no_main_damage_sequence_;
Mingjing Zhang94314962019-11-05 02:59:20507
behdad2adc4232019-12-18 18:11:39508 if (!ShouldIgnoreBeginFrameSource(origin_args.frame_id.source_id) &&
Sadrul Habib Chowdhurydc34c8b2019-12-16 18:39:13509 main_changes_after_sequence_started && main_changes_include_new_changes &&
510 !main_change_had_no_damage) {
511 TRACKER_TRACE_STREAM << 'S';
512
behdad2adc4232019-12-18 18:11:39513 last_submitted_main_sequence_ = origin_args.frame_id.sequence_number;
Sadrul Habib Chowdhurydc34c8b2019-12-16 18:39:13514 main_frames_.push_back(frame_token);
515 DCHECK_GE(main_throughput().frames_expected, main_frames_.size())
516 << TRACKER_DCHECK_MSG;
Sadrul Habib Chowdhuryab4d350f2019-07-13 00:17:37517 }
Sadrul Habib Chowdhury40a4d8c2019-09-05 03:02:31518
519 if (has_missing_content) {
520 checkerboarding_.frames.push_back(frame_token);
521 }
Sadrul Habib Chowdhuryab4d350f2019-07-13 00:17:37522}
523
Sadrul Habib Chowdhury7fe10ea2019-12-11 01:59:29524void FrameSequenceTracker::ReportFrameEnd(const viz::BeginFrameArgs& args) {
525#if DCHECK_IS_ON()
526 if (termination_status_ != TerminationStatus::kActive)
527 return;
528
behdad2adc4232019-12-18 18:11:39529 if (ShouldIgnoreBeginFrameSource(args.frame_id.source_id))
Sadrul Habib Chowdhury7fe10ea2019-12-11 01:59:29530 return;
531
behdad2adc4232019-12-18 18:11:39532 if (ShouldIgnoreSequence(args.frame_id.sequence_number)) {
Sadrul Habib Chowdhury7fe10ea2019-12-11 01:59:29533 is_inside_frame_ = false;
534 return;
535 }
536
behdad2adc4232019-12-18 18:11:39537 TRACKER_TRACE_STREAM << "e(" << args.frame_id.sequence_number << ")";
Sadrul Habib Chowdhury7fe10ea2019-12-11 01:59:29538 DCHECK(is_inside_frame_) << TRACKER_DCHECK_MSG;
539 is_inside_frame_ = false;
540#endif
541}
542
Sadrul Habib Chowdhuryab4d350f2019-07-13 00:17:37543void 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 Chend56033c2019-12-05 13:31:41565 if (ignored_frame_tokens_.contains(frame_token))
566 return;
567
Mingjing Zhangc0ce5412019-11-07 22:00:07568 TRACKER_TRACE_STREAM << 'P';
Mingjing Zhang94314962019-11-05 02:59:20569
Sadrul Habib Chowdhury40a4d8c2019-09-05 03:02:31570 TRACE_EVENT_ASYNC_STEP_INTO_WITH_TIMESTAMP0(
Sadrul Habib Chowdhury590a32f2019-12-06 20:08:45571 "cc,benchmark", "FrameSequenceTracker", metrics_.get(), "FramePresented",
Sadrul Habib Chowdhury40a4d8c2019-09-05 03:02:31572 feedback.timestamp);
Sadrul Habib Chowdhuryab4d350f2019-07-13 00:17:37573 const bool was_presented = !feedback.timestamp.is_null();
574 if (was_presented && last_submitted_frame_) {
Sadrul Habib Chowdhuryc537f2f42019-12-05 19:52:28575 DCHECK_LT(impl_throughput().frames_produced,
576 impl_throughput().frames_expected)
Mingjing Zhang2879aa892019-11-01 02:54:54577 << TRACKER_DCHECK_MSG;
Sadrul Habib Chowdhuryc537f2f42019-12-05 19:52:28578 ++impl_throughput().frames_produced;
Sadrul Habib Chowdhuryab4d350f2019-07-13 00:17:37579
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 Chowdhuryc537f2f42019-12-05 19:52:28587 DCHECK_LT(main_throughput().frames_produced,
588 main_throughput().frames_expected)
Mingjing Zhang94314962019-11-05 02:59:20589 << TRACKER_DCHECK_MSG;
Sadrul Habib Chowdhuryc537f2f42019-12-05 19:52:28590 ++main_throughput().frames_produced;
Sadrul Habib Chowdhuryab4d350f2019-07-13 00:17:37591 }
592 main_frames_.pop_front();
593 }
Sadrul Habib Chowdhury40a4d8c2019-09-05 03:02:31594
595 if (was_presented) {
596 if (checkerboarding_.last_frame_had_checkerboarding) {
Mingjing Zhang2879aa892019-11-01 02:54:54597 DCHECK(!checkerboarding_.last_frame_timestamp.is_null())
598 << TRACKER_DCHECK_MSG;
599 DCHECK(!feedback.timestamp.is_null()) << TRACKER_DCHECK_MSG;
Sadrul Habib Chowdhury40a4d8c2019-09-05 03:02:31600
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 Zhang2879aa892019-11-01 02:54:54612 DCHECK(!interval.is_zero()) << TRACKER_DCHECK_MSG;
Sadrul Habib Chowdhury40a4d8c2019-09-05 03:02:31613 constexpr base::TimeDelta kEpsilon = base::TimeDelta::FromMilliseconds(1);
614 int64_t frames = (difference + kEpsilon) / interval;
Sadrul Habib Chowdhury590a32f2019-12-06 20:08:45615 metrics_->add_checkerboarded_frames(frames);
Sadrul Habib Chowdhury40a4d8c2019-09-05 03:02:31616 }
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 Chowdhuryab4d350f2019-07-13 00:17:37628}
629
630void FrameSequenceTracker::ReportImplFrameCausedNoDamage(
631 const viz::BeginFrameAck& ack) {
632 if (termination_status_ != TerminationStatus::kActive)
633 return;
634
behdad2adc4232019-12-18 18:11:39635 if (ShouldIgnoreBeginFrameSource(ack.frame_id.source_id))
Sadrul Habib Chowdhury23919172019-07-22 23:58:50636 return;
637
Sadrul Habib Chowdhuryab4d350f2019-07-13 00:17:37638 // 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.
behdad2adc4232019-12-18 18:11:39640 if (ShouldIgnoreSequence(ack.frame_id.sequence_number))
Sadrul Habib Chowdhuryab4d350f2019-07-13 00:17:37641 return;
Xida Chend56033c2019-12-05 13:31:41642
Mingjing Zhangc0ce5412019-11-07 22:00:07643 TRACKER_TRACE_STREAM << 'n';
Sadrul Habib Chowdhuryc537f2f42019-12-05 19:52:28644 DCHECK_GT(impl_throughput().frames_expected, 0u) << TRACKER_DCHECK_MSG;
645 DCHECK_GT(impl_throughput().frames_expected,
646 impl_throughput().frames_produced)
Mingjing Zhang2879aa892019-11-01 02:54:54647 << TRACKER_DCHECK_MSG;
Sadrul Habib Chowdhuryc537f2f42019-12-05 19:52:28648 --impl_throughput().frames_expected;
Sadrul Habib Chowdhuryab4d350f2019-07-13 00:17:37649
behdad2adc4232019-12-18 18:11:39650 if (begin_impl_frame_data_.previous_sequence == ack.frame_id.sequence_number)
Sadrul Habib Chowdhuryab4d350f2019-07-13 00:17:37651 begin_impl_frame_data_.previous_sequence = 0;
652}
653
654void FrameSequenceTracker::ReportMainFrameCausedNoDamage(
655 const viz::BeginFrameArgs& args) {
656 if (termination_status_ != TerminationStatus::kActive)
657 return;
658
behdad2adc4232019-12-18 18:11:39659 if (ShouldIgnoreBeginFrameSource(args.frame_id.source_id))
Sadrul Habib Chowdhury23919172019-07-22 23:58:50660 return;
661
behdad2adc4232019-12-18 18:11:39662 if (ShouldIgnoreSequence(args.frame_id.sequence_number))
Xida Chend56033c2019-12-05 13:31:41663 return;
Sadrul Habib Chowdhuryab4d350f2019-07-13 00:17:37664
Mingjing Zhangc0ce5412019-11-07 22:00:07665 TRACKER_TRACE_STREAM << 'N';
666 TRACKER_TRACE_STREAM << "(" << begin_main_frame_data_.previous_sequence << ","
behdad2adc4232019-12-18 18:11:39667 << args.frame_id.sequence_number << ")";
Sadrul Habib Chowdhuryc537f2f42019-12-05 19:52:28668 DCHECK_GT(main_throughput().frames_expected, 0u) << TRACKER_DCHECK_MSG;
669 DCHECK_GT(main_throughput().frames_expected,
670 main_throughput().frames_produced)
Mingjing Zhang2879aa892019-11-01 02:54:54671 << TRACKER_DCHECK_MSG;
behdad2adc4232019-12-18 18:11:39672 last_no_main_damage_sequence_ = args.frame_id.sequence_number;
Sadrul Habib Chowdhuryc537f2f42019-12-05 19:52:28673 --main_throughput().frames_expected;
674 DCHECK_GE(main_throughput().frames_expected, main_frames_.size())
Mingjing Zhang2879aa892019-11-01 02:54:54675 << TRACKER_DCHECK_MSG;
Sadrul Habib Chowdhuryab4d350f2019-07-13 00:17:37676
behdad2adc4232019-12-18 18:11:39677 if (begin_main_frame_data_.previous_sequence == args.frame_id.sequence_number)
Sadrul Habib Chowdhuryab4d350f2019-07-13 00:17:37678 begin_main_frame_data_.previous_sequence = 0;
679}
680
681void 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
688void 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 Zhang0ccb625d2019-11-20 17:50:20693 uint32_t current_latency = sequence_number - frame_data->previous_sequence;
Sadrul Habib Chowdhury70d2fed2019-12-12 22:56:57694 DCHECK_GT(current_latency, 0u);
Sadrul Habib Chowdhuryab4d350f2019-07-13 00:17:37695 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 Chowdhury23919172019-07-22 23:58:50703bool 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 Chend56033c2019-12-05 13:31:41710// This check ensures that when ReportBeginMainFrame, or ReportSubmitFrame, or
711// ReportFramePresented is called for a particular arg, the ReportBeginImplFrame
712// is been called already.
713bool 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 Chowdhuryab4d350f2019-07-13 00:17:37719std::unique_ptr<base::trace_event::TracedValue>
Sadrul Habib Chowdhuryc537f2f42019-12-05 19:52:28720FrameSequenceMetrics::ThroughputData::ToTracedValue(
Sadrul Habib Chowdhuryab4d350f2019-07-13 00:17:37721 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 Chen1102307b2019-10-11 17:03:15731bool FrameSequenceTracker::ShouldReportMetricsNow(
732 const viz::BeginFrameArgs& args) const {
Sadrul Habib Chowdhury590a32f2019-12-06 20:08:45733 return metrics_->HasEnoughDataForReporting() &&
734 !first_frame_timestamp_.is_null() &&
735 args.frame_time - first_frame_timestamp_ >= time_delta_to_report_;
736}
737
738std::unique_ptr<FrameSequenceMetrics> FrameSequenceTracker::TakeMetrics() {
739 return std::move(metrics_);
Xida Chen1102307b2019-10-11 17:03:15740}
741
Sadrul Habib Chowdhuryc537f2f42019-12-05 19:52:28742base::Optional<int> FrameSequenceMetrics::ThroughputData::ReportHistogram(
Sadrul Habib Chowdhurydb3d7be72019-07-13 03:27:32743 FrameSequenceTrackerType sequence_type,
Sadrul Habib Chowdhuryd4e8f4a2019-12-13 15:10:27744 ThreadType thread_type,
Sadrul Habib Chowdhurydb3d7be72019-07-13 03:27:32745 int metric_index,
746 const ThroughputData& data) {
747 DCHECK_LT(sequence_type, FrameSequenceTrackerType::kMaxType);
748
Sadrul Habib Chowdhury6c17e5f2019-07-26 16:57:10749 STATIC_HISTOGRAM_POINTER_GROUP(
Sadrul Habib Chowdhury4bba3d02019-09-06 02:33:27750 GetFrameSequenceLengthHistogramName(sequence_type), sequence_type,
751 FrameSequenceTrackerType::kMaxType, Add(data.frames_expected),
Sadrul Habib Chowdhury6c17e5f2019-07-26 16:57:10752 base::Histogram::FactoryGet(
Sadrul Habib Chowdhury4bba3d02019-09-06 02:33:27753 GetFrameSequenceLengthHistogramName(sequence_type), 1, 1000, 50,
Sadrul Habib Chowdhury6c17e5f2019-07-26 16:57:10754 base::HistogramBase::kUmaTargetedHistogramFlag));
Sadrul Habib Chowdhurydb3d7be72019-07-13 03:27:32755
Sadrul Habib Chowdhurydb3d7be72019-07-13 03:27:32756 if (data.frames_expected < kMinFramesForThroughputMetric)
Xida Chenf8afda32019-09-25 01:46:07757 return base::nullopt;
Sadrul Habib Chowdhurydb3d7be72019-07-13 03:27:32758
Sadrul Habib Chowdhurydb3d7be72019-07-13 03:27:32759 const int percent =
760 static_cast<int>(100 * data.frames_produced / data.frames_expected);
Sadrul Habib Chowdhury3ebe03822019-12-16 18:29:20761
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 Chowdhuryd4e8f4a2019-12-13 15:10:27782 const char* thread_name =
783 thread_type == ThreadType::kCompositor
784 ? "CompositorThread"
785 : thread_type == ThreadType::kMain ? "MainThread" : "SlowerThread";
Sadrul Habib Chowdhurydb3d7be72019-07-13 03:27:32786 STATIC_HISTOGRAM_POINTER_GROUP(
Sadrul Habib Chowdhury4bba3d02019-09-06 02:33:27787 GetThroughputHistogramName(sequence_type, thread_name), metric_index,
788 kMaximumHistogramIndex, Add(percent),
Sadrul Habib Chowdhurydb3d7be72019-07-13 03:27:32789 base::LinearHistogram::FactoryGet(
Sadrul Habib Chowdhury4bba3d02019-09-06 02:33:27790 GetThroughputHistogramName(sequence_type, thread_name), 1, 100, 101,
791 base::HistogramBase::kUmaTargetedHistogramFlag));
Xida Chenf8afda32019-09-25 01:46:07792 return percent;
Sadrul Habib Chowdhurydb3d7be72019-07-13 03:27:32793}
794
Sadrul Habib Chowdhury40a4d8c2019-09-05 03:02:31795FrameSequenceTracker::CheckerboardingData::CheckerboardingData() = default;
796FrameSequenceTracker::CheckerboardingData::~CheckerboardingData() = default;
797
Sadrul Habib Chowdhuryab4d350f2019-07-13 00:17:37798} // namespace cc