[go: nahoru, domu]

blob: b5d08e138a1bf9199752b48cfa02a1f74b22cb83 [file] [log] [blame]
// Copyright 2020 The Chromium Authors
// 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 <bitset>
#include <cmath>
#include <memory>
#include "base/check.h"
#include "base/functional/callback.h"
#include "base/memory/raw_ptr.h"
#include "base/trace_event/traced_value.h"
#include "cc/cc_export.h"
#include "cc/metrics/frame_info.h"
#include "components/viz/common/frame_sinks/begin_frame_args.h"
namespace viz {
struct BeginFrameArgs;
} // namespace viz
namespace cc {
struct FrameInfo;
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.
kCanvasAnimation = 10,
kJSAnimation = 11,
kSETMainThreadAnimation = 12,
kSETCompositorAnimation = 13,
kMaxType
};
using ActiveTrackers =
std::bitset<static_cast<size_t>(FrameSequenceTrackerType::kMaxType)>;
inline bool IsScrollActive(const ActiveTrackers& trackers) {
return trackers.test(
static_cast<size_t>(FrameSequenceTrackerType::kWheelScroll)) ||
trackers.test(
static_cast<size_t>(FrameSequenceTrackerType::kTouchScroll)) ||
trackers.test(
static_cast<size_t>(FrameSequenceTrackerType::kScrollbarScroll));
}
inline bool HasMainThreadAnimation(const ActiveTrackers& trackers) {
return trackers.test(static_cast<size_t>(
FrameSequenceTrackerType::kMainThreadAnimation)) ||
trackers.test(
static_cast<size_t>(FrameSequenceTrackerType::kCanvasAnimation)) ||
trackers.test(
static_cast<size_t>(FrameSequenceTrackerType::kJSAnimation)) ||
trackers.test(static_cast<size_t>(FrameSequenceTrackerType::kRAF));
}
inline bool HasCompositorThreadAnimation(const ActiveTrackers& trackers) {
return trackers.test(
static_cast<size_t>(FrameSequenceTrackerType::kCompositorAnimation));
}
class CC_EXPORT FrameSequenceMetrics {
public:
explicit FrameSequenceMetrics(FrameSequenceTrackerType type);
~FrameSequenceMetrics();
FrameSequenceMetrics(const FrameSequenceMetrics&) = delete;
FrameSequenceMetrics& operator=(const FrameSequenceMetrics&) = delete;
void SetScrollingThread(FrameInfo::SmoothEffectDrivingThread thread);
struct CustomReportData {
uint32_t frames_expected_v3 = 0;
uint32_t frames_dropped_v3 = 0;
uint32_t jank_count_v3 = 0;
};
using CustomReporter = base::OnceCallback<void(const CustomReportData& 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).
FrameInfo::SmoothEffectDrivingThread GetEffectiveThread() const;
void Merge(std::unique_ptr<FrameSequenceMetrics> metrics);
bool HasEnoughDataForReporting() const;
bool HasDataLeftForReporting() const;
// Report related metrics: throughput, checkboarding...
void ReportMetrics();
void AddSortedFrame(const viz::BeginFrameArgs& args,
const FrameInfo& frame_info);
FrameSequenceTrackerType type() const { return type_; }
// Must be called before destructor.
void ReportLeftoverData();
void AdoptTrace(FrameSequenceMetrics* adopt_from);
private:
friend class FrameSequenceMetricsTest;
friend class FrameSequenceTrackerTest;
// FrameInfo is a merger of two threads' frame production. We should only look
// at the `final_state`, `last_presented_termination_time` and
// `termination_time` for the GetEffectiveThread.
void CalculateCheckerboardingAndJankV3(
const viz::BeginFrameArgs& args,
const FrameInfo& frame_info,
FrameInfo::FrameFinalState final_state,
base::TimeTicks last_presented_termination_time,
base::TimeTicks termination_time);
void IncrementJankIdleTimeV3(base::TimeTicks last_presented_termination_time,
base::TimeTicks termination_time);
void TraceJankV3(uint64_t sequence_number,
base::TimeTicks last_termination_time,
base::TimeTicks termination_time);
const FrameSequenceTrackerType type_;
// Track state for measuring the various Graphics.Smoothness V3 metrics.
struct V3 {
V3();
~V3();
uint32_t frames_expected = 0;
uint32_t frames_dropped = 0;
uint32_t frames_missing_content = 0;
uint32_t no_update_count = 0;
uint32_t jank_count = 0;
viz::BeginFrameArgs last_begin_frame_args;
FrameInfo last_frame;
FrameInfo last_presented_frame;
base::TimeDelta last_frame_delta;
base::TimeDelta no_update_duration;
} v3_;
// Tracks some data to generate useful trace events.
struct TraceData {
explicit TraceData(FrameSequenceMetrics* metrics);
~TraceData();
raw_ptr<FrameSequenceMetrics> metrics;
uint64_t last_presented_sequence_number = 0u;
base::TimeTicks last_timestamp = base::TimeTicks::Now();
int frame_count = 0;
bool enabled = false;
uint64_t trace_id = 0u;
void Advance(base::TimeTicks start_timestamp,
base::TimeTicks new_timestamp,
uint32_t expected,
uint32_t dropped,
uint64_t sequence_number,
const char* histogram_name);
void TerminateV3(const V3& v3,
FrameInfo::SmoothEffectDrivingThread effective_thread);
} trace_data_{this};
TraceData trace_data_v3_{this};
FrameInfo::SmoothEffectDrivingThread scrolling_thread_ =
FrameInfo::SmoothEffectDrivingThread::kUnknown;
// Callback invoked to report metrics for kCustom typed sequence.
CustomReporter custom_reporter_;
};
bool ShouldReportForAnimation(FrameSequenceTrackerType sequence_type,
FrameInfo::SmoothEffectDrivingThread thread_type);
bool ShouldReportForInteraction(
FrameSequenceTrackerType sequence_type,
FrameInfo::SmoothEffectDrivingThread reporting_thread_type,
FrameInfo::SmoothEffectDrivingThread metrics_effective_thread_type);
} // namespace cc
#endif // CC_METRICS_FRAME_SEQUENCE_METRICS_H_