OLD | NEW |
(Empty) | |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "components/latency_tracker/latency_tracker.h" |
| 6 |
| 7 #include "base/metrics/histogram_functions.h" |
| 8 #include "base/metrics/histogram_macros.h" |
| 9 |
| 10 using ui::LatencyInfo; |
| 11 |
| 12 // TODO: SHould we have separate classes with state for browser and GPU |
| 13 // callbacks? Or perhaps stateless? |
| 14 |
| 15 namespace latency_tracker { |
| 16 namespace { |
| 17 |
| 18 // Check valid timing for start and end latency components. |
| 19 #define CONFIRM_VALID_TIMING(start, end) \ |
| 20 DCHECK(!start.first_event_time.is_null()); \ |
| 21 DCHECK(!end.last_event_time.is_null()); \ |
| 22 DCHECK_GE(end.last_event_time, start.first_event_time); |
| 23 |
| 24 // Event latency that is mostly under 1 second. We should only use 100 buckets |
| 25 // when needed. |
| 26 #define UMA_HISTOGRAM_INPUT_LATENCY_HIGH_RESOLUTION_MICROSECONDS(name, start, \ |
| 27 end) \ |
| 28 CONFIRM_VALID_TIMING(start, end) \ |
| 29 base::UmaHistogramCustomCounts( \ |
| 30 name, (end.last_event_time - start.first_event_time).InMicroseconds(), \ |
| 31 1, 1000000, 100); |
| 32 |
| 33 // Long touch/wheel scroll latency component that is mostly under 200ms. |
| 34 #define UMA_HISTOGRAM_SCROLL_LATENCY_LONG_2(name, start, end) \ |
| 35 CONFIRM_VALID_TIMING(start, end) \ |
| 36 base::Histogram::FactoryGet(name, 1000, 200000, 50, \ |
| 37 base::HistogramBase::kUmaTargetedHistogramFlag) \ |
| 38 ->Add((end.last_event_time - start.first_event_time).InMicroseconds()); |
| 39 |
| 40 // Short touch/wheel scroll latency component that is mostly under 50ms. |
| 41 #define UMA_HISTOGRAM_SCROLL_LATENCY_SHORT_2(name, start, end) \ |
| 42 CONFIRM_VALID_TIMING(start, end) \ |
| 43 base::Histogram::FactoryGet(name, 1, 50000, 50, \ |
| 44 base::HistogramBase::kUmaTargetedHistogramFlag) \ |
| 45 ->Add((end.last_event_time - start.first_event_time).InMicroseconds()); |
| 46 |
| 47 std::string LatencySourceEventTypeToInputModalityString( |
| 48 ui::SourceEventType type) { |
| 49 switch (type) { |
| 50 case ui::SourceEventType::WHEEL: |
| 51 return "Wheel"; |
| 52 case ui::SourceEventType::TOUCH: |
| 53 return "Touch"; |
| 54 default: |
| 55 return ""; |
| 56 } |
| 57 } |
| 58 |
| 59 void ComputeScrollLatencyHistograms( |
| 60 const LatencyInfo::LatencyComponent& gpu_swap_begin_component, |
| 61 const LatencyInfo::LatencyComponent& gpu_swap_end_component, |
| 62 const LatencyInfo& latency, |
| 63 bool is_running_navigation_hint_task) { |
| 64 DCHECK(!latency.coalesced()); |
| 65 if (latency.coalesced()) |
| 66 return; |
| 67 |
| 68 DCHECK(!gpu_swap_begin_component.event_time.is_null()); |
| 69 DCHECK(!gpu_swap_end_component.event_time.is_null()); |
| 70 LatencyInfo::LatencyComponent original_component; |
| 71 if (latency.FindLatency( |
| 72 ui::INPUT_EVENT_LATENCY_FIRST_SCROLL_UPDATE_ORIGINAL_COMPONENT, |
| 73 &original_component)) { |
| 74 // This UMA metric tracks the time between the final frame swap for the |
| 75 // first scroll event in a sequence and the original timestamp of that |
| 76 // scroll event's underlying touch event. |
| 77 for (size_t i = 0; i < original_component.event_count; i++) { |
| 78 UMA_HISTOGRAM_INPUT_LATENCY_HIGH_RESOLUTION_MICROSECONDS( |
| 79 "Event.Latency.TouchToFirstScrollUpdateSwapBegin", |
| 80 original_component, gpu_swap_begin_component); |
| 81 } |
| 82 // TODO(horo): IsRunningNavigationHintTask UMAs are only for |
| 83 // SpeculativeLaunchServiceWorker experimentation. So remove this UMA when |
| 84 // the experimentation finished (crbug.com/638827). |
| 85 if (is_running_navigation_hint_task) { |
| 86 for (size_t i = 0; i < original_component.event_count; i++) { |
| 87 UMA_HISTOGRAM_INPUT_LATENCY_HIGH_RESOLUTION_MICROSECONDS( |
| 88 "Event.Latency.TouchToFirstScrollUpdateSwapBegin_" |
| 89 "IsRunningNavigationHintTask", |
| 90 original_component, gpu_swap_begin_component); |
| 91 } |
| 92 } |
| 93 } else if (!latency.FindLatency( |
| 94 ui::INPUT_EVENT_LATENCY_SCROLL_UPDATE_ORIGINAL_COMPONENT, |
| 95 &original_component)) { |
| 96 return; |
| 97 } |
| 98 |
| 99 // This UMA metric tracks the time from when the original touch event is |
| 100 // created to when the scroll gesture results in final frame swap. |
| 101 for (size_t i = 0; i < original_component.event_count; i++) { |
| 102 UMA_HISTOGRAM_INPUT_LATENCY_HIGH_RESOLUTION_MICROSECONDS( |
| 103 "Event.Latency.TouchToScrollUpdateSwapBegin", original_component, |
| 104 gpu_swap_begin_component); |
| 105 } |
| 106 // TODO(horo): IsRunningNavigationHintTask UMAs are only for |
| 107 // SpeculativeLaunchServiceWorker experimentation. So remove this UMA when |
| 108 // the experimentation finished (crbug.com/638827). |
| 109 if (is_running_navigation_hint_task) { |
| 110 for (size_t i = 0; i < original_component.event_count; i++) { |
| 111 UMA_HISTOGRAM_INPUT_LATENCY_HIGH_RESOLUTION_MICROSECONDS( |
| 112 "Event.Latency.TouchToScrollUpdateSwapBegin_" |
| 113 "IsRunningNavigationHintTask", |
| 114 original_component, gpu_swap_begin_component); |
| 115 } |
| 116 } |
| 117 } |
| 118 |
| 119 } // namespace |
| 120 |
| 121 void LatencyTracker::OnGpuSwapBufersCompleted( |
| 122 const LatencyInfo& latency, |
| 123 bool is_running_navigation_hint_task) { |
| 124 LOG(ERROR) << "LatencyTracker::OnGpuSwapBufersCompleted"; |
| 125 int i = 0; |
| 126 for (const auto& lc : latency.latency_components()) { |
| 127 ++i; |
| 128 LOG(ERROR) << "Component " << i << ": " |
| 129 << ui::GetComponentName(lc.first.first); |
| 130 } |
| 131 |
| 132 LatencyInfo::LatencyComponent gpu_swap_end_component; |
| 133 if (!latency.FindLatency( |
| 134 ui::INPUT_EVENT_LATENCY_TERMINATED_FRAME_SWAP_COMPONENT, 0, |
| 135 &gpu_swap_end_component)) { |
| 136 return; |
| 137 } |
| 138 |
| 139 LatencyInfo::LatencyComponent gpu_swap_begin_component; |
| 140 if (!latency.FindLatency(ui::INPUT_EVENT_GPU_SWAP_BUFFER_COMPONENT, 0, |
| 141 &gpu_swap_begin_component)) { |
| 142 return; |
| 143 } |
| 144 |
| 145 LatencyInfo::LatencyComponent tab_switch_component; |
| 146 if (latency.FindLatency(ui::TAB_SHOW_COMPONENT, &tab_switch_component)) { |
| 147 base::TimeDelta delta = |
| 148 gpu_swap_end_component.event_time - tab_switch_component.event_time; |
| 149 for (size_t i = 0; i < tab_switch_component.event_count; i++) { |
| 150 UMA_HISTOGRAM_TIMES("MPArch.RWH_TabSwitchPaintDuration", delta); |
| 151 } |
| 152 } |
| 153 |
| 154 if (!latency.FindLatency(ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT, |
| 155 nullptr)) { |
| 156 return; |
| 157 } |
| 158 |
| 159 ui::SourceEventType source_event_type = latency.source_event_type(); |
| 160 if (source_event_type == ui::SourceEventType::WHEEL || |
| 161 source_event_type == ui::SourceEventType::TOUCH) { |
| 162 ComputeTouchAndWheelScrollLatencyHistograms( |
| 163 gpu_swap_begin_component, |
| 164 gpu_swap_end_component, latency); |
| 165 } |
| 166 |
| 167 // Compute the old scroll update latency metrics. They are exclusively |
| 168 // calculated for touch scrolls, and will be deprecated on M56. |
| 169 // (https://crbug.com/649754) |
| 170 LatencyInfo::LatencyComponent mouse_wheel_scroll_update_component; |
| 171 if (!latency.FindLatency( |
| 172 ui::INPUT_EVENT_LATENCY_GENERATE_SCROLL_UPDATE_FROM_MOUSE_WHEEL, 0, |
| 173 &mouse_wheel_scroll_update_component)) { |
| 174 ComputeScrollLatencyHistograms( |
| 175 gpu_swap_begin_component, gpu_swap_end_component, |
| 176 latency, is_running_navigation_hint_task); |
| 177 } |
| 178 } |
| 179 |
| 180 void LatencyTracker::ReportRapporScrollLatency( |
| 181 const std::string& name, |
| 182 const LatencyInfo::LatencyComponent& start_component, |
| 183 const LatencyInfo::LatencyComponent& end_component) {} |
| 184 |
| 185 void LatencyTracker::ComputeTouchAndWheelScrollLatencyHistograms( |
| 186 const ui::LatencyInfo::LatencyComponent& gpu_swap_begin_component, |
| 187 const ui::LatencyInfo::LatencyComponent& gpu_swap_end_component, |
| 188 const ui::LatencyInfo& latency) { |
| 189 DCHECK(!latency.coalesced()); |
| 190 if (latency.coalesced()) |
| 191 return; |
| 192 |
| 193 LatencyInfo::LatencyComponent original_component; |
| 194 std::string scroll_name = "ScrollUpdate"; |
| 195 |
| 196 const std::string input_modality = |
| 197 LatencySourceEventTypeToInputModalityString(latency.source_event_type()); |
| 198 |
| 199 if (latency.FindLatency( |
| 200 ui::INPUT_EVENT_LATENCY_FIRST_SCROLL_UPDATE_ORIGINAL_COMPONENT, |
| 201 &original_component)) { |
| 202 scroll_name = "ScrollBegin"; |
| 203 // This UMA metric tracks the time between the final frame swap for the |
| 204 // first scroll event in a sequence and the original timestamp of that |
| 205 // scroll event's underlying touch/wheel event. |
| 206 UMA_HISTOGRAM_INPUT_LATENCY_HIGH_RESOLUTION_MICROSECONDS( |
| 207 "Event.Latency.ScrollBegin." + input_modality + |
| 208 ".TimeToScrollUpdateSwapBegin2", |
| 209 original_component, gpu_swap_begin_component); |
| 210 |
| 211 ReportRapporScrollLatency( |
| 212 "Event.Latency.ScrollBegin." + input_modality + |
| 213 ".TimeToScrollUpdateSwapBegin2", |
| 214 original_component, gpu_swap_begin_component); |
| 215 |
| 216 // TODO(lanwei): Will remove them when M56 is stable, see |
| 217 // https://crbug.com/669618. |
| 218 UMA_HISTOGRAM_INPUT_LATENCY_HIGH_RESOLUTION_MICROSECONDS( |
| 219 "Event.Latency.ScrollUpdate." + input_modality + |
| 220 ".TimeToFirstScrollUpdateSwapBegin2", |
| 221 original_component, gpu_swap_begin_component); |
| 222 } else if (latency.FindLatency( |
| 223 ui::INPUT_EVENT_LATENCY_SCROLL_UPDATE_ORIGINAL_COMPONENT, |
| 224 &original_component)) { |
| 225 // This UMA metric tracks the time from when the original touch event is |
| 226 // created to when the scroll gesture results in final frame swap. |
| 227 // First scroll events are excluded from this metric. |
| 228 if (input_modality == "Touch") { |
| 229 UMA_HISTOGRAM_INPUT_LATENCY_HIGH_RESOLUTION_MICROSECONDS( |
| 230 "Event.Latency.ScrollUpdate.Touch.TimeToScrollUpdateSwapBegin2", |
| 231 original_component, gpu_swap_begin_component); |
| 232 |
| 233 ReportRapporScrollLatency( |
| 234 "Event.Latency.ScrollUpdate.Touch.TimeToScrollUpdateSwapBegin2", |
| 235 original_component, gpu_swap_begin_component); |
| 236 } |
| 237 } else { |
| 238 // No original component found. |
| 239 return; |
| 240 } |
| 241 |
| 242 LatencyInfo::LatencyComponent rendering_scheduled_component; |
| 243 bool rendering_scheduled_on_main = latency.FindLatency( |
| 244 ui::INPUT_EVENT_LATENCY_RENDERING_SCHEDULED_MAIN_COMPONENT, 0, |
| 245 &rendering_scheduled_component); |
| 246 if (!rendering_scheduled_on_main) { |
| 247 if (!latency.FindLatency( |
| 248 ui::INPUT_EVENT_LATENCY_RENDERING_SCHEDULED_IMPL_COMPONENT, 0, |
| 249 &rendering_scheduled_component)) |
| 250 return; |
| 251 } |
| 252 |
| 253 const std::string thread_name = rendering_scheduled_on_main ? "Main" : "Impl"; |
| 254 |
| 255 UMA_HISTOGRAM_SCROLL_LATENCY_LONG_2( |
| 256 "Event.Latency." + scroll_name + "." + input_modality + |
| 257 ".TimeToHandled2_" + thread_name, |
| 258 original_component, rendering_scheduled_component); |
| 259 |
| 260 LatencyInfo::LatencyComponent renderer_swap_component; |
| 261 if (!latency.FindLatency(ui::INPUT_EVENT_LATENCY_RENDERER_SWAP_COMPONENT, 0, |
| 262 &renderer_swap_component)) |
| 263 return; |
| 264 |
| 265 UMA_HISTOGRAM_SCROLL_LATENCY_LONG_2( |
| 266 "Event.Latency." + scroll_name + "." + input_modality + |
| 267 ".HandledToRendererSwap2_" + thread_name, |
| 268 rendering_scheduled_component, renderer_swap_component); |
| 269 |
| 270 LatencyInfo::LatencyComponent browser_received_swap_component; |
| 271 if (!latency.FindLatency( |
| 272 ui::INPUT_EVENT_BROWSER_RECEIVED_RENDERER_SWAP_COMPONENT, 0, |
| 273 &browser_received_swap_component)) |
| 274 return; |
| 275 |
| 276 UMA_HISTOGRAM_SCROLL_LATENCY_SHORT_2( |
| 277 "Event.Latency." + scroll_name + "." + input_modality + |
| 278 ".RendererSwapToBrowserNotified2", |
| 279 renderer_swap_component, browser_received_swap_component); |
| 280 |
| 281 UMA_HISTOGRAM_SCROLL_LATENCY_LONG_2( |
| 282 "Event.Latency." + scroll_name + "." + input_modality + |
| 283 ".BrowserNotifiedToBeforeGpuSwap2", |
| 284 browser_received_swap_component, gpu_swap_begin_component); |
| 285 |
| 286 UMA_HISTOGRAM_SCROLL_LATENCY_SHORT_2( |
| 287 "Event.Latency." + scroll_name + "." + input_modality + ".GpuSwap2", |
| 288 gpu_swap_begin_component, gpu_swap_end_component); |
| 289 } |
| 290 } // namespace content |
OLD | NEW |