Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "content/browser/renderer_host/input/render_widget_host_latency_tracker .h" | 5 #include "content/browser/renderer_host/input/render_widget_host_latency_tracker .h" |
| 6 | 6 |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 | 8 |
| 9 #include "base/logging.h" | 9 #include "base/logging.h" |
| 10 #include "base/metrics/histogram.h" | 10 #include "base/metrics/histogram.h" |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 68 latency, device_scale_factor); | 68 latency, device_scale_factor); |
| 69 } else if (WebInputEvent::isTouchEventType(event.type)) { | 69 } else if (WebInputEvent::isTouchEventType(event.type)) { |
| 70 UpdateLatencyCoordinatesImpl(static_cast<const WebTouchEvent&>(event), | 70 UpdateLatencyCoordinatesImpl(static_cast<const WebTouchEvent&>(event), |
| 71 latency, device_scale_factor); | 71 latency, device_scale_factor); |
| 72 } else if (event.type == WebInputEvent::MouseWheel) { | 72 } else if (event.type == WebInputEvent::MouseWheel) { |
| 73 UpdateLatencyCoordinatesImpl(static_cast<const WebMouseWheelEvent&>(event), | 73 UpdateLatencyCoordinatesImpl(static_cast<const WebMouseWheelEvent&>(event), |
| 74 latency, device_scale_factor); | 74 latency, device_scale_factor); |
| 75 } | 75 } |
| 76 } | 76 } |
| 77 | 77 |
| 78 void ComputeInputLatencyHistograms(WebInputEvent::Type type, | |
| 79 int64_t latency_component_id, | |
| 80 const LatencyInfo& latency) { | |
| 81 if (latency.coalesced()) | |
| 82 return; | |
| 83 | |
| 84 LatencyInfo::LatencyComponent rwh_component; | |
| 85 if (!latency.FindLatency(ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT, | |
| 86 latency_component_id, &rwh_component)) { | |
| 87 return; | |
| 88 } | |
| 89 DCHECK_EQ(rwh_component.event_count, 1u); | |
| 90 | |
| 91 LatencyInfo::LatencyComponent ui_component; | |
| 92 if (latency.FindLatency(ui::INPUT_EVENT_LATENCY_UI_COMPONENT, 0, | |
| 93 &ui_component)) { | |
| 94 DCHECK_EQ(ui_component.event_count, 1u); | |
| 95 base::TimeDelta ui_delta = | |
| 96 rwh_component.event_time - ui_component.event_time; | |
| 97 switch (type) { | |
| 98 case blink::WebInputEvent::MouseWheel: | |
| 99 UMA_HISTOGRAM_CUSTOM_COUNTS( | |
| 100 "Event.Latency.Browser.WheelUI", | |
| 101 ui_delta.InMicroseconds(), 1, 20000, 100); | |
| 102 break; | |
| 103 case blink::WebInputEvent::TouchTypeFirst: | |
| 104 UMA_HISTOGRAM_CUSTOM_COUNTS( | |
| 105 "Event.Latency.Browser.TouchUI", | |
| 106 ui_delta.InMicroseconds(), 1, 20000, 100); | |
| 107 break; | |
| 108 default: | |
| 109 NOTREACHED(); | |
| 110 break; | |
| 111 } | |
| 112 } | |
| 113 | |
| 114 LatencyInfo::LatencyComponent acked_component; | |
| 115 if (latency.FindLatency(ui::INPUT_EVENT_LATENCY_ACK_RWH_COMPONENT, 0, | |
| 116 &acked_component)) { | |
| 117 DCHECK_EQ(acked_component.event_count, 1u); | |
| 118 base::TimeDelta acked_delta = | |
| 119 acked_component.event_time - rwh_component.event_time; | |
| 120 switch (type) { | |
| 121 case blink::WebInputEvent::MouseWheel: | |
| 122 UMA_HISTOGRAM_CUSTOM_COUNTS( | |
| 123 "Event.Latency.Browser.WheelAcked", | |
| 124 acked_delta.InMicroseconds(), 1, 1000000, 100); | |
| 125 break; | |
| 126 case blink::WebInputEvent::TouchTypeFirst: | |
| 127 UMA_HISTOGRAM_CUSTOM_COUNTS( | |
| 128 "Event.Latency.Browser.TouchAcked", | |
| 129 acked_delta.InMicroseconds(), 1, 1000000, 100); | |
| 130 break; | |
| 131 default: | |
| 132 NOTREACHED(); | |
| 133 break; | |
| 134 } | |
| 135 } | |
| 136 } | |
| 137 | |
| 138 // Touch to scroll latency that is mostly under 1 second. | 78 // Touch to scroll latency that is mostly under 1 second. |
| 139 #define UMA_HISTOGRAM_TOUCH_TO_SCROLL_LATENCY(name, start, end) \ | 79 #define UMA_HISTOGRAM_TOUCH_TO_SCROLL_LATENCY(name, start, end) \ |
| 140 UMA_HISTOGRAM_CUSTOM_COUNTS( \ | 80 UMA_HISTOGRAM_CUSTOM_COUNTS( \ |
| 141 name, (end.event_time - start.event_time).InMicroseconds(), 1, 1000000, \ | 81 name, (end.event_time - start.event_time).InMicroseconds(), 1, 1000000, \ |
| 142 100) | 82 100) |
| 143 | 83 |
| 144 // Long scroll latency component that is mostly under 200ms. | 84 // Long scroll latency component that is mostly under 200ms. |
| 145 #define UMA_HISTOGRAM_SCROLL_LATENCY_LONG(name, start, end) \ | 85 #define UMA_HISTOGRAM_SCROLL_LATENCY_LONG(name, start, end) \ |
| 146 UMA_HISTOGRAM_CUSTOM_COUNTS( \ | 86 UMA_HISTOGRAM_CUSTOM_COUNTS( \ |
| 147 name, \ | 87 name, \ |
| (...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 280 new_components_value[i].event_count); | 220 new_components_value[i].event_count); |
| 281 } | 221 } |
| 282 } | 222 } |
| 283 | 223 |
| 284 } // namespace | 224 } // namespace |
| 285 | 225 |
| 286 RenderWidgetHostLatencyTracker::RenderWidgetHostLatencyTracker() | 226 RenderWidgetHostLatencyTracker::RenderWidgetHostLatencyTracker() |
| 287 : last_event_id_(0), | 227 : last_event_id_(0), |
| 288 latency_component_id_(0), | 228 latency_component_id_(0), |
| 289 device_scale_factor_(1), | 229 device_scale_factor_(1), |
| 290 has_seen_first_gesture_scroll_update_(false) { | 230 has_seen_first_gesture_scroll_update_(false), |
| 291 } | 231 multi_finger_gesture_(false), |
| 232 touch_start_default_prevented_(false) {} | |
| 292 | 233 |
| 293 RenderWidgetHostLatencyTracker::~RenderWidgetHostLatencyTracker() { | 234 RenderWidgetHostLatencyTracker::~RenderWidgetHostLatencyTracker() {} |
| 294 } | |
| 295 | 235 |
| 296 void RenderWidgetHostLatencyTracker::Initialize(int routing_id, | 236 void RenderWidgetHostLatencyTracker::Initialize(int routing_id, |
| 297 int process_id) { | 237 int process_id) { |
| 298 DCHECK_EQ(0, last_event_id_); | 238 DCHECK_EQ(0, last_event_id_); |
| 299 DCHECK_EQ(0, latency_component_id_); | 239 DCHECK_EQ(0, latency_component_id_); |
| 300 last_event_id_ = static_cast<int64_t>(process_id) << 32; | 240 last_event_id_ = static_cast<int64_t>(process_id) << 32; |
| 301 latency_component_id_ = routing_id | last_event_id_; | 241 latency_component_id_ = routing_id | last_event_id_; |
| 302 } | 242 } |
| 303 | 243 |
| 244 void RenderWidgetHostLatencyTracker::ComputeInputLatencyHistograms( | |
| 245 WebInputEvent::Type type, | |
| 246 int64_t latency_component_id, | |
| 247 const LatencyInfo& latency, | |
| 248 bool default_prevented) { | |
| 249 if (latency.coalesced()) | |
| 250 return; | |
| 251 | |
| 252 LatencyInfo::LatencyComponent rwh_component; | |
| 253 if (!latency.FindLatency(ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT, | |
| 254 latency_component_id, &rwh_component)) { | |
| 255 return; | |
| 256 } | |
| 257 DCHECK_EQ(rwh_component.event_count, 1u); | |
| 258 | |
| 259 LatencyInfo::LatencyComponent ui_component; | |
| 260 if (latency.FindLatency(ui::INPUT_EVENT_LATENCY_UI_COMPONENT, 0, | |
| 261 &ui_component)) { | |
| 262 DCHECK_EQ(ui_component.event_count, 1u); | |
| 263 base::TimeDelta ui_delta = | |
| 264 rwh_component.event_time - ui_component.event_time; | |
| 265 | |
| 266 if (type == blink::WebInputEvent::MouseWheel) { | |
| 267 UMA_HISTOGRAM_CUSTOM_COUNTS("Event.Latency.Browser.WheelUI", | |
| 268 ui_delta.InMicroseconds(), 1, 20000, 100); | |
| 269 | |
| 270 } else { | |
| 271 DCHECK(WebInputEvent::isTouchEventType(type)); | |
| 272 UMA_HISTOGRAM_CUSTOM_COUNTS("Event.Latency.Browser.TouchUI", | |
| 273 ui_delta.InMicroseconds(), 1, 20000, 100); | |
| 274 } | |
| 275 } | |
| 276 | |
| 277 LatencyInfo::LatencyComponent dispatched_to_renderer_component; | |
| 278 if (latency.FindLatency(ui::INPUT_EVENT_LATENCY_REACHED_RWH_COMPONENT, 0, | |
| 279 &dispatched_to_renderer_component)) { | |
| 280 DCHECK_EQ(dispatched_to_renderer_component.event_count, 1u); | |
| 281 base::TimeDelta queueing_delta = | |
| 282 dispatched_to_renderer_component.event_time - rwh_component.event_time; | |
| 283 if (type == WebInputEvent::TouchMove && !multi_finger_gesture_) { | |
| 284 if (touch_start_default_prevented_ || default_prevented) { | |
| 285 UMA_HISTOGRAM_CUSTOM_COUNTS( | |
| 286 "Event.Latency.QueueingTime.TouchMoveDefaultPrevented", | |
| 287 queueing_delta.InMicroseconds(), 1, 1000000, 100); | |
| 288 } else { | |
| 289 UMA_HISTOGRAM_CUSTOM_COUNTS( | |
| 290 "Event.Latency.QueueingTime.TouchMoveDefaultAllowed", | |
| 291 queueing_delta.InMicroseconds(), 1, 1000000, 100); | |
| 292 } | |
| 293 } | |
| 294 } | |
| 295 | |
| 296 LatencyInfo::LatencyComponent acked_component; | |
| 297 if (latency.FindLatency(ui::INPUT_EVENT_LATENCY_ACK_RWH_COMPONENT, 0, | |
| 298 &acked_component)) { | |
| 299 DCHECK_EQ(acked_component.event_count, 1u); | |
| 300 base::TimeDelta acked_delta = | |
| 301 acked_component.event_time - rwh_component.event_time; | |
| 302 if (type == blink::WebInputEvent::MouseWheel) { | |
| 303 UMA_HISTOGRAM_CUSTOM_COUNTS("Event.Latency.Browser.WheelAcked", | |
| 304 acked_delta.InMicroseconds(), 1, 1000000, | |
| 305 100); | |
| 306 } else { | |
| 307 DCHECK(WebInputEvent::isTouchEventType(type)); | |
| 308 UMA_HISTOGRAM_CUSTOM_COUNTS("Event.Latency.Browser.TouchAcked", | |
| 309 acked_delta.InMicroseconds(), 1, 1000000, | |
| 310 100); | |
| 311 } | |
| 312 | |
| 313 if (type == WebInputEvent::TouchMove && !multi_finger_gesture_) { | |
| 314 base::TimeDelta blocking_delta; | |
| 315 if (dispatched_to_renderer_component.event_time != base::TimeTicks()) { | |
| 316 blocking_delta = acked_component.event_time - | |
| 317 dispatched_to_renderer_component.event_time; | |
| 318 } | |
| 319 | |
| 320 if (touch_start_default_prevented_ || default_prevented) { | |
| 321 UMA_HISTOGRAM_CUSTOM_COUNTS( | |
| 322 "Event.Latency.BlockingTime.TouchMoveDefaultPrevented", | |
| 323 blocking_delta.InMicroseconds(), 1, 1000000, 100); | |
| 324 } else { | |
| 325 UMA_HISTOGRAM_CUSTOM_COUNTS( | |
| 326 "Event.Latency.BlockingTime.TouchMoveDefaultAllowed", | |
| 327 blocking_delta.InMicroseconds(), 1, 1000000, 100); | |
|
Ilya Sherman
2016/04/06 01:34:54
Do you need 100 buckets, or would 50 suffice?
tdresser
2016/05/19 20:48:08
Done.
| |
| 328 } | |
| 329 } | |
| 330 } | |
| 331 } | |
| 332 | |
| 304 void RenderWidgetHostLatencyTracker::OnInputEvent( | 333 void RenderWidgetHostLatencyTracker::OnInputEvent( |
| 305 const blink::WebInputEvent& event, | 334 const blink::WebInputEvent& event, |
| 306 LatencyInfo* latency) { | 335 LatencyInfo* latency) { |
| 307 DCHECK(latency); | 336 DCHECK(latency); |
| 308 if (latency->FindLatency(ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT, | 337 if (latency->FindLatency(ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT, |
| 309 latency_component_id_, NULL)) { | 338 latency_component_id_, NULL)) { |
| 310 return; | 339 return; |
| 311 } | 340 } |
| 312 | 341 |
| 313 if (event.timeStampSeconds && | 342 if (event.timeStampSeconds && |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 353 ? ui::INPUT_EVENT_LATENCY_SCROLL_UPDATE_ORIGINAL_COMPONENT | 382 ? ui::INPUT_EVENT_LATENCY_SCROLL_UPDATE_ORIGINAL_COMPONENT |
| 354 : ui::INPUT_EVENT_LATENCY_FIRST_SCROLL_UPDATE_ORIGINAL_COMPONENT, | 383 : ui::INPUT_EVENT_LATENCY_FIRST_SCROLL_UPDATE_ORIGINAL_COMPONENT, |
| 355 latency_component_id_, original_component.sequence_number, | 384 latency_component_id_, original_component.sequence_number, |
| 356 original_component.event_time, original_component.event_count); | 385 original_component.event_time, original_component.event_count); |
| 357 } | 386 } |
| 358 | 387 |
| 359 has_seen_first_gesture_scroll_update_ = true; | 388 has_seen_first_gesture_scroll_update_ = true; |
| 360 } | 389 } |
| 361 } | 390 } |
| 362 | 391 |
| 392 void RenderWidgetHostLatencyTracker::OnForwardEventToRenderer( | |
| 393 const blink::WebInputEvent& event, | |
| 394 ui::LatencyInfo* latency) { | |
| 395 DCHECK(latency); | |
| 396 if (WebInputEvent::isTouchEventType(event.type)) { | |
| 397 latency->AddLatencyNumber(ui::INPUT_EVENT_LATENCY_REACHED_RWH_COMPONENT, 0, | |
| 398 0); | |
| 399 } | |
| 400 } | |
| 401 | |
| 363 void RenderWidgetHostLatencyTracker::OnInputEventAck( | 402 void RenderWidgetHostLatencyTracker::OnInputEventAck( |
| 364 const blink::WebInputEvent& event, | 403 const blink::WebInputEvent& event, |
| 365 LatencyInfo* latency) { | 404 LatencyInfo* latency, bool defaultPrevented) { |
| 366 DCHECK(latency); | 405 DCHECK(latency); |
| 367 | 406 |
| 368 // Latency ends when it is acked but does not cause render scheduling. | 407 // Latency ends when it is acked but does not cause render scheduling. |
| 369 bool rendering_scheduled = latency->FindLatency( | 408 bool rendering_scheduled = latency->FindLatency( |
| 370 ui::INPUT_EVENT_LATENCY_RENDERING_SCHEDULED_MAIN_COMPONENT, 0, nullptr); | 409 ui::INPUT_EVENT_LATENCY_RENDERING_SCHEDULED_MAIN_COMPONENT, 0, nullptr); |
| 371 rendering_scheduled |= latency->FindLatency( | 410 rendering_scheduled |= latency->FindLatency( |
| 372 ui::INPUT_EVENT_LATENCY_RENDERING_SCHEDULED_IMPL_COMPONENT, 0, nullptr); | 411 ui::INPUT_EVENT_LATENCY_RENDERING_SCHEDULED_IMPL_COMPONENT, 0, nullptr); |
| 373 | 412 |
| 374 if (WebInputEvent::isGestureEventType(event.type)) { | 413 if (WebInputEvent::isGestureEventType(event.type)) { |
| 375 if (!rendering_scheduled) { | 414 if (!rendering_scheduled) { |
| 376 latency->AddLatencyNumber( | 415 latency->AddLatencyNumber( |
| 377 ui::INPUT_EVENT_LATENCY_TERMINATED_GESTURE_COMPONENT, 0, 0); | 416 ui::INPUT_EVENT_LATENCY_TERMINATED_GESTURE_COMPONENT, 0, 0); |
| 378 // TODO(jdduke): Consider exposing histograms for gesture event types. | 417 // TODO(jdduke): Consider exposing histograms for gesture event types. |
| 379 } | 418 } |
| 380 return; | 419 return; |
| 381 } | 420 } |
| 382 | 421 |
| 383 if (WebInputEvent::isTouchEventType(event.type)) { | 422 if (WebInputEvent::isTouchEventType(event.type)) { |
| 423 const WebTouchEvent& touch_event = | |
| 424 *static_cast<const WebTouchEvent*>(&event); | |
| 425 if (event.type == WebInputEvent::TouchStart) { | |
| 426 DCHECK(touch_event.touchesLength >= 1); | |
| 427 multi_finger_gesture_ = touch_event.touchesLength != 1; | |
| 428 touch_start_default_prevented_ = defaultPrevented; | |
| 429 } | |
| 430 | |
| 384 latency->AddLatencyNumber(ui::INPUT_EVENT_LATENCY_ACK_RWH_COMPONENT, 0, 0); | 431 latency->AddLatencyNumber(ui::INPUT_EVENT_LATENCY_ACK_RWH_COMPONENT, 0, 0); |
| 432 | |
| 385 if (!rendering_scheduled) { | 433 if (!rendering_scheduled) { |
| 386 latency->AddLatencyNumber( | 434 latency->AddLatencyNumber( |
| 387 ui::INPUT_EVENT_LATENCY_TERMINATED_TOUCH_COMPONENT, 0, 0); | 435 ui::INPUT_EVENT_LATENCY_TERMINATED_TOUCH_COMPONENT, 0, 0); |
| 388 } | 436 } |
| 389 ComputeInputLatencyHistograms(WebInputEvent::TouchTypeFirst, | 437 ComputeInputLatencyHistograms(event.type, latency_component_id_, *latency, |
| 390 latency_component_id_, *latency); | 438 defaultPrevented); |
| 391 return; | 439 return; |
| 392 } | 440 } |
| 393 | 441 |
| 394 if (event.type == WebInputEvent::MouseWheel) { | 442 if (event.type == WebInputEvent::MouseWheel) { |
| 395 latency->AddLatencyNumber(ui::INPUT_EVENT_LATENCY_ACK_RWH_COMPONENT, 0, 0); | 443 latency->AddLatencyNumber(ui::INPUT_EVENT_LATENCY_ACK_RWH_COMPONENT, 0, 0); |
| 396 if (!rendering_scheduled) { | 444 if (!rendering_scheduled) { |
| 397 latency->AddLatencyNumber( | 445 latency->AddLatencyNumber( |
| 398 ui::INPUT_EVENT_LATENCY_TERMINATED_MOUSE_WHEEL_COMPONENT, 0, 0); | 446 ui::INPUT_EVENT_LATENCY_TERMINATED_MOUSE_WHEEL_COMPONENT, 0, 0); |
| 399 } | 447 } |
| 400 ComputeInputLatencyHistograms(WebInputEvent::MouseWheel, | 448 ComputeInputLatencyHistograms(event.type, latency_component_id_, *latency, |
| 401 latency_component_id_, *latency); | 449 defaultPrevented); |
| 402 return; | 450 return; |
| 403 } | 451 } |
| 404 | 452 |
| 405 if (WebInputEvent::isMouseEventType(event.type) && !rendering_scheduled) { | 453 if (WebInputEvent::isMouseEventType(event.type) && !rendering_scheduled) { |
| 406 latency->AddLatencyNumber( | 454 latency->AddLatencyNumber( |
| 407 ui::INPUT_EVENT_LATENCY_TERMINATED_MOUSE_COMPONENT, 0, 0); | 455 ui::INPUT_EVENT_LATENCY_TERMINATED_MOUSE_COMPONENT, 0, 0); |
| 408 return; | 456 return; |
| 409 } | 457 } |
| 410 | 458 |
| 411 if (WebInputEvent::isKeyboardEventType(event.type) && !rendering_scheduled) { | 459 if (WebInputEvent::isKeyboardEventType(event.type) && !rendering_scheduled) { |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 454 latency_component_id_, nullptr)) { | 502 latency_component_id_, nullptr)) { |
| 455 return; | 503 return; |
| 456 } | 504 } |
| 457 | 505 |
| 458 ComputeScrollLatencyHistograms(gpu_swap_begin_component, | 506 ComputeScrollLatencyHistograms(gpu_swap_begin_component, |
| 459 gpu_swap_end_component, latency_component_id_, | 507 gpu_swap_end_component, latency_component_id_, |
| 460 latency); | 508 latency); |
| 461 } | 509 } |
| 462 | 510 |
| 463 } // namespace content | 511 } // namespace content |
| OLD | NEW |