| // Copyright 2020 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef CC_METRICS_FRAME_SEQUENCE_METRICS_H_ |
| #define CC_METRICS_FRAME_SEQUENCE_METRICS_H_ |
| |
| #include <memory> |
| |
| #include "base/callback.h" |
| #include "base/optional.h" |
| #include "base/trace_event/traced_value.h" |
| #include "cc/cc_export.h" |
| |
| namespace cc { |
| class ThroughputUkmReporter; |
| class JankMetrics; |
| |
| enum class FrameSequenceTrackerType { |
| // Used as an enum for metrics. DO NOT reorder or delete values. Rather, |
| // add them at the end and increment kMaxType. |
| kCompositorAnimation = 0, |
| kMainThreadAnimation = 1, |
| kPinchZoom = 2, |
| kRAF = 3, |
| kTouchScroll = 4, |
| kVideo = 6, |
| kWheelScroll = 7, |
| kScrollbarScroll = 8, |
| kCustom = 9, // Note that the metrics for kCustom are not reported on UMA, |
| // and instead are dispatched back to the LayerTreeHostClient. |
| kMaxType |
| }; |
| |
| class CC_EXPORT FrameSequenceMetrics { |
| public: |
| FrameSequenceMetrics(FrameSequenceTrackerType type, |
| ThroughputUkmReporter* ukm_reporter); |
| ~FrameSequenceMetrics(); |
| |
| FrameSequenceMetrics(const FrameSequenceMetrics&) = delete; |
| FrameSequenceMetrics& operator=(const FrameSequenceMetrics&) = delete; |
| |
| enum class ThreadType { kMain, kCompositor, kSlower, kUnknown }; |
| |
| struct ThroughputData { |
| static std::unique_ptr<base::trace_event::TracedValue> ToTracedValue( |
| const ThroughputData& impl, |
| const ThroughputData& main, |
| ThreadType effective_thred); |
| |
| // Returns the throughput in percent, a return value of base::nullopt |
| // indicates that no throughput metric is reported. |
| static base::Optional<int> ReportHistogram(FrameSequenceMetrics* metrics, |
| ThreadType thread_type, |
| int metric_index, |
| const ThroughputData& data); |
| |
| void Merge(const ThroughputData& data) { |
| frames_expected += data.frames_expected; |
| frames_produced += data.frames_produced; |
| #if DCHECK_IS_ON() |
| frames_processed += data.frames_processed; |
| frames_received += data.frames_received; |
| #endif |
| } |
| |
| int DroppedFramePercent() const { |
| if (frames_expected == 0) |
| return 0; |
| return std::ceil(100 * (frames_expected - frames_produced) / |
| static_cast<double>(frames_expected)); |
| } |
| |
| // Tracks the number of frames that were expected to be shown during this |
| // frame-sequence. |
| uint32_t frames_expected = 0; |
| |
| // Tracks the number of frames that were actually presented to the user |
| // during this frame-sequence. |
| uint32_t frames_produced = 0; |
| |
| #if DCHECK_IS_ON() |
| // Tracks the number of frames that is either submitted or reported as no |
| // damage. |
| uint32_t frames_processed = 0; |
| |
| // Tracks the number of begin-frames that are received. |
| uint32_t frames_received = 0; |
| #endif |
| }; |
| |
| void SetScrollingThread(ThreadType thread); |
| |
| using CustomReporter = |
| base::OnceCallback<void(ThroughputData throughput_data)>; |
| // Sets reporter callback for kCustom typed sequence. |
| void SetCustomReporter(CustomReporter custom_reporter); |
| |
| // Returns the 'effective thread' for the metrics (i.e. the thread most |
| // relevant for this metric). |
| ThreadType GetEffectiveThread() const; |
| |
| void Merge(std::unique_ptr<FrameSequenceMetrics> metrics); |
| bool HasEnoughDataForReporting() const; |
| bool HasDataLeftForReporting() const; |
| // Report related metrics: throughput, checkboarding... |
| void ReportMetrics(); |
| |
| ThroughputData& impl_throughput() { return impl_throughput_; } |
| ThroughputData& main_throughput() { return main_throughput_; } |
| ThroughputData& aggregated_throughput() { return aggregated_throughput_; } |
| void add_checkerboarded_frames(int64_t frames) { |
| frames_checkerboarded_ += frames; |
| } |
| uint32_t frames_checkerboarded() const { return frames_checkerboarded_; } |
| |
| FrameSequenceTrackerType type() const { return type_; } |
| ThroughputUkmReporter* ukm_reporter() const { |
| return throughput_ukm_reporter_; |
| } |
| |
| // Must be called before destructor. |
| void ReportLeftoverData(); |
| |
| void AdoptTrace(FrameSequenceMetrics* adopt_from); |
| void AdvanceTrace(base::TimeTicks timestamp); |
| |
| void ComputeJank(FrameSequenceMetrics::ThreadType thread_type, |
| base::TimeTicks presentation_time, |
| base::TimeDelta frame_interval); |
| |
| private: |
| const FrameSequenceTrackerType type_; |
| |
| // Tracks some data to generate useful trace events. |
| struct TraceData { |
| explicit TraceData(FrameSequenceMetrics* metrics); |
| ~TraceData(); |
| FrameSequenceMetrics* metrics; |
| base::TimeTicks last_timestamp = base::TimeTicks::Now(); |
| int frame_count = 0; |
| bool enabled = false; |
| void* trace_id = nullptr; |
| |
| void Advance(base::TimeTicks new_timestamp); |
| void Terminate(); |
| } trace_data_{this}; |
| |
| // Pointer to the reporter owned by the FrameSequenceTrackerCollection. |
| ThroughputUkmReporter* const throughput_ukm_reporter_; |
| |
| ThroughputData impl_throughput_; |
| ThroughputData main_throughput_; |
| // The aggregated throughput for the main/compositor thread. |
| ThroughputData aggregated_throughput_; |
| |
| ThreadType scrolling_thread_ = ThreadType::kUnknown; |
| |
| // Tracks the number of produced frames that had some amount of |
| // checkerboarding, and how many frames showed such checkerboarded frames. |
| uint32_t frames_checkerboarded_ = 0; |
| |
| // Callback invoked to report metrics for kCustom typed sequence. |
| CustomReporter custom_reporter_; |
| |
| std::unique_ptr<JankMetrics> jank_reporter_; |
| }; |
| |
| } // namespace cc |
| |
| #endif // CC_METRICS_FRAME_SEQUENCE_METRICS_H_ |