Commit d8d52440 authored by Mohsen Izadi's avatar Mohsen Izadi Committed by Commit Bot

Add total latency up to gpu-swap-end for scroll events

Existing LatencyInfo-based event latency metrics measure the time
between event creation timestamp and gpu-swap-end. To be able to verify
new event latency metrics against them, we need add similar metrics for
new EventLatency metrics. This is only added for scroll events as
LatencyInfo-based metrics only exist for scroll events.

Bug: 1057193
Change-Id: I73169330a4ffb0e4b5fd9506960a5737624867bc
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2129215Reviewed-by: default avatarSadrul Chowdhury <sadrul@chromium.org>
Commit-Queue: Mohsen Izadi <mohsen@chromium.org>
Cr-Commit-Position: refs/heads/master@{#754948}
parent 3ae250ed
...@@ -188,12 +188,12 @@ std::string GetCompositorLatencyHistogramName( ...@@ -188,12 +188,12 @@ std::string GetCompositorLatencyHistogramName(
GetStageName(stage_type_index)}); GetStageName(stage_type_index)});
} }
std::string GetEventLatencyHistogramName(const EventMetrics& event_metrics) { std::string GetEventLatencyHistogramBaseName(
const EventMetrics& event_metrics) {
const bool is_scroll = event_metrics.scroll_input_type().has_value(); const bool is_scroll = event_metrics.scroll_input_type().has_value();
return base::StrCat({"EventLatency.", event_metrics.GetTypeName(), return base::StrCat(
is_scroll ? "." : nullptr, {"EventLatency.", event_metrics.GetTypeName(), is_scroll ? "." : nullptr,
is_scroll ? event_metrics.GetScrollTypeName() : nullptr, is_scroll ? event_metrics.GetScrollTypeName() : nullptr});
".TotalLatency"});
} }
} // namespace } // namespace
...@@ -529,29 +529,51 @@ void CompositorFrameReporter::ReportCompositorLatencyHistogram( ...@@ -529,29 +529,51 @@ void CompositorFrameReporter::ReportCompositorLatencyHistogram(
void CompositorFrameReporter::ReportEventLatencyHistograms() const { void CompositorFrameReporter::ReportEventLatencyHistograms() const {
for (const EventMetrics& event_metrics : events_metrics_) { for (const EventMetrics& event_metrics : events_metrics_) {
base::TimeDelta total_latency = const std::string histogram_base_name =
frame_termination_time_ - event_metrics.time_stamp(); GetEventLatencyHistogramBaseName(event_metrics);
const auto trace_id = TRACE_ID_LOCAL(&event_metrics); const int event_type_index = static_cast<int>(event_metrics.type());
TRACE_EVENT_NESTABLE_ASYNC_BEGIN_WITH_TIMESTAMP1(
"cc,input", "EventLatency", trace_id, event_metrics.time_stamp(),
"event", event_metrics.GetTypeName());
const int type_index = static_cast<int>(event_metrics.type());
const int scroll_type_index = const int scroll_type_index =
event_metrics.scroll_input_type() event_metrics.scroll_input_type()
? static_cast<int>(*event_metrics.scroll_input_type()) ? static_cast<int>(*event_metrics.scroll_input_type())
: 0; : 0;
const int histogram_index = const int histogram_index =
type_index * kEventLatencyScrollTypeCount + scroll_type_index; event_type_index * kEventLatencyScrollTypeCount + scroll_type_index;
// For scroll events, report total latency up to gpu-swap-end. This is
// useful in comparing new EventLatency metrics with LatencyInfo-based
// scroll event latency metrics.
if (event_metrics.scroll_input_type() &&
!viz_breakdown_.swap_timings.is_null()) {
const base::TimeDelta swap_end_latency =
viz_breakdown_.swap_timings.swap_end - event_metrics.time_stamp();
const std::string swap_end_histogram_name =
histogram_base_name + ".TotalLatencyToSwapEnd";
STATIC_HISTOGRAM_POINTER_GROUP(
swap_end_histogram_name, histogram_index,
kMaxEventLatencyHistogramIndex,
AddTimeMicrosecondsGranularity(swap_end_latency),
base::Histogram::FactoryGet(
swap_end_histogram_name, kEventLatencyHistogramMin,
kEventLatencyHistogramMax, kEventLatencyHistogramBucketCount,
base::HistogramBase::kUmaTargetedHistogramFlag));
}
base::TimeDelta total_latency =
frame_termination_time_ - event_metrics.time_stamp();
const std::string histogram_name = histogram_base_name + ".TotalLatency";
STATIC_HISTOGRAM_POINTER_GROUP( STATIC_HISTOGRAM_POINTER_GROUP(
GetEventLatencyHistogramName(event_metrics), histogram_index, histogram_name, histogram_index, kMaxEventLatencyHistogramIndex,
kMaxEventLatencyHistogramIndex,
AddTimeMicrosecondsGranularity(total_latency), AddTimeMicrosecondsGranularity(total_latency),
base::Histogram::FactoryGet( base::Histogram::FactoryGet(
GetEventLatencyHistogramName(event_metrics), histogram_name, kEventLatencyHistogramMin,
kEventLatencyHistogramMin, kEventLatencyHistogramMax, kEventLatencyHistogramMax, kEventLatencyHistogramBucketCount,
kEventLatencyHistogramBucketCount,
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());
// Report the breakdowns. // Report the breakdowns.
// 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
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#include "cc/input/scroll_input_type.h" #include "cc/input/scroll_input_type.h"
#include "cc/metrics/compositor_frame_reporting_controller.h" #include "cc/metrics/compositor_frame_reporting_controller.h"
#include "cc/metrics/event_metrics.h" #include "cc/metrics/event_metrics.h"
#include "components/viz/common/frame_timing_details.h"
#include "testing/gmock/include/gmock/gmock.h" #include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
...@@ -36,14 +37,31 @@ class CompositorFrameReporterTest : public testing::Test { ...@@ -36,14 +37,31 @@ class CompositorFrameReporterTest : public testing::Test {
AdvanceNowByMs(1); AdvanceNowByMs(1);
} }
protected:
void AdvanceNowByMs(int advance_ms) { void AdvanceNowByMs(int advance_ms) {
now_ += base::TimeDelta::FromMicroseconds(advance_ms); now_ += base::TimeDelta::FromMicroseconds(advance_ms);
} }
base::TimeTicks Now() { return now_; } base::TimeTicks Now() { return now_; }
protected: viz::FrameTimingDetails BuildFrameTimingDetails() {
viz::FrameTimingDetails frame_timing_details;
AdvanceNowByMs(1);
frame_timing_details.received_compositor_frame_timestamp = Now();
AdvanceNowByMs(1);
frame_timing_details.draw_start_timestamp = Now();
AdvanceNowByMs(1);
frame_timing_details.swap_timings.swap_start = Now();
AdvanceNowByMs(1);
frame_timing_details.swap_timings.swap_end = Now();
AdvanceNowByMs(1);
frame_timing_details.presentation_feedback.timestamp = Now();
return frame_timing_details;
}
std::unique_ptr<CompositorFrameReporter> pipeline_reporter_; std::unique_ptr<CompositorFrameReporter> pipeline_reporter_;
private:
base::TimeTicks now_; base::TimeTicks now_;
}; };
...@@ -270,22 +288,40 @@ TEST_F(CompositorFrameReporterTest, ...@@ -270,22 +288,40 @@ TEST_F(CompositorFrameReporterTest,
pipeline_reporter_->SetEventsMetrics(std::move(events_metrics)); pipeline_reporter_->SetEventsMetrics(std::move(events_metrics));
AdvanceNowByMs(3); AdvanceNowByMs(3);
const base::TimeTicks presentation_time = Now(); viz::FrameTimingDetails frame_timing_details = BuildFrameTimingDetails();
pipeline_reporter_->SetVizBreakdown(frame_timing_details);
pipeline_reporter_->TerminateFrame( pipeline_reporter_->TerminateFrame(
CompositorFrameReporter::FrameTerminationStatus::kPresentedFrame, CompositorFrameReporter::FrameTerminationStatus::kPresentedFrame,
presentation_time); frame_timing_details.presentation_feedback.timestamp);
pipeline_reporter_ = nullptr; pipeline_reporter_ = nullptr;
const int latency_ms = (presentation_time - event_time).InMicroseconds(); const int total_latency_ms =
(frame_timing_details.presentation_feedback.timestamp - event_time)
.InMicroseconds();
const int swap_end_latency_ms =
(frame_timing_details.swap_timings.swap_end - event_time)
.InMicroseconds();
histogram_tester.ExpectTotalCount( histogram_tester.ExpectTotalCount(
"EventLatency.GestureScrollBegin.Wheel.TotalLatency", 1); "EventLatency.GestureScrollBegin.Wheel.TotalLatency", 1);
histogram_tester.ExpectTotalCount(
"EventLatency.GestureScrollBegin.Wheel.TotalLatencyToSwapEnd", 1);
histogram_tester.ExpectTotalCount( histogram_tester.ExpectTotalCount(
"EventLatency.GestureScrollUpdate.Wheel.TotalLatency", 2); "EventLatency.GestureScrollUpdate.Wheel.TotalLatency", 2);
histogram_tester.ExpectTotalCount(
"EventLatency.GestureScrollUpdate.Wheel.TotalLatencyToSwapEnd", 2);
histogram_tester.ExpectBucketCount(
"EventLatency.GestureScrollBegin.Wheel.TotalLatency", total_latency_ms,
1);
histogram_tester.ExpectBucketCount(
"EventLatency.GestureScrollBegin.Wheel.TotalLatencyToSwapEnd",
swap_end_latency_ms, 1);
histogram_tester.ExpectBucketCount( histogram_tester.ExpectBucketCount(
"EventLatency.GestureScrollBegin.Wheel.TotalLatency", latency_ms, 1); "EventLatency.GestureScrollUpdate.Wheel.TotalLatency", total_latency_ms,
2);
histogram_tester.ExpectBucketCount( histogram_tester.ExpectBucketCount(
"EventLatency.GestureScrollUpdate.Wheel.TotalLatency", latency_ms, 2); "EventLatency.GestureScrollUpdate.Wheel.TotalLatencyToSwapEnd",
swap_end_latency_ms, 2);
} }
// Tests that when the frame is not presented to the user, event latency metrics // Tests that when the frame is not presented to the user, event latency metrics
......
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