#ifdef UNSAFE_BUFFERS_BUILD
#pragma allow_unsafe_buffers
#endif
#include "cc/metrics/compositor_frame_reporter.h"
#include <algorithm>
#include <cmath>
#include <cstdint>
#include <deque>
#include <memory>
#include <string>
#include <type_traits>
#include <utility>
#include "base/cpu_reduction_experiment.h"
#include "base/debug/alias.h"
#include "base/metrics/histogram_macros.h"
#include "base/notreached.h"
#include "base/ranges/algorithm.h"
#include "base/strings/strcat.h"
#include "base/strings/string_util.h"
#include "base/time/time.h"
#include "base/trace_event/common/trace_event_common.h"
#include "base/trace_event/trace_event.h"
#include "base/trace_event/trace_id_helper.h"
#include "base/trace_event/typed_macros.h"
#include "base/tracing/protos/chrome_track_event.pbzero.h"
#include "cc/base/rolling_time_delta_history.h"
#include "cc/metrics/dropped_frame_counter.h"
#include "cc/metrics/event_latency_tracing_recorder.h"
#include "cc/metrics/event_latency_tracker.h"
#include "cc/metrics/event_metrics.h"
#include "cc/metrics/frame_sequence_tracker.h"
#include "cc/metrics/latency_ukm_reporter.h"
#include "services/tracing/public/cpp/perfetto/macros.h"
#include "third_party/perfetto/protos/perfetto/trace/track_event/chrome_frame_reporter.pbzero.h"
#include "ui/events/types/event_type.h"
namespace cc {
namespace {
StageType;
FrameReportType;
BlinkBreakdown;
VizBreakdown;
FrameFinalState;
constexpr int kFrameReportTypeCount = …;
constexpr int kStageTypeCount = …;
constexpr int kAllBreakdownCount = …;
constexpr int kVizBreakdownInitialIndex = …;
constexpr int kBlinkBreakdownInitialIndex = …;
constexpr int kFrameSequenceTrackerTypeCount = …;
constexpr size_t kMaxOwnedPartialUpdateDependents = …;
constexpr const char* kReportTypeNames[]{ … };
static_assert …;
constexpr int kStagesWithBreakdownCount = …;
constexpr int kMaxCompositorLatencyHistogramIndex = …;
constexpr base::TimeDelta kCompositorLatencyHistogramMin = …;
constexpr base::TimeDelta kCompositorLatencyHistogramMax = …;
constexpr int kCompositorLatencyHistogramBucketCount = …;
constexpr const char kEventLatencyBaseHistogramName[] = …;
constexpr int kEventLatencyEventTypeCount = …;
constexpr const char kGenerationToBrowserMainName[] = …;
constexpr int kEventLatencyScrollTypeCount = …;
constexpr int kEventLatencyPinchTypeCount = …;
constexpr int kEventLatencyGestureTypeCount = …;
constexpr int kMaxEventLatencyHistogramIndex = …;
constexpr base::TimeDelta kEventLatencyHistogramMin = …;
constexpr base::TimeDelta kEventLatencyHistogramMax = …;
constexpr int kEventLatencyHistogramBucketCount = …;
constexpr base::TimeDelta kHighLatencyMin = …;
constexpr int kNumOfCompositorStages = …;
constexpr int kNumOfBlinkStages = …;
constexpr int kNumOfVizStages = …;
constexpr int kNumDispatchStages = …;
constexpr double kWeightOfCurStageInPercent = …;
constexpr double kEpsilon = …;
std::string GetCompositorLatencyHistogramName(
FrameReportType report_type,
FrameSequenceTrackerType frame_sequence_tracker_type,
StageType stage_type,
std::optional<VizBreakdown> viz_breakdown,
std::optional<BlinkBreakdown> blink_breakdown) { … }
void ReportEventLatencyMetric(
const std::string& name,
int index,
base::TimeDelta latency,
const std::optional<EventMetrics::HistogramBucketing>& bucketing,
bool guiding_metric = false) { … }
constexpr char kTraceCategory[] = …);
bool IsTracingEnabled() { … }
base::TimeTicks ComputeSafeDeadlineForFrame(const viz::BeginFrameArgs& args) { … }
base::TimeDelta CalculateWeightedAverage(base::TimeDelta previous_value,
base::TimeDelta current_value) { … }
base::TimeDelta PredictLatency(base::TimeDelta previous_prediction,
base::TimeDelta current_latency) { … }
double DetermineHighestContribution(
double contribution_change,
double highest_contribution_change,
const std::string& stage_name,
std::vector<std::string>& high_latency_stages) { … }
void TraceScrollJankMetrics(const EventMetrics::List& events_metrics,
int32_t fling_input_count,
int32_t normal_input_count,
perfetto::EventContext& ctx) { … }
constexpr int kMaxGestureScrollHistogramIndex = …;
int GetGestureScrollIndex(EventMetrics::EventType type) { … }
constexpr int kMaxVSyncRatioHistogramIndex = …;
const char* GetVSyncRatioTypeName(
CompositorFrameReporter::VSyncRatioType type) { … }
void ReportVSyncRatioMetric(const std::string& base_histogram_name,
int gesture_scroll_index,
CompositorFrameReporter::VSyncRatioType type,
int percentage) { … }
#if BUILDFLAG(IS_ANDROID)
constexpr const char kTopControlsMovedName[] = ".TopControlsMoved";
constexpr const char kTopControlsDidNotMoveName[] = ".TopControlsDidNotMove";
void ReportTopControlsMetric(
const std::string& name,
bool top_controls_moved,
base::TimeDelta latency,
EventMetrics::EventType type,
const std::optional<EventMetrics::HistogramBucketing>& bucketing) {
if (!bucketing) {
return;
}
if (top_controls_moved) {
std::string versioned_name = name + kTopControlsMovedName;
STATIC_HISTOGRAM_POINTER_GROUP(
versioned_name, GetGestureScrollIndex(type),
kMaxGestureScrollHistogramIndex,
AddTimeMicrosecondsGranularity(latency),
base::Histogram::FactoryMicrosecondsTimeGet(
versioned_name, bucketing->min, bucketing->max, bucketing->count,
base::HistogramBase::kUmaTargetedHistogramFlag));
} else if (base::ShouldLogHistogramForCpuReductionExperiment()) {
std::string versioned_name = name + kTopControlsDidNotMoveName;
STATIC_HISTOGRAM_POINTER_GROUP(
versioned_name, GetGestureScrollIndex(type),
kMaxGestureScrollHistogramIndex,
AddTimeMicrosecondsGranularity(latency),
base::Histogram::FactoryMicrosecondsTimeGet(
versioned_name, bucketing->min, bucketing->max, bucketing->count,
base::HistogramBase::kUmaTargetedHistogramFlag));
}
}
#endif
}
CompositorFrameReporter::ProcessedBlinkBreakdown::Iterator::Iterator(
const ProcessedBlinkBreakdown* owner)
: … { … }
CompositorFrameReporter::ProcessedBlinkBreakdown::Iterator::~Iterator() =
default;
bool CompositorFrameReporter::ProcessedBlinkBreakdown::Iterator::IsValid()
const { … }
void CompositorFrameReporter::ProcessedBlinkBreakdown::Iterator::Advance() { … }
BlinkBreakdown
CompositorFrameReporter::ProcessedBlinkBreakdown::Iterator::GetBreakdown()
const { … }
base::TimeDelta
CompositorFrameReporter::ProcessedBlinkBreakdown::Iterator::GetLatency() const { … }
CompositorFrameReporter::ProcessedBlinkBreakdown::ProcessedBlinkBreakdown(
base::TimeTicks blink_start_time,
base::TimeTicks begin_main_frame_start,
const BeginMainFrameMetrics& blink_breakdown) { … }
CompositorFrameReporter::ProcessedBlinkBreakdown::~ProcessedBlinkBreakdown() =
default;
CompositorFrameReporter::ProcessedBlinkBreakdown::Iterator
CompositorFrameReporter::ProcessedBlinkBreakdown::CreateIterator() const { … }
CompositorFrameReporter::ProcessedVizBreakdown::Iterator::Iterator(
const ProcessedVizBreakdown* owner,
bool skip_swap_start_to_swap_end)
: … { … }
CompositorFrameReporter::ProcessedVizBreakdown::Iterator::~Iterator() = default;
bool CompositorFrameReporter::ProcessedVizBreakdown::Iterator::IsValid() const { … }
void CompositorFrameReporter::ProcessedVizBreakdown::Iterator::Advance() { … }
VizBreakdown
CompositorFrameReporter::ProcessedVizBreakdown::Iterator::GetBreakdown() const { … }
base::TimeTicks
CompositorFrameReporter::ProcessedVizBreakdown::Iterator::GetStartTime() const { … }
base::TimeTicks
CompositorFrameReporter::ProcessedVizBreakdown::Iterator::GetEndTime() const { … }
base::TimeDelta
CompositorFrameReporter::ProcessedVizBreakdown::Iterator::GetDuration() const { … }
bool CompositorFrameReporter::ProcessedVizBreakdown::Iterator::HasValue()
const { … }
void CompositorFrameReporter::ProcessedVizBreakdown::Iterator::
SkipBreakdownsIfNecessary() { … }
CompositorFrameReporter::ProcessedVizBreakdown::ProcessedVizBreakdown(
base::TimeTicks viz_start_time,
const viz::FrameTimingDetails& viz_breakdown) { … }
CompositorFrameReporter::ProcessedVizBreakdown::~ProcessedVizBreakdown() =
default;
CompositorFrameReporter::ProcessedVizBreakdown::Iterator
CompositorFrameReporter::ProcessedVizBreakdown::CreateIterator(
bool skip_swap_start_to_swap_end_if_breakdown_available) const { … }
CompositorFrameReporter::CompositorLatencyInfo::CompositorLatencyInfo() =
default;
CompositorFrameReporter::CompositorLatencyInfo::CompositorLatencyInfo(
base::TimeDelta init_value)
: … { … }
CompositorFrameReporter::CompositorLatencyInfo::~CompositorLatencyInfo() =
default;
CompositorFrameReporter::CompositorFrameReporter(
const ActiveTrackers& active_trackers,
const viz::BeginFrameArgs& args,
bool should_report_histograms,
SmoothThread smooth_thread,
FrameInfo::SmoothEffectDrivingThread scrolling_thread,
int layer_tree_host_id,
const GlobalMetricsTrackers& trackers)
: … { … }
const char* CompositorFrameReporter::GetStageName(
StageType stage_type,
std::optional<VizBreakdown> viz_breakdown,
std::optional<BlinkBreakdown> blink_breakdown,
bool impl_only) { … }
const char* CompositorFrameReporter::GetVizBreakdownName(
VizBreakdown breakdown) { … }
std::unique_ptr<CompositorFrameReporter>
CompositorFrameReporter::CopyReporterAtBeginImplStage() { … }
CompositorFrameReporter::~CompositorFrameReporter() { … }
CompositorFrameReporter::StageData::StageData() = default;
CompositorFrameReporter::StageData::StageData(StageType stage_type,
base::TimeTicks start_time,
base::TimeTicks end_time)
: … { … }
CompositorFrameReporter::StageData::StageData(const StageData&) = default;
CompositorFrameReporter::StageData::~StageData() = default;
CompositorFrameReporter::EventLatencyInfo::EventLatencyInfo(
const int num_dispatch_stages,
const int num_compositor_stages)
: … { … }
CompositorFrameReporter::EventLatencyInfo::~EventLatencyInfo() = default;
void CompositorFrameReporter::StartStage(
CompositorFrameReporter::StageType stage_type,
base::TimeTicks start_time) { … }
void CompositorFrameReporter::TerminateFrame(
FrameTerminationStatus termination_status,
base::TimeTicks termination_time) { … }
void CompositorFrameReporter::OnFinishImplFrame(base::TimeTicks timestamp) { … }
void CompositorFrameReporter::OnAbortBeginMainFrame(base::TimeTicks timestamp) { … }
void CompositorFrameReporter::OnDidNotProduceFrame(
FrameSkippedReason skip_reason) { … }
void CompositorFrameReporter::EnableCompositorOnlyReporting() { … }
void CompositorFrameReporter::SetBlinkBreakdown(
std::unique_ptr<BeginMainFrameMetrics> blink_breakdown,
base::TimeTicks begin_main_start) { … }
void CompositorFrameReporter::SetVizBreakdown(
const viz::FrameTimingDetails& viz_breakdown) { … }
void CompositorFrameReporter::AddEventsMetrics(
EventMetrics::List events_metrics) { … }
EventMetrics::List CompositorFrameReporter::TakeEventsMetrics() { … }
EventMetrics::List CompositorFrameReporter::TakeMainBlockedEventsMetrics() { … }
void CompositorFrameReporter::DidSuccessfullyPresentFrame() { … }
void CompositorFrameReporter::TerminateReporter() { … }
void CompositorFrameReporter::EndCurrentStage(base::TimeTicks end_time) { … }
void CompositorFrameReporter::ReportCompositorLatencyMetrics() const { … }
void CompositorFrameReporter::ReportStageHistogramWithBreakdown(
const CompositorFrameReporter::StageData& stage,
FrameSequenceTrackerType frame_sequence_tracker_type) const { … }
void CompositorFrameReporter::ReportCompositorLatencyBlinkBreakdowns(
FrameSequenceTrackerType frame_sequence_tracker_type) const { … }
void CompositorFrameReporter::ReportCompositorLatencyVizBreakdowns(
FrameSequenceTrackerType frame_sequence_tracker_type) const { … }
void CompositorFrameReporter::ReportCompositorLatencyHistogram(
FrameSequenceTrackerType frame_sequence_tracker_type,
StageType stage_type,
std::optional<VizBreakdown> viz_breakdown,
std::optional<BlinkBreakdown> blink_breakdown,
base::TimeDelta time_delta) const { … }
void CompositorFrameReporter::ReportEventLatencyMetrics() const { … }
void CompositorFrameReporter::ReportCompositorLatencyTraceEvents(
const FrameInfo& info) const { … }
void CompositorFrameReporter::ReportScrollJankMetrics() const { … }
void CompositorFrameReporter::ReportEventLatencyTraceEvents() const { … }
base::TimeDelta CompositorFrameReporter::SumOfStageHistory() const { … }
base::TimeTicks CompositorFrameReporter::Now() const { … }
void CompositorFrameReporter::AdoptReporter(
std::unique_ptr<CompositorFrameReporter> reporter) { … }
void CompositorFrameReporter::CalculateCompositorLatencyPrediction(
CompositorLatencyInfo& previous_predictions,
base::TimeDelta prediction_deviation_threshold) { … }
void CompositorFrameReporter::CalculateEventLatencyPrediction(
CompositorFrameReporter::EventLatencyInfo& predicted_event_latency,
base::TimeDelta prediction_deviation_threshold) { … }
void CompositorFrameReporter::SetPartialUpdateDecider(
CompositorFrameReporter* decider) { … }
void CompositorFrameReporter::DiscardOldPartialUpdateReporters() { … }
base::WeakPtr<CompositorFrameReporter> CompositorFrameReporter::GetWeakPtr() { … }
FrameInfo CompositorFrameReporter::GenerateFrameInfo() const { … }
void CompositorFrameReporter::FindHighLatencyAttribution(
CompositorLatencyInfo& previous_predictions,
CompositorLatencyInfo& current_stage_durations) { … }
void CompositorFrameReporter::FindEventLatencyAttribution(
EventMetrics* event_metrics,
CompositorFrameReporter::EventLatencyInfo& predicted_event_latency,
CompositorFrameReporter::EventLatencyInfo& actual_event_latency) { … }
}