| 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 "components/scheduler/renderer/renderer_scheduler_impl.h" | 5 #include "components/scheduler/renderer/renderer_scheduler_impl.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/debug/stack_trace.h" | 8 #include "base/debug/stack_trace.h" |
| 9 #include "base/logging.h" | 9 #include "base/logging.h" |
| 10 #include "base/memory/ptr_util.h" | 10 #include "base/memory/ptr_util.h" |
| (...skipping 386 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 397 } | 397 } |
| 398 | 398 |
| 399 void RendererSchedulerImpl::EndIdlePeriodForTesting( | 399 void RendererSchedulerImpl::EndIdlePeriodForTesting( |
| 400 const base::Closure& callback, | 400 const base::Closure& callback, |
| 401 base::TimeTicks time_remaining) { | 401 base::TimeTicks time_remaining) { |
| 402 MainThreadOnly().in_idle_period_for_testing = false; | 402 MainThreadOnly().in_idle_period_for_testing = false; |
| 403 EndIdlePeriod(); | 403 EndIdlePeriod(); |
| 404 callback.Run(); | 404 callback.Run(); |
| 405 } | 405 } |
| 406 | 406 |
| 407 bool RendererSchedulerImpl::PolicyNeedsUpdateForTesting() { |
| 408 return policy_may_need_update_.IsSet(); |
| 409 } |
| 410 |
| 407 // static | 411 // static |
| 408 bool RendererSchedulerImpl::ShouldPrioritizeInputEvent( | 412 bool RendererSchedulerImpl::ShouldPrioritizeInputEvent( |
| 409 const blink::WebInputEvent& web_input_event) { | 413 const blink::WebInputEvent& web_input_event) { |
| 410 // We regard MouseMove events with the left mouse button down as a signal | 414 // We regard MouseMove events with the left mouse button down as a signal |
| 411 // that the user is doing something requiring a smooth frame rate. | 415 // that the user is doing something requiring a smooth frame rate. |
| 412 if (web_input_event.type == blink::WebInputEvent::MouseMove && | 416 if (web_input_event.type == blink::WebInputEvent::MouseMove && |
| 413 (web_input_event.modifiers & blink::WebInputEvent::LeftButtonDown)) { | 417 (web_input_event.modifiers & blink::WebInputEvent::LeftButtonDown)) { |
| 414 return true; | 418 return true; |
| 415 } | 419 } |
| 416 // Ignore all other mouse events because they probably don't signal user | 420 // Ignore all other mouse events because they probably don't signal user |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 451 base::AutoLock lock(any_thread_lock_); | 455 base::AutoLock lock(any_thread_lock_); |
| 452 base::TimeTicks now = helper_.scheduler_tqm_delegate()->NowTicks(); | 456 base::TimeTicks now = helper_.scheduler_tqm_delegate()->NowTicks(); |
| 453 | 457 |
| 454 // TODO(alexclarke): Move WebInputEventTraits where we can access it from here | 458 // TODO(alexclarke): Move WebInputEventTraits where we can access it from here |
| 455 // and record the name rather than the integer representation. | 459 // and record the name rather than the integer representation. |
| 456 TRACE_EVENT2(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), | 460 TRACE_EVENT2(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), |
| 457 "RendererSchedulerImpl::UpdateForInputEventOnCompositorThread", | 461 "RendererSchedulerImpl::UpdateForInputEventOnCompositorThread", |
| 458 "type", static_cast<int>(type), "input_event_state", | 462 "type", static_cast<int>(type), "input_event_state", |
| 459 InputEventStateToString(input_event_state)); | 463 InputEventStateToString(input_event_state)); |
| 460 | 464 |
| 461 bool gesture_already_in_progress = InputSignalsSuggestGestureInProgress(now); | 465 base::TimeDelta unused_policy_duration; |
| 466 UseCase previous_use_case = |
| 467 ComputeCurrentUseCase(now, &unused_policy_duration); |
| 462 bool was_awaiting_touch_start_response = | 468 bool was_awaiting_touch_start_response = |
| 463 AnyThread().awaiting_touch_start_response; | 469 AnyThread().awaiting_touch_start_response; |
| 464 | 470 |
| 465 AnyThread().user_model.DidStartProcessingInputEvent(type, now); | 471 AnyThread().user_model.DidStartProcessingInputEvent(type, now); |
| 466 | 472 |
| 467 if (input_event_state == InputEventState::EVENT_CONSUMED_BY_COMPOSITOR) | 473 if (input_event_state == InputEventState::EVENT_CONSUMED_BY_COMPOSITOR) |
| 468 AnyThread().user_model.DidFinishProcessingInputEvent(now); | 474 AnyThread().user_model.DidFinishProcessingInputEvent(now); |
| 469 | 475 |
| 470 if (type) { | 476 if (type) { |
| 471 switch (type) { | 477 switch (type) { |
| (...skipping 14 matching lines...) Expand all Loading... |
| 486 // state. | 492 // state. |
| 487 if (AnyThread().awaiting_touch_start_response && | 493 if (AnyThread().awaiting_touch_start_response && |
| 488 CompositorThreadOnly().last_input_type == | 494 CompositorThreadOnly().last_input_type == |
| 489 blink::WebInputEvent::TouchMove) { | 495 blink::WebInputEvent::TouchMove) { |
| 490 AnyThread().awaiting_touch_start_response = false; | 496 AnyThread().awaiting_touch_start_response = false; |
| 491 } | 497 } |
| 492 break; | 498 break; |
| 493 | 499 |
| 494 case blink::WebInputEvent::GesturePinchUpdate: | 500 case blink::WebInputEvent::GesturePinchUpdate: |
| 495 case blink::WebInputEvent::GestureScrollUpdate: | 501 case blink::WebInputEvent::GestureScrollUpdate: |
| 502 // If we see events for an established gesture, we can lock it to the |
| 503 // appropriate thread as the gesture can no longer be cancelled. |
| 496 AnyThread().last_gesture_was_compositor_driven = | 504 AnyThread().last_gesture_was_compositor_driven = |
| 497 input_event_state == InputEventState::EVENT_CONSUMED_BY_COMPOSITOR; | 505 input_event_state == InputEventState::EVENT_CONSUMED_BY_COMPOSITOR; |
| 498 AnyThread().awaiting_touch_start_response = false; | 506 AnyThread().awaiting_touch_start_response = false; |
| 499 break; | 507 break; |
| 500 | 508 |
| 501 case blink::WebInputEvent::GestureFlingCancel: | 509 case blink::WebInputEvent::GestureFlingCancel: |
| 502 AnyThread().fling_compositor_escalation_deadline = base::TimeTicks(); | 510 AnyThread().fling_compositor_escalation_deadline = base::TimeTicks(); |
| 503 break; | 511 break; |
| 504 | 512 |
| 505 case blink::WebInputEvent::GestureTapDown: | 513 case blink::WebInputEvent::GestureTapDown: |
| 506 case blink::WebInputEvent::GestureShowPress: | 514 case blink::WebInputEvent::GestureShowPress: |
| 507 case blink::WebInputEvent::GestureScrollEnd: | 515 case blink::WebInputEvent::GestureScrollEnd: |
| 508 // With no observable effect, these meta events do not indicate a | 516 // With no observable effect, these meta events do not indicate a |
| 509 // meaningful touchstart response and should not impact task priority. | 517 // meaningful touchstart response and should not impact task priority. |
| 510 break; | 518 break; |
| 511 | 519 |
| 512 default: | 520 default: |
| 513 AnyThread().awaiting_touch_start_response = false; | 521 AnyThread().awaiting_touch_start_response = false; |
| 514 break; | 522 break; |
| 515 } | 523 } |
| 516 } | 524 } |
| 517 | 525 |
| 518 // Avoid unnecessary policy updates, while a gesture is already in progress. | 526 // Avoid unnecessary policy updates if the use case did not change. |
| 519 if (!gesture_already_in_progress || | 527 UseCase use_case = ComputeCurrentUseCase(now, &unused_policy_duration); |
| 528 |
| 529 if (use_case != previous_use_case || |
| 520 was_awaiting_touch_start_response != | 530 was_awaiting_touch_start_response != |
| 521 AnyThread().awaiting_touch_start_response) { | 531 AnyThread().awaiting_touch_start_response) { |
| 522 EnsureUrgentPolicyUpdatePostedOnMainThread(FROM_HERE); | 532 EnsureUrgentPolicyUpdatePostedOnMainThread(FROM_HERE); |
| 523 } | 533 } |
| 524 CompositorThreadOnly().last_input_type = type; | 534 CompositorThreadOnly().last_input_type = type; |
| 525 } | 535 } |
| 526 | 536 |
| 527 void RendererSchedulerImpl::DidHandleInputEventOnMainThread( | 537 void RendererSchedulerImpl::DidHandleInputEventOnMainThread( |
| 528 const blink::WebInputEvent& web_input_event) { | 538 const blink::WebInputEvent& web_input_event) { |
| 529 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), | 539 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), |
| (...skipping 262 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 792 } | 802 } |
| 793 | 803 |
| 794 // Tracing is done before the early out check, because it's quite possible we | 804 // Tracing is done before the early out check, because it's quite possible we |
| 795 // will otherwise miss this information in traces. | 805 // will otherwise miss this information in traces. |
| 796 TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID( | 806 TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID( |
| 797 TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), "RendererScheduler", | 807 TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), "RendererScheduler", |
| 798 this, AsValueLocked(now)); | 808 this, AsValueLocked(now)); |
| 799 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), "use_case", | 809 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), "use_case", |
| 800 use_case); | 810 use_case); |
| 801 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), | 811 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), |
| 812 "touchstart_expected_soon", |
| 813 MainThreadOnly().touchstart_expected_soon); |
| 814 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), |
| 815 "expensive_task_policy", expensive_task_policy); |
| 816 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), |
| 802 "RendererScheduler.loading_tasks_seem_expensive", | 817 "RendererScheduler.loading_tasks_seem_expensive", |
| 803 MainThreadOnly().loading_tasks_seem_expensive); | 818 MainThreadOnly().loading_tasks_seem_expensive); |
| 804 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), | 819 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), |
| 805 "RendererScheduler.timer_tasks_seem_expensive", | 820 "RendererScheduler.timer_tasks_seem_expensive", |
| 806 MainThreadOnly().timer_tasks_seem_expensive); | 821 MainThreadOnly().timer_tasks_seem_expensive); |
| 807 | 822 |
| 808 // TODO(alexclarke): Can we get rid of force update now? | 823 // TODO(alexclarke): Can we get rid of force update now? |
| 809 if (update_type == UpdateType::MAY_EARLY_OUT_IF_POLICY_UNCHANGED && | 824 if (update_type == UpdateType::MAY_EARLY_OUT_IF_POLICY_UNCHANGED && |
| 810 new_policy == MainThreadOnly().current_policy) { | 825 new_policy == MainThreadOnly().current_policy) { |
| 811 return; | 826 return; |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 855 new_task_queue_policy.time_domain_type) { | 870 new_task_queue_policy.time_domain_type) { |
| 856 if (new_task_queue_policy.time_domain_type == TimeDomainType::THROTTLED) { | 871 if (new_task_queue_policy.time_domain_type == TimeDomainType::THROTTLED) { |
| 857 throttling_helper_->IncreaseThrottleRefCount(task_queue); | 872 throttling_helper_->IncreaseThrottleRefCount(task_queue); |
| 858 } else if (old_task_queue_policy.time_domain_type == | 873 } else if (old_task_queue_policy.time_domain_type == |
| 859 TimeDomainType::THROTTLED) { | 874 TimeDomainType::THROTTLED) { |
| 860 throttling_helper_->DecreaseThrottleRefCount(task_queue); | 875 throttling_helper_->DecreaseThrottleRefCount(task_queue); |
| 861 } | 876 } |
| 862 } | 877 } |
| 863 } | 878 } |
| 864 | 879 |
| 865 bool RendererSchedulerImpl::InputSignalsSuggestGestureInProgress( | |
| 866 base::TimeTicks now) const { | |
| 867 base::TimeDelta unused_policy_duration; | |
| 868 switch (ComputeCurrentUseCase(now, &unused_policy_duration)) { | |
| 869 case UseCase::COMPOSITOR_GESTURE: | |
| 870 case UseCase::MAIN_THREAD_GESTURE: | |
| 871 case UseCase::SYNCHRONIZED_GESTURE: | |
| 872 case UseCase::TOUCHSTART: | |
| 873 return true; | |
| 874 | |
| 875 default: | |
| 876 break; | |
| 877 } | |
| 878 return false; | |
| 879 } | |
| 880 | |
| 881 RendererSchedulerImpl::UseCase RendererSchedulerImpl::ComputeCurrentUseCase( | 880 RendererSchedulerImpl::UseCase RendererSchedulerImpl::ComputeCurrentUseCase( |
| 882 base::TimeTicks now, | 881 base::TimeTicks now, |
| 883 base::TimeDelta* expected_use_case_duration) const { | 882 base::TimeDelta* expected_use_case_duration) const { |
| 884 any_thread_lock_.AssertAcquired(); | 883 any_thread_lock_.AssertAcquired(); |
| 885 // Special case for flings. This is needed because we don't get notification | 884 // Special case for flings. This is needed because we don't get notification |
| 886 // of a fling ending (although we do for cancellation). | 885 // of a fling ending (although we do for cancellation). |
| 887 if (AnyThread().fling_compositor_escalation_deadline > now && | 886 if (AnyThread().fling_compositor_escalation_deadline > now && |
| 888 !AnyThread().awaiting_touch_start_response) { | 887 !AnyThread().awaiting_touch_start_response) { |
| 889 *expected_use_case_duration = | 888 *expected_use_case_duration = |
| 890 AnyThread().fling_compositor_escalation_deadline - now; | 889 AnyThread().fling_compositor_escalation_deadline - now; |
| (...skipping 378 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1269 } | 1268 } |
| 1270 MainThreadOnly().have_reported_blocking_intervention_since_navigation = | 1269 MainThreadOnly().have_reported_blocking_intervention_since_navigation = |
| 1271 true; | 1270 true; |
| 1272 BroadcastConsoleWarning( | 1271 BroadcastConsoleWarning( |
| 1273 "Deferred long-running timer task(s) to improve scrolling smoothness. " | 1272 "Deferred long-running timer task(s) to improve scrolling smoothness. " |
| 1274 "See crbug.com/574343."); | 1273 "See crbug.com/574343."); |
| 1275 } | 1274 } |
| 1276 } | 1275 } |
| 1277 | 1276 |
| 1278 } // namespace scheduler | 1277 } // namespace scheduler |
| OLD | NEW |