| 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 InputEventAckState ack_result) { |
| 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 main_component; |
| 278 if (latency.FindLatency(ui::INPUT_EVENT_LATENCY_RENDERER_MAIN_COMPONENT, 0, |
| 279 &main_component)) { |
| 280 DCHECK_EQ(main_component.event_count, 1u); |
| 281 base::TimeDelta queueing_delta = |
| 282 main_component.event_time - rwh_component.event_time; |
| 283 if (type == WebInputEvent::TouchMove && !multi_finger_gesture_) { |
| 284 if (touch_start_default_prevented_ || |
| 285 ack_result == INPUT_EVENT_ACK_STATE_CONSUMED) { |
| 286 UMA_HISTOGRAM_TIMES( |
| 287 "Event.Latency.QueueingTime.TouchMoveDefaultPrevented", |
| 288 queueing_delta); |
| 289 } else if (ack_result == INPUT_EVENT_ACK_STATE_NOT_CONSUMED) { |
| 290 UMA_HISTOGRAM_TIMES( |
| 291 "Event.Latency.QueueingTime.TouchMoveDefaultAllowed", |
| 292 queueing_delta); |
| 293 } |
| 294 } |
| 295 } |
| 296 |
| 297 LatencyInfo::LatencyComponent acked_component; |
| 298 if (latency.FindLatency(ui::INPUT_EVENT_LATENCY_ACK_RWH_COMPONENT, 0, |
| 299 &acked_component)) { |
| 300 DCHECK_EQ(acked_component.event_count, 1u); |
| 301 base::TimeDelta acked_delta = |
| 302 acked_component.event_time - rwh_component.event_time; |
| 303 if (type == blink::WebInputEvent::MouseWheel) { |
| 304 UMA_HISTOGRAM_CUSTOM_COUNTS("Event.Latency.Browser.WheelAcked", |
| 305 acked_delta.InMicroseconds(), 1, 1000000, |
| 306 100); |
| 307 } else { |
| 308 DCHECK(WebInputEvent::isTouchEventType(type)); |
| 309 UMA_HISTOGRAM_CUSTOM_COUNTS("Event.Latency.Browser.TouchAcked", |
| 310 acked_delta.InMicroseconds(), 1, 1000000, |
| 311 100); |
| 312 } |
| 313 |
| 314 if (type == WebInputEvent::TouchMove && !multi_finger_gesture_ && |
| 315 main_component.event_time != base::TimeTicks()) { |
| 316 base::TimeDelta blocking_delta; |
| 317 blocking_delta = acked_component.event_time - main_component.event_time; |
| 318 |
| 319 if (touch_start_default_prevented_ || |
| 320 ack_result == INPUT_EVENT_ACK_STATE_CONSUMED) { |
| 321 UMA_HISTOGRAM_TIMES( |
| 322 "Event.Latency.BlockingTime.TouchMoveDefaultPrevented", |
| 323 blocking_delta); |
| 324 } else if (ack_result == INPUT_EVENT_ACK_STATE_NOT_CONSUMED) { |
| 325 UMA_HISTOGRAM_TIMES( |
| 326 "Event.Latency.BlockingTime.TouchMoveDefaultAllowed", |
| 327 blocking_delta); |
| 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 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 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 |
| 363 void RenderWidgetHostLatencyTracker::OnInputEventAck( | 392 void RenderWidgetHostLatencyTracker::OnInputEventAck( |
| 364 const blink::WebInputEvent& event, | 393 const blink::WebInputEvent& event, |
| 365 LatencyInfo* latency) { | 394 LatencyInfo* latency, InputEventAckState ack_result) { |
| 366 DCHECK(latency); | 395 DCHECK(latency); |
| 367 | 396 |
| 368 // Latency ends when it is acked but does not cause render scheduling. | 397 // Latency ends when it is acked but does not cause render scheduling. |
| 369 bool rendering_scheduled = latency->FindLatency( | 398 bool rendering_scheduled = latency->FindLatency( |
| 370 ui::INPUT_EVENT_LATENCY_RENDERING_SCHEDULED_MAIN_COMPONENT, 0, nullptr); | 399 ui::INPUT_EVENT_LATENCY_RENDERING_SCHEDULED_MAIN_COMPONENT, 0, nullptr); |
| 371 rendering_scheduled |= latency->FindLatency( | 400 rendering_scheduled |= latency->FindLatency( |
| 372 ui::INPUT_EVENT_LATENCY_RENDERING_SCHEDULED_IMPL_COMPONENT, 0, nullptr); | 401 ui::INPUT_EVENT_LATENCY_RENDERING_SCHEDULED_IMPL_COMPONENT, 0, nullptr); |
| 373 | 402 |
| 374 if (WebInputEvent::isGestureEventType(event.type)) { | 403 if (WebInputEvent::isGestureEventType(event.type)) { |
| 375 if (!rendering_scheduled) { | 404 if (!rendering_scheduled) { |
| 376 latency->AddLatencyNumber( | 405 latency->AddLatencyNumber( |
| 377 ui::INPUT_EVENT_LATENCY_TERMINATED_GESTURE_COMPONENT, 0, 0); | 406 ui::INPUT_EVENT_LATENCY_TERMINATED_GESTURE_COMPONENT, 0, 0); |
| 378 // TODO(jdduke): Consider exposing histograms for gesture event types. | 407 // TODO(jdduke): Consider exposing histograms for gesture event types. |
| 379 } | 408 } |
| 380 return; | 409 return; |
| 381 } | 410 } |
| 382 | 411 |
| 383 if (WebInputEvent::isTouchEventType(event.type)) { | 412 if (WebInputEvent::isTouchEventType(event.type)) { |
| 413 const WebTouchEvent& touch_event = |
| 414 *static_cast<const WebTouchEvent*>(&event); |
| 415 if (event.type == WebInputEvent::TouchStart) { |
| 416 DCHECK(touch_event.touchesLength >= 1); |
| 417 multi_finger_gesture_ = touch_event.touchesLength != 1; |
| 418 touch_start_default_prevented_ = |
| 419 ack_result == INPUT_EVENT_ACK_STATE_CONSUMED; |
| 420 } |
| 421 |
| 384 latency->AddLatencyNumber(ui::INPUT_EVENT_LATENCY_ACK_RWH_COMPONENT, 0, 0); | 422 latency->AddLatencyNumber(ui::INPUT_EVENT_LATENCY_ACK_RWH_COMPONENT, 0, 0); |
| 423 |
| 385 if (!rendering_scheduled) { | 424 if (!rendering_scheduled) { |
| 386 latency->AddLatencyNumber( | 425 latency->AddLatencyNumber( |
| 387 ui::INPUT_EVENT_LATENCY_TERMINATED_TOUCH_COMPONENT, 0, 0); | 426 ui::INPUT_EVENT_LATENCY_TERMINATED_TOUCH_COMPONENT, 0, 0); |
| 388 } | 427 } |
| 389 ComputeInputLatencyHistograms(WebInputEvent::TouchTypeFirst, | 428 ComputeInputLatencyHistograms(event.type, latency_component_id_, *latency, |
| 390 latency_component_id_, *latency); | 429 ack_result); |
| 391 return; | 430 return; |
| 392 } | 431 } |
| 393 | 432 |
| 394 if (event.type == WebInputEvent::MouseWheel) { | 433 if (event.type == WebInputEvent::MouseWheel) { |
| 395 latency->AddLatencyNumber(ui::INPUT_EVENT_LATENCY_ACK_RWH_COMPONENT, 0, 0); | 434 latency->AddLatencyNumber(ui::INPUT_EVENT_LATENCY_ACK_RWH_COMPONENT, 0, 0); |
| 396 if (!rendering_scheduled) { | 435 if (!rendering_scheduled) { |
| 397 latency->AddLatencyNumber( | 436 latency->AddLatencyNumber( |
| 398 ui::INPUT_EVENT_LATENCY_TERMINATED_MOUSE_WHEEL_COMPONENT, 0, 0); | 437 ui::INPUT_EVENT_LATENCY_TERMINATED_MOUSE_WHEEL_COMPONENT, 0, 0); |
| 399 } | 438 } |
| 400 ComputeInputLatencyHistograms(WebInputEvent::MouseWheel, | 439 ComputeInputLatencyHistograms(event.type, latency_component_id_, *latency, |
| 401 latency_component_id_, *latency); | 440 ack_result); |
| 402 return; | 441 return; |
| 403 } | 442 } |
| 404 | 443 |
| 405 if (WebInputEvent::isMouseEventType(event.type) && !rendering_scheduled) { | 444 if (WebInputEvent::isMouseEventType(event.type) && !rendering_scheduled) { |
| 406 latency->AddLatencyNumber( | 445 latency->AddLatencyNumber( |
| 407 ui::INPUT_EVENT_LATENCY_TERMINATED_MOUSE_COMPONENT, 0, 0); | 446 ui::INPUT_EVENT_LATENCY_TERMINATED_MOUSE_COMPONENT, 0, 0); |
| 408 return; | 447 return; |
| 409 } | 448 } |
| 410 | 449 |
| 411 if (WebInputEvent::isKeyboardEventType(event.type) && !rendering_scheduled) { | 450 if (WebInputEvent::isKeyboardEventType(event.type) && !rendering_scheduled) { |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 464 latency_component_id_, nullptr)) { | 503 latency_component_id_, nullptr)) { |
| 465 return; | 504 return; |
| 466 } | 505 } |
| 467 | 506 |
| 468 ComputeScrollLatencyHistograms(gpu_swap_begin_component, | 507 ComputeScrollLatencyHistograms(gpu_swap_begin_component, |
| 469 gpu_swap_end_component, latency_component_id_, | 508 gpu_swap_end_component, latency_component_id_, |
| 470 latency); | 509 latency); |
| 471 } | 510 } |
| 472 | 511 |
| 473 } // namespace content | 512 } // namespace content |
| OLD | NEW |