Commit 0b919c6d authored by Mohsen Izadi's avatar Mohsen Izadi Committed by Commit Bot

Add Viz breakdown to EventLatency trace events

Please see a screenshot from a sample trace at:
https://drive.google.com/file/d/1rTdrSmfPoM07ycf76cpLAC1zHZrfwus0/view

Bug: 1054009
Change-Id: Ia24056e6a9951dae4e4be00f1e58aa6c93ff2706
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2166637Reviewed-by: default avatarSadrul Chowdhury <sadrul@chromium.org>
Commit-Queue: Mohsen Izadi <mohsen@chromium.org>
Cr-Commit-Position: refs/heads/master@{#770946}
parent 090f4e37
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
#include "cc/metrics/compositor_frame_reporter.h" #include "cc/metrics/compositor_frame_reporter.h"
#include <algorithm>
#include <memory> #include <memory>
#include <string> #include <string>
#include <utility> #include <utility>
...@@ -11,6 +12,7 @@ ...@@ -11,6 +12,7 @@
#include "base/metrics/histogram_macros.h" #include "base/metrics/histogram_macros.h"
#include "base/stl_util.h" #include "base/stl_util.h"
#include "base/strings/strcat.h" #include "base/strings/strcat.h"
#include "base/time/time.h"
#include "base/trace_event/trace_event.h" #include "base/trace_event/trace_event.h"
#include "cc/base/rolling_time_delta_history.h" #include "cc/base/rolling_time_delta_history.h"
#include "cc/metrics/frame_sequence_tracker.h" #include "cc/metrics/frame_sequence_tracker.h"
...@@ -42,7 +44,8 @@ constexpr int kFrameSequenceTrackerTypeCount = ...@@ -42,7 +44,8 @@ constexpr int kFrameSequenceTrackerTypeCount =
static_cast<int>(FrameSequenceTrackerType::kMaxType) + 1; static_cast<int>(FrameSequenceTrackerType::kMaxType) + 1;
// Names for the viz breakdowns that are shown in trace as substages under // Names for the viz breakdowns that are shown in trace as substages under
// PipelineReporter -> SubmitCompositorFrameToPresentationCompositorFrame // PipelineReporter -> SubmitCompositorFrameToPresentationCompositorFrame or
// EventLatency -> SubmitCompositorFrameToPresentationCompositorFrame.
constexpr const char* GetVizBreakdownName(VizBreakdown stage) { constexpr const char* GetVizBreakdownName(VizBreakdown stage) {
switch (stage) { switch (stage) {
case VizBreakdown::kSubmitToReceiveCompositorFrame: case VizBreakdown::kSubmitToReceiveCompositorFrame:
...@@ -378,7 +381,9 @@ void CompositorFrameReporter::TerminateReporter() { ...@@ -378,7 +381,9 @@ void CompositorFrameReporter::TerminateReporter() {
break; break;
} }
ReportAllTraceEvents(termination_status_str); ReportCompositorLatencyTraceEvents(termination_status_str);
if (TestReportType(FrameReportType::kNonDroppedFrame))
ReportEventLatencyTraceEvents();
// Only report compositor latency histograms if the frame was produced. // Only report compositor latency histograms if the frame was produced.
if (should_report_metrics_ && report_types_.any()) { if (should_report_metrics_ && report_types_.any()) {
...@@ -510,9 +515,11 @@ void CompositorFrameReporter::ReportCompositorLatencyVizBreakdowns( ...@@ -510,9 +515,11 @@ void CompositorFrameReporter::ReportCompositorLatencyVizBreakdowns(
#endif #endif
break; break;
} }
const base::TimeTicks start_time = viz_breakdown_list_[i]->first;
const base::TimeTicks end_time = viz_breakdown_list_[i]->second;
ReportCompositorLatencyHistogram(frame_sequence_tracker_type, ReportCompositorLatencyHistogram(frame_sequence_tracker_type,
kVizBreakdownInitialIndex + i, kVizBreakdownInitialIndex + i,
*viz_breakdown_list_[i]); end_time - start_time);
} }
} }
...@@ -586,57 +593,43 @@ void CompositorFrameReporter::ReportEventLatencyHistograms() const { ...@@ -586,57 +593,43 @@ void CompositorFrameReporter::ReportEventLatencyHistograms() const {
base::HistogramBase::kUmaTargetedHistogramFlag)); base::HistogramBase::kUmaTargetedHistogramFlag));
} }
const auto trace_id = TRACE_ID_LOCAL(&event_metrics);
TRACE_EVENT_NESTABLE_ASYNC_BEGIN_WITH_TIMESTAMP1(
"cc,input", "EventLatency", trace_id, event_metrics.time_stamp(),
"event", event_metrics.GetTypeName());
// It is possible for an event to arrive in the compositor in the middle of // It is possible for an event to arrive in the compositor in the middle of
// a frame (e.g. the browser received the event *after* renderer received a // a frame (e.g. the browser received the event *after* renderer received a
// begin-impl, and the event reached the compositor before that frame // begin-impl, and the event reached the compositor before that frame
// ended). To handle such cases, find the first stage that happens after the // ended). To handle such cases, find the first stage that happens after the
// event's arrival in the browser. // event's arrival in the browser.
size_t index = 0; auto stage_it =
for (; index < stage_history_.size(); ++index) { std::find_if(stage_history_.begin(), stage_history_.end(),
const auto& stage = stage_history_[index]; [&event_metrics](const StageData& stage) {
if (stage.start_time > event_metrics.time_stamp()) { return stage.start_time > event_metrics.time_stamp();
const char stage_type_name[] = "BrowserToRendererCompositor"; });
DCHECK(stage_it != stage_history_.end());
const base::TimeDelta latency =
stage.start_time - event_metrics.time_stamp(); const base::TimeDelta b2r_latency =
const std::string histogram_name = stage_it->start_time - event_metrics.time_stamp();
base::StrCat({histogram_base_name, ".", stage_type_name}); const std::string b2r_histogram_name =
histogram_base_name + ".BrowserToRendererCompositor";
STATIC_HISTOGRAM_POINTER_GROUP( STATIC_HISTOGRAM_POINTER_GROUP(
histogram_name, histogram_base_index, b2r_histogram_name, histogram_base_index,
kMaxEventLatencyHistogramBaseIndex, kMaxEventLatencyHistogramBaseIndex,
AddTimeMicrosecondsGranularity(latency), AddTimeMicrosecondsGranularity(b2r_latency),
base::Histogram::FactoryGet( base::Histogram::FactoryGet(
histogram_name, kEventLatencyHistogramMin, b2r_histogram_name, kEventLatencyHistogramMin,
kEventLatencyHistogramMax, kEventLatencyHistogramBucketCount, kEventLatencyHistogramMax, kEventLatencyHistogramBucketCount,
base::HistogramBase::kUmaTargetedHistogramFlag)); base::HistogramBase::kUmaTargetedHistogramFlag));
TRACE_EVENT_NESTABLE_ASYNC_BEGIN_WITH_TIMESTAMP0( for (; stage_it != stage_history_.end(); ++stage_it) {
"cc,input", stage_type_name, trace_id, event_metrics.time_stamp());
TRACE_EVENT_NESTABLE_ASYNC_END_WITH_TIMESTAMP0(
"cc,input", stage_type_name, trace_id, stage.start_time);
break;
}
}
for (; index < stage_history_.size(); ++index) {
const auto& stage = stage_history_[index];
// Total latency is calculated since the event timestamp. // Total latency is calculated since the event timestamp.
const base::TimeTicks start_time = const base::TimeTicks start_time =
stage.stage_type == StageType::kTotalLatency stage_it->stage_type == StageType::kTotalLatency
? event_metrics.time_stamp() ? event_metrics.time_stamp()
: stage.start_time; : stage_it->start_time;
const base::TimeDelta latency = stage.end_time - start_time; const base::TimeDelta latency = stage_it->end_time - start_time;
const int stage_type_index = static_cast<int>(stage.stage_type); const int stage_type_index = static_cast<int>(stage_it->stage_type);
ReportEventLatencyHistogram(histogram_base_index, histogram_base_name, ReportEventLatencyHistogram(histogram_base_index, histogram_base_name,
stage_type_index, latency); stage_type_index, latency);
switch (stage.stage_type) { switch (stage_it->stage_type) {
case StageType::kSendBeginMainFrameToCommit: case StageType::kSendBeginMainFrameToCommit:
ReportEventLatencyBlinkBreakdowns(histogram_base_index, ReportEventLatencyBlinkBreakdowns(histogram_base_index,
histogram_base_name); histogram_base_name);
...@@ -648,18 +641,7 @@ void CompositorFrameReporter::ReportEventLatencyHistograms() const { ...@@ -648,18 +641,7 @@ void CompositorFrameReporter::ReportEventLatencyHistograms() const {
default: default:
break; break;
} }
if (stage.stage_type != StageType::kTotalLatency) {
TRACE_EVENT_NESTABLE_ASYNC_BEGIN_WITH_TIMESTAMP0(
"cc,input", GetStageName(stage_type_index), trace_id,
stage.start_time);
TRACE_EVENT_NESTABLE_ASYNC_END_WITH_TIMESTAMP0(
"cc,input", GetStageName(stage_type_index), trace_id,
stage.end_time);
}
} }
TRACE_EVENT_NESTABLE_ASYNC_END_WITH_TIMESTAMP0(
"cc,input", "EventLatency", trace_id, frame_termination_time_);
} }
} }
...@@ -685,9 +667,11 @@ void CompositorFrameReporter::ReportEventLatencyVizBreakdowns( ...@@ -685,9 +667,11 @@ void CompositorFrameReporter::ReportEventLatencyVizBreakdowns(
#endif #endif
break; break;
} }
const base::TimeTicks start_time = viz_breakdown_list_[i]->first;
const base::TimeTicks end_time = viz_breakdown_list_[i]->second;
ReportEventLatencyHistogram(histogram_base_index, histogram_base_name, ReportEventLatencyHistogram(histogram_base_index, histogram_base_name,
kVizBreakdownInitialIndex + i, kVizBreakdownInitialIndex + i,
*viz_breakdown_list_[i]); end_time - start_time);
} }
} }
...@@ -710,32 +694,15 @@ void CompositorFrameReporter::ReportEventLatencyHistogram( ...@@ -710,32 +694,15 @@ void CompositorFrameReporter::ReportEventLatencyHistogram(
base::HistogramBase::kUmaTargetedHistogramFlag)); base::HistogramBase::kUmaTargetedHistogramFlag));
} }
void CompositorFrameReporter::ReportVizBreakdownTrace( void CompositorFrameReporter::ReportCompositorLatencyTraceEvents(
VizBreakdown substage,
const base::TimeTicks start_time,
const base::TimeTicks end_time) const {
// Do not report events with negative time span.
if (end_time < start_time)
return;
const char* stage_name = GetVizBreakdownName(substage);
TRACE_EVENT_NESTABLE_ASYNC_BEGIN_WITH_TIMESTAMP0(
"cc,benchmark", stage_name, TRACE_ID_LOCAL(this), start_time);
TRACE_EVENT_NESTABLE_ASYNC_END_WITH_TIMESTAMP0(
"cc,benchmark", stage_name, TRACE_ID_LOCAL(this), end_time);
}
void CompositorFrameReporter::ReportAllTraceEvents(
const char* termination_status_str) const { const char* termination_status_str) const {
if (stage_history_.empty()) if (stage_history_.empty())
return; return;
const auto trace_id = TRACE_ID_LOCAL(this); const auto trace_id = TRACE_ID_LOCAL(this);
const auto& startstage = stage_history_.front();
TRACE_EVENT_NESTABLE_ASYNC_BEGIN_WITH_TIMESTAMP1( TRACE_EVENT_NESTABLE_ASYNC_BEGIN_WITH_TIMESTAMP1(
"cc,benchmark", "PipelineReporter", trace_id, startstage.start_time, "cc,benchmark", "PipelineReporter", trace_id,
"frame_id", frame_id_.ToString()); stage_history_.front().start_time, "frame_id", frame_id_.ToString());
// The trace-viewer cannot seem to handle a single child-event that has the // The trace-viewer cannot seem to handle a single child-event that has the
// same start/end timestamps as the parent-event. So avoid adding the // same start/end timestamps as the parent-event. So avoid adding the
...@@ -750,39 +717,30 @@ void CompositorFrameReporter::ReportAllTraceEvents( ...@@ -750,39 +717,30 @@ void CompositorFrameReporter::ReportAllTraceEvents(
DCHECK_GE(stage.end_time, stage.start_time); DCHECK_GE(stage.end_time, stage.start_time);
if (stage.start_time == stage.end_time) if (stage.start_time == stage.end_time)
continue; continue;
const char* name = GetStageName(stage_type_index); const char* stage_name = GetStageName(stage_type_index);
TRACE_EVENT_NESTABLE_ASYNC_BEGIN_WITH_TIMESTAMP0( TRACE_EVENT_NESTABLE_ASYNC_BEGIN_WITH_TIMESTAMP0(
"cc,benchmark", name, trace_id, stage.start_time); "cc,benchmark", stage_name, trace_id, stage.start_time);
if (stage.stage_type == if (stage.stage_type ==
StageType::kSubmitCompositorFrameToPresentationCompositorFrame) { StageType::kSubmitCompositorFrameToPresentationCompositorFrame) {
const struct { for (size_t i = 0; i < base::size(viz_breakdown_list_); i++) {
VizBreakdown stage; if (!viz_breakdown_list_[i])
base::TimeTicks start_time;
base::TimeTicks end_time;
} sub_stages[] = {
{VizBreakdown::kSubmitToReceiveCompositorFrame, stage.start_time,
viz_breakdown_.received_compositor_frame_timestamp},
{VizBreakdown::kReceivedCompositorFrameToStartDraw,
viz_breakdown_.received_compositor_frame_timestamp,
viz_breakdown_.draw_start_timestamp},
{VizBreakdown::kStartDrawToSwapStart,
viz_breakdown_.draw_start_timestamp,
viz_breakdown_.swap_timings.swap_start},
{VizBreakdown::kSwapStartToSwapEnd,
viz_breakdown_.swap_timings.swap_start,
viz_breakdown_.swap_timings.swap_end},
{VizBreakdown::kSwapEndToPresentationCompositorFrame,
viz_breakdown_.swap_timings.swap_end,
viz_breakdown_.presentation_feedback.timestamp}};
for (const auto& sub : sub_stages) {
if (sub.start_time.is_null() || sub.end_time.is_null())
break; break;
ReportVizBreakdownTrace(sub.stage, sub.start_time, sub.end_time); const base::TimeTicks start_time = viz_breakdown_list_[i]->first;
const base::TimeTicks end_time = viz_breakdown_list_[i]->second;
// Do not report events with negative time span.
if (start_time > end_time)
continue;
const char* substage_name =
GetVizBreakdownName(static_cast<VizBreakdown>(i));
TRACE_EVENT_NESTABLE_ASYNC_BEGIN_WITH_TIMESTAMP0(
"cc,benchmark", substage_name, trace_id, start_time);
TRACE_EVENT_NESTABLE_ASYNC_END_WITH_TIMESTAMP0(
"cc,benchmark", substage_name, trace_id, end_time);
} }
} }
TRACE_EVENT_NESTABLE_ASYNC_END_WITH_TIMESTAMP0("cc,benchmark", name, TRACE_EVENT_NESTABLE_ASYNC_END_WITH_TIMESTAMP0("cc,benchmark", stage_name,
trace_id, stage.end_time); trace_id, stage.end_time);
} }
} }
...@@ -796,6 +754,70 @@ void CompositorFrameReporter::ReportAllTraceEvents( ...@@ -796,6 +754,70 @@ void CompositorFrameReporter::ReportAllTraceEvents(
"compositor_frame_submission_status", submission_status_str); "compositor_frame_submission_status", submission_status_str);
} }
void CompositorFrameReporter::ReportEventLatencyTraceEvents() const {
for (const EventMetrics& event_metrics : events_metrics_) {
const auto trace_id = TRACE_ID_LOCAL(&event_metrics);
TRACE_EVENT_NESTABLE_ASYNC_BEGIN_WITH_TIMESTAMP1(
"cc,input", "EventLatency", trace_id, event_metrics.time_stamp(),
"event", event_metrics.GetTypeName());
// Find the first stage that happens after the event's arrival in the
// browser.
auto stage_it =
std::find_if(stage_history_.begin(), stage_history_.end(),
[&event_metrics](const StageData& stage) {
return stage.start_time > event_metrics.time_stamp();
});
DCHECK(stage_it != stage_history_.end());
TRACE_EVENT_NESTABLE_ASYNC_BEGIN_WITH_TIMESTAMP0(
"cc,input", "BrowserToRendererCompositor", trace_id,
event_metrics.time_stamp());
TRACE_EVENT_NESTABLE_ASYNC_END_WITH_TIMESTAMP0(
"cc,input", "BrowserToRendererCompositor", trace_id,
stage_it->start_time);
for (; stage_it != stage_history_.end(); ++stage_it) {
const int stage_type_index = static_cast<int>(stage_it->stage_type);
CHECK_LT(stage_type_index, static_cast<int>(StageType::kStageTypeCount));
CHECK_GE(stage_type_index, 0);
if (stage_it->start_time >= frame_termination_time_)
break;
DCHECK_GE(stage_it->end_time, stage_it->start_time);
if (stage_it->start_time == stage_it->end_time)
continue;
const char* stage_name = GetStageName(stage_type_index);
TRACE_EVENT_NESTABLE_ASYNC_BEGIN_WITH_TIMESTAMP0(
"cc,input", stage_name, trace_id, stage_it->start_time);
if (stage_it->stage_type ==
StageType::kSubmitCompositorFrameToPresentationCompositorFrame) {
for (size_t i = 0; i < base::size(viz_breakdown_list_); i++) {
if (!viz_breakdown_list_[i])
break;
const base::TimeTicks start_time = viz_breakdown_list_[i]->first;
const base::TimeTicks end_time = viz_breakdown_list_[i]->second;
// Do not report events with negative time span.
if (start_time > end_time)
continue;
const char* substage_name =
GetVizBreakdownName(static_cast<VizBreakdown>(i));
TRACE_EVENT_NESTABLE_ASYNC_BEGIN_WITH_TIMESTAMP0(
"cc,input", substage_name, trace_id, start_time);
TRACE_EVENT_NESTABLE_ASYNC_END_WITH_TIMESTAMP0(
"cc,input", substage_name, trace_id, end_time);
}
}
TRACE_EVENT_NESTABLE_ASYNC_END_WITH_TIMESTAMP0(
"cc,input", stage_name, trace_id, stage_it->end_time);
}
TRACE_EVENT_NESTABLE_ASYNC_END_WITH_TIMESTAMP0(
"cc,input", "EventLatency", trace_id, frame_termination_time_);
}
}
void CompositorFrameReporter::PopulateBlinkBreakdownList() { void CompositorFrameReporter::PopulateBlinkBreakdownList() {
if (blink_start_time_.is_null()) if (blink_start_time_.is_null())
return; return;
...@@ -839,29 +861,30 @@ void CompositorFrameReporter::PopulateVizBreakdownList() { ...@@ -839,29 +861,30 @@ void CompositorFrameReporter::PopulateVizBreakdownList() {
} }
viz_breakdown_list_[static_cast<int>( viz_breakdown_list_[static_cast<int>(
VizBreakdown::kSubmitToReceiveCompositorFrame)] = VizBreakdown::kSubmitToReceiveCompositorFrame)] =
viz_breakdown_.received_compositor_frame_timestamp - viz_start_time_; std::make_pair(viz_start_time_,
viz_breakdown_.received_compositor_frame_timestamp);
if (viz_breakdown_.draw_start_timestamp.is_null()) if (viz_breakdown_.draw_start_timestamp.is_null())
return; return;
viz_breakdown_list_[static_cast<int>( viz_breakdown_list_[static_cast<int>(
VizBreakdown::kReceivedCompositorFrameToStartDraw)] = VizBreakdown::kReceivedCompositorFrameToStartDraw)] =
viz_breakdown_.draw_start_timestamp - std::make_pair(viz_breakdown_.received_compositor_frame_timestamp,
viz_breakdown_.received_compositor_frame_timestamp; viz_breakdown_.draw_start_timestamp);
if (viz_breakdown_.swap_timings.is_null()) if (viz_breakdown_.swap_timings.is_null())
return; return;
viz_breakdown_list_[static_cast<int>(VizBreakdown::kStartDrawToSwapStart)] = viz_breakdown_list_[static_cast<int>(VizBreakdown::kStartDrawToSwapStart)] =
viz_breakdown_.swap_timings.swap_start - std::make_pair(viz_breakdown_.draw_start_timestamp,
viz_breakdown_.draw_start_timestamp; viz_breakdown_.swap_timings.swap_start);
viz_breakdown_list_[static_cast<int>(VizBreakdown::kSwapStartToSwapEnd)] = viz_breakdown_list_[static_cast<int>(VizBreakdown::kSwapStartToSwapEnd)] =
viz_breakdown_.swap_timings.swap_end - std::make_pair(viz_breakdown_.swap_timings.swap_start,
viz_breakdown_.swap_timings.swap_start; viz_breakdown_.swap_timings.swap_end);
viz_breakdown_list_[static_cast<int>( viz_breakdown_list_[static_cast<int>(
VizBreakdown::kSwapEndToPresentationCompositorFrame)] = VizBreakdown::kSwapEndToPresentationCompositorFrame)] =
viz_breakdown_.presentation_feedback.timestamp - std::make_pair(viz_breakdown_.swap_timings.swap_end,
viz_breakdown_.swap_timings.swap_end; viz_breakdown_.presentation_feedback.timestamp);
} }
base::TimeDelta CompositorFrameReporter::SumOfStageHistory() const { base::TimeDelta CompositorFrameReporter::SumOfStageHistory() const {
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include <bitset> #include <bitset>
#include <memory> #include <memory>
#include <utility>
#include <vector> #include <vector>
#include "base/optional.h" #include "base/optional.h"
...@@ -213,15 +214,9 @@ class CC_EXPORT CompositorFrameReporter { ...@@ -213,15 +214,9 @@ class CC_EXPORT CompositorFrameReporter {
int stage_type_index, int stage_type_index,
base::TimeDelta latency) const; base::TimeDelta latency) const;
// Generate a trace event corresponding to a Viz breakdown under void ReportCompositorLatencyTraceEvents(
// SubmitCompositorFrameToPresentationCompositorFrame stage in const char* termination_status_str) const;
// PipelineReporter. This function only generates trace events and does not void ReportEventLatencyTraceEvents() const;
// report histograms.
void ReportVizBreakdownTrace(VizBreakdown substage,
const base::TimeTicks start_time,
const base::TimeTicks end_time) const;
void ReportAllTraceEvents(const char* termination_status_str) const;
void EnableReportType(FrameReportType report_type) { void EnableReportType(FrameReportType report_type) {
report_types_.set(static_cast<size_t>(report_type)); report_types_.set(static_cast<size_t>(report_type));
...@@ -249,7 +244,7 @@ class CC_EXPORT CompositorFrameReporter { ...@@ -249,7 +244,7 @@ class CC_EXPORT CompositorFrameReporter {
viz::FrameTimingDetails viz_breakdown_; viz::FrameTimingDetails viz_breakdown_;
base::TimeTicks viz_start_time_; base::TimeTicks viz_start_time_;
base::Optional<base::TimeDelta> base::Optional<std::pair<base::TimeTicks, base::TimeTicks>>
viz_breakdown_list_[static_cast<int>(VizBreakdown::kBreakdownCount)]; viz_breakdown_list_[static_cast<int>(VizBreakdown::kBreakdownCount)];
// Stage data is recorded here. On destruction these stages will be reported // Stage data is recorded here. On destruction these stages will be reported
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment