| Index: ui/latency/latency_tracker.cc
|
| diff --git a/ui/latency/latency_tracker.cc b/ui/latency/latency_tracker.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..25d15fe9c98a5970e8c5e0cbe11dbc7f3fa6707f
|
| --- /dev/null
|
| +++ b/ui/latency/latency_tracker.cc
|
| @@ -0,0 +1,223 @@
|
| +// Copyright 2017 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.
|
| +
|
| +#include "ui/latency/latency_tracker.h"
|
| +
|
| +#include "base/metrics/histogram_functions.h"
|
| +#include "base/metrics/histogram_macros.h"
|
| +#include "ui/latency/latency_histogram_macros.h"
|
| +
|
| +namespace ui {
|
| +namespace {
|
| +
|
| +std::string LatencySourceEventTypeToInputModalityString(
|
| + ui::SourceEventType type) {
|
| + switch (type) {
|
| + case ui::SourceEventType::WHEEL:
|
| + return "Wheel";
|
| + case ui::SourceEventType::TOUCH:
|
| + return "Touch";
|
| + default:
|
| + return "";
|
| + }
|
| +}
|
| +
|
| +void ComputeScrollLatencyHistograms(
|
| + const LatencyInfo::LatencyComponent& gpu_swap_begin_component,
|
| + const LatencyInfo::LatencyComponent& gpu_swap_end_component,
|
| + const LatencyInfo& latency) {
|
| + DCHECK(!latency.coalesced());
|
| + if (latency.coalesced())
|
| + return;
|
| +
|
| + DCHECK(!gpu_swap_begin_component.event_time.is_null());
|
| + DCHECK(!gpu_swap_end_component.event_time.is_null());
|
| + LatencyInfo::LatencyComponent original_component;
|
| + if (latency.FindLatency(
|
| + ui::INPUT_EVENT_LATENCY_FIRST_SCROLL_UPDATE_ORIGINAL_COMPONENT,
|
| + &original_component)) {
|
| + // This UMA metric tracks the time between the final frame swap for the
|
| + // first scroll event in a sequence and the original timestamp of that
|
| + // scroll event's underlying touch event.
|
| + for (size_t i = 0; i < original_component.event_count; i++) {
|
| + UMA_HISTOGRAM_INPUT_LATENCY_HIGH_RESOLUTION_MICROSECONDS(
|
| + "Event.Latency.TouchToFirstScrollUpdateSwapBegin", original_component,
|
| + gpu_swap_begin_component);
|
| + }
|
| + } else if (!latency.FindLatency(
|
| + ui::INPUT_EVENT_LATENCY_SCROLL_UPDATE_ORIGINAL_COMPONENT,
|
| + &original_component)) {
|
| + return;
|
| + }
|
| +
|
| + // This UMA metric tracks the time from when the original touch event is
|
| + // created to when the scroll gesture results in final frame swap.
|
| + for (size_t i = 0; i < original_component.event_count; i++) {
|
| + UMA_HISTOGRAM_INPUT_LATENCY_HIGH_RESOLUTION_MICROSECONDS(
|
| + "Event.Latency.TouchToScrollUpdateSwapBegin", original_component,
|
| + gpu_swap_begin_component);
|
| + }
|
| +}
|
| +
|
| +} // namespace
|
| +
|
| +void LatencyTracker::ReportRapporScrollLatency(
|
| + const std::string& name,
|
| + const LatencyInfo::LatencyComponent& start_component,
|
| + const LatencyInfo::LatencyComponent& end_component) {}
|
| +
|
| +void LatencyTracker::ComputeTouchAndWheelScrollLatencyHistograms(
|
| + const ui::LatencyInfo::LatencyComponent& gpu_swap_begin_component,
|
| + const ui::LatencyInfo::LatencyComponent& gpu_swap_end_component,
|
| + const ui::LatencyInfo& latency) {
|
| + DCHECK(!latency.coalesced());
|
| + if (latency.coalesced())
|
| + return;
|
| +
|
| + LatencyInfo::LatencyComponent original_component;
|
| + std::string scroll_name = "ScrollUpdate";
|
| +
|
| + const std::string input_modality =
|
| + LatencySourceEventTypeToInputModalityString(latency.source_event_type());
|
| +
|
| + if (latency.FindLatency(
|
| + ui::INPUT_EVENT_LATENCY_FIRST_SCROLL_UPDATE_ORIGINAL_COMPONENT,
|
| + &original_component)) {
|
| + scroll_name = "ScrollBegin";
|
| + // This UMA metric tracks the time between the final frame swap for the
|
| + // first scroll event in a sequence and the original timestamp of that
|
| + // scroll event's underlying touch/wheel event.
|
| + UMA_HISTOGRAM_INPUT_LATENCY_HIGH_RESOLUTION_MICROSECONDS(
|
| + "Event.Latency.ScrollBegin." + input_modality +
|
| + ".TimeToScrollUpdateSwapBegin2",
|
| + original_component, gpu_swap_begin_component);
|
| +
|
| + ReportRapporScrollLatency("Event.Latency.ScrollBegin." + input_modality +
|
| + ".TimeToScrollUpdateSwapBegin2",
|
| + original_component, gpu_swap_begin_component);
|
| +
|
| + // TODO(lanwei): Will remove them when M56 is stable, see
|
| + // https://crbug.com/669618.
|
| + UMA_HISTOGRAM_INPUT_LATENCY_HIGH_RESOLUTION_MICROSECONDS(
|
| + "Event.Latency.ScrollUpdate." + input_modality +
|
| + ".TimeToFirstScrollUpdateSwapBegin2",
|
| + original_component, gpu_swap_begin_component);
|
| + } else if (latency.FindLatency(
|
| + ui::INPUT_EVENT_LATENCY_SCROLL_UPDATE_ORIGINAL_COMPONENT,
|
| + &original_component)) {
|
| + // This UMA metric tracks the time from when the original touch event is
|
| + // created to when the scroll gesture results in final frame swap.
|
| + // First scroll events are excluded from this metric.
|
| + if (input_modality == "Touch") {
|
| + UMA_HISTOGRAM_INPUT_LATENCY_HIGH_RESOLUTION_MICROSECONDS(
|
| + "Event.Latency.ScrollUpdate.Touch.TimeToScrollUpdateSwapBegin2",
|
| + original_component, gpu_swap_begin_component);
|
| +
|
| + ReportRapporScrollLatency(
|
| + "Event.Latency.ScrollUpdate.Touch.TimeToScrollUpdateSwapBegin2",
|
| + original_component, gpu_swap_begin_component);
|
| + }
|
| + } else {
|
| + // No original component found.
|
| + return;
|
| + }
|
| +
|
| + LatencyInfo::LatencyComponent rendering_scheduled_component;
|
| + bool rendering_scheduled_on_main = latency.FindLatency(
|
| + ui::INPUT_EVENT_LATENCY_RENDERING_SCHEDULED_MAIN_COMPONENT, 0,
|
| + &rendering_scheduled_component);
|
| + if (!rendering_scheduled_on_main) {
|
| + if (!latency.FindLatency(
|
| + ui::INPUT_EVENT_LATENCY_RENDERING_SCHEDULED_IMPL_COMPONENT, 0,
|
| + &rendering_scheduled_component))
|
| + return;
|
| + }
|
| +
|
| + const std::string thread_name = rendering_scheduled_on_main ? "Main" : "Impl";
|
| +
|
| + UMA_HISTOGRAM_SCROLL_LATENCY_LONG_2(
|
| + "Event.Latency." + scroll_name + "." + input_modality +
|
| + ".TimeToHandled2_" + thread_name,
|
| + original_component, rendering_scheduled_component);
|
| +
|
| + LatencyInfo::LatencyComponent renderer_swap_component;
|
| + if (!latency.FindLatency(ui::INPUT_EVENT_LATENCY_RENDERER_SWAP_COMPONENT, 0,
|
| + &renderer_swap_component))
|
| + return;
|
| +
|
| + UMA_HISTOGRAM_SCROLL_LATENCY_LONG_2(
|
| + "Event.Latency." + scroll_name + "." + input_modality +
|
| + ".HandledToRendererSwap2_" + thread_name,
|
| + rendering_scheduled_component, renderer_swap_component);
|
| +
|
| + LatencyInfo::LatencyComponent browser_received_swap_component;
|
| + if (!latency.FindLatency(ui::DISPLAY_COMPOSITOR_RECEIVED_FRAME_COMPONENT, 0,
|
| + &browser_received_swap_component))
|
| + return;
|
| +
|
| + UMA_HISTOGRAM_SCROLL_LATENCY_SHORT_2(
|
| + "Event.Latency." + scroll_name + "." + input_modality +
|
| + ".RendererSwapToBrowserNotified2",
|
| + renderer_swap_component, browser_received_swap_component);
|
| +
|
| + UMA_HISTOGRAM_SCROLL_LATENCY_LONG_2(
|
| + "Event.Latency." + scroll_name + "." + input_modality +
|
| + ".BrowserNotifiedToBeforeGpuSwap2",
|
| + browser_received_swap_component, gpu_swap_begin_component);
|
| +
|
| + UMA_HISTOGRAM_SCROLL_LATENCY_SHORT_2(
|
| + "Event.Latency." + scroll_name + "." + input_modality + ".GpuSwap2",
|
| + gpu_swap_begin_component, gpu_swap_end_component);
|
| +}
|
| +
|
| +// TODO(mfomitchev): Move the method up. It's here temporarily for ease of
|
| +// review.
|
| +void LatencyTracker::OnGpuSwapBuffersCompleted(const LatencyInfo& latency) {
|
| + LatencyInfo::LatencyComponent gpu_swap_end_component;
|
| + if (!latency.FindLatency(
|
| + ui::INPUT_EVENT_LATENCY_TERMINATED_FRAME_SWAP_COMPONENT, 0,
|
| + &gpu_swap_end_component)) {
|
| + return;
|
| + }
|
| +
|
| + LatencyInfo::LatencyComponent gpu_swap_begin_component;
|
| + if (!latency.FindLatency(ui::INPUT_EVENT_GPU_SWAP_BUFFER_COMPONENT, 0,
|
| + &gpu_swap_begin_component)) {
|
| + return;
|
| + }
|
| +
|
| + LatencyInfo::LatencyComponent tab_switch_component;
|
| + if (latency.FindLatency(ui::TAB_SHOW_COMPONENT, &tab_switch_component)) {
|
| + base::TimeDelta delta =
|
| + gpu_swap_end_component.event_time - tab_switch_component.event_time;
|
| + for (size_t i = 0; i < tab_switch_component.event_count; i++) {
|
| + UMA_HISTOGRAM_TIMES("MPArch.RWH_TabSwitchPaintDuration", delta);
|
| + }
|
| + }
|
| +
|
| + if (!latency.FindLatency(ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT,
|
| + nullptr)) {
|
| + return;
|
| + }
|
| +
|
| + ui::SourceEventType source_event_type = latency.source_event_type();
|
| + if (source_event_type == ui::SourceEventType::WHEEL ||
|
| + source_event_type == ui::SourceEventType::TOUCH) {
|
| + ComputeTouchAndWheelScrollLatencyHistograms(
|
| + gpu_swap_begin_component, gpu_swap_end_component, latency);
|
| + }
|
| +
|
| + // Compute the old scroll update latency metrics. They are exclusively
|
| + // calculated for touch scrolls, and will be deprecated on M56.
|
| + // (https://crbug.com/649754)
|
| + LatencyInfo::LatencyComponent mouse_wheel_scroll_update_component;
|
| + if (!latency.FindLatency(
|
| + ui::INPUT_EVENT_LATENCY_GENERATE_SCROLL_UPDATE_FROM_MOUSE_WHEEL, 0,
|
| + &mouse_wheel_scroll_update_component)) {
|
| + ComputeScrollLatencyHistograms(gpu_swap_begin_component,
|
| + gpu_swap_end_component, latency);
|
| + }
|
| +}
|
| +
|
| +} // namespace ui
|
|
|