| 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 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 133 expensive_task_blocking_allowed(true), | 133 expensive_task_blocking_allowed(true), |
| 134 in_idle_period_for_testing(false) {} | 134 in_idle_period_for_testing(false) {} |
| 135 | 135 |
| 136 RendererSchedulerImpl::MainThreadOnly::~MainThreadOnly() {} | 136 RendererSchedulerImpl::MainThreadOnly::~MainThreadOnly() {} |
| 137 | 137 |
| 138 RendererSchedulerImpl::AnyThread::AnyThread() | 138 RendererSchedulerImpl::AnyThread::AnyThread() |
| 139 : awaiting_touch_start_response(false), | 139 : awaiting_touch_start_response(false), |
| 140 in_idle_period(false), | 140 in_idle_period(false), |
| 141 begin_main_frame_on_critical_path(false), | 141 begin_main_frame_on_critical_path(false), |
| 142 last_gesture_was_compositor_driven(false), | 142 last_gesture_was_compositor_driven(false), |
| 143 default_gesture_prevented(true), |
| 143 have_seen_touchstart(false) {} | 144 have_seen_touchstart(false) {} |
| 144 | 145 |
| 145 RendererSchedulerImpl::AnyThread::~AnyThread() {} | 146 RendererSchedulerImpl::AnyThread::~AnyThread() {} |
| 146 | 147 |
| 147 RendererSchedulerImpl::CompositorThreadOnly::CompositorThreadOnly() | 148 RendererSchedulerImpl::CompositorThreadOnly::CompositorThreadOnly() |
| 148 : last_input_type(blink::WebInputEvent::Undefined) {} | 149 : last_input_type(blink::WebInputEvent::Undefined) {} |
| 149 | 150 |
| 150 RendererSchedulerImpl::CompositorThreadOnly::~CompositorThreadOnly() {} | 151 RendererSchedulerImpl::CompositorThreadOnly::~CompositorThreadOnly() {} |
| 151 | 152 |
| 152 void RendererSchedulerImpl::Shutdown() { | 153 void RendererSchedulerImpl::Shutdown() { |
| (...skipping 333 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 486 | 487 |
| 487 if (type) { | 488 if (type) { |
| 488 switch (type) { | 489 switch (type) { |
| 489 case blink::WebInputEvent::TouchStart: | 490 case blink::WebInputEvent::TouchStart: |
| 490 AnyThread().awaiting_touch_start_response = true; | 491 AnyThread().awaiting_touch_start_response = true; |
| 491 // This is just a fail-safe to reset the state of | 492 // This is just a fail-safe to reset the state of |
| 492 // |last_gesture_was_compositor_driven| to the default. We don't know | 493 // |last_gesture_was_compositor_driven| to the default. We don't know |
| 493 // yet where the gesture will run. | 494 // yet where the gesture will run. |
| 494 AnyThread().last_gesture_was_compositor_driven = false; | 495 AnyThread().last_gesture_was_compositor_driven = false; |
| 495 AnyThread().have_seen_touchstart = true; | 496 AnyThread().have_seen_touchstart = true; |
| 497 // Assume the default gesture is prevented until we see evidence |
| 498 // otherwise. |
| 499 AnyThread().default_gesture_prevented = true; |
| 496 break; | 500 break; |
| 497 | 501 |
| 498 case blink::WebInputEvent::TouchMove: | 502 case blink::WebInputEvent::TouchMove: |
| 499 // Observation of consecutive touchmoves is a strong signal that the | 503 // Observation of consecutive touchmoves is a strong signal that the |
| 500 // page is consuming the touch sequence, in which case touchstart | 504 // page is consuming the touch sequence, in which case touchstart |
| 501 // response prioritization is no longer necessary. Otherwise, the | 505 // response prioritization is no longer necessary. Otherwise, the |
| 502 // initial touchmove should preserve the touchstart response pending | 506 // initial touchmove should preserve the touchstart response pending |
| 503 // state. | 507 // state. |
| 504 if (AnyThread().awaiting_touch_start_response && | 508 if (AnyThread().awaiting_touch_start_response && |
| 505 CompositorThreadOnly().last_input_type == | 509 CompositorThreadOnly().last_input_type == |
| 506 blink::WebInputEvent::TouchMove) { | 510 blink::WebInputEvent::TouchMove) { |
| 507 AnyThread().awaiting_touch_start_response = false; | 511 AnyThread().awaiting_touch_start_response = false; |
| 508 } | 512 } |
| 509 break; | 513 break; |
| 510 | 514 |
| 511 case blink::WebInputEvent::GesturePinchUpdate: | 515 case blink::WebInputEvent::GesturePinchUpdate: |
| 512 case blink::WebInputEvent::GestureScrollUpdate: | 516 case blink::WebInputEvent::GestureScrollUpdate: |
| 513 // If we see events for an established gesture, we can lock it to the | 517 // If we see events for an established gesture, we can lock it to the |
| 514 // appropriate thread as the gesture can no longer be cancelled. | 518 // appropriate thread as the gesture can no longer be cancelled. |
| 515 AnyThread().last_gesture_was_compositor_driven = | 519 AnyThread().last_gesture_was_compositor_driven = |
| 516 input_event_state == InputEventState::EVENT_CONSUMED_BY_COMPOSITOR; | 520 input_event_state == InputEventState::EVENT_CONSUMED_BY_COMPOSITOR; |
| 517 AnyThread().awaiting_touch_start_response = false; | 521 AnyThread().awaiting_touch_start_response = false; |
| 522 AnyThread().default_gesture_prevented = false; |
| 518 break; | 523 break; |
| 519 | 524 |
| 520 case blink::WebInputEvent::GestureFlingCancel: | 525 case blink::WebInputEvent::GestureFlingCancel: |
| 521 AnyThread().fling_compositor_escalation_deadline = base::TimeTicks(); | 526 AnyThread().fling_compositor_escalation_deadline = base::TimeTicks(); |
| 522 break; | 527 break; |
| 523 | 528 |
| 524 case blink::WebInputEvent::GestureTapDown: | 529 case blink::WebInputEvent::GestureTapDown: |
| 525 case blink::WebInputEvent::GestureShowPress: | 530 case blink::WebInputEvent::GestureShowPress: |
| 526 case blink::WebInputEvent::GestureScrollEnd: | 531 case blink::WebInputEvent::GestureScrollEnd: |
| 527 // With no observable effect, these meta events do not indicate a | 532 // With no observable effect, these meta events do not indicate a |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 562 if (helper_.IsShutdown()) | 567 if (helper_.IsShutdown()) |
| 563 return false; | 568 return false; |
| 564 | 569 |
| 565 MaybeUpdatePolicy(); | 570 MaybeUpdatePolicy(); |
| 566 // The touchstart, synchronized gesture and main-thread gesture use cases | 571 // The touchstart, synchronized gesture and main-thread gesture use cases |
| 567 // indicate a strong likelihood of high-priority work in the near future. | 572 // indicate a strong likelihood of high-priority work in the near future. |
| 568 UseCase use_case = MainThreadOnly().current_use_case; | 573 UseCase use_case = MainThreadOnly().current_use_case; |
| 569 return MainThreadOnly().touchstart_expected_soon || | 574 return MainThreadOnly().touchstart_expected_soon || |
| 570 use_case == UseCase::TOUCHSTART || | 575 use_case == UseCase::TOUCHSTART || |
| 571 use_case == UseCase::MAIN_THREAD_GESTURE || | 576 use_case == UseCase::MAIN_THREAD_GESTURE || |
| 577 use_case == UseCase::MAIN_THREAD_CUSTOM_INPUT_HANDLING || |
| 572 use_case == UseCase::SYNCHRONIZED_GESTURE; | 578 use_case == UseCase::SYNCHRONIZED_GESTURE; |
| 573 } | 579 } |
| 574 | 580 |
| 575 bool RendererSchedulerImpl::ShouldYieldForHighPriorityWork() { | 581 bool RendererSchedulerImpl::ShouldYieldForHighPriorityWork() { |
| 576 helper_.CheckOnValidThread(); | 582 helper_.CheckOnValidThread(); |
| 577 if (helper_.IsShutdown()) | 583 if (helper_.IsShutdown()) |
| 578 return false; | 584 return false; |
| 579 | 585 |
| 580 MaybeUpdatePolicy(); | 586 MaybeUpdatePolicy(); |
| 581 // We only yield if there's a urgent task to be run now, or we are expecting | 587 // We only yield if there's a urgent task to be run now, or we are expecting |
| 582 // one soon (touch start). | 588 // one soon (touch start). |
| 583 // Note: even though the control queue has the highest priority we don't yield | 589 // Note: even though the control queue has the highest priority we don't yield |
| 584 // for it since these tasks are not user-provided work and they are only | 590 // for it since these tasks are not user-provided work and they are only |
| 585 // intended to run before the next task, not interrupt the tasks. | 591 // intended to run before the next task, not interrupt the tasks. |
| 586 switch (MainThreadOnly().current_use_case) { | 592 switch (MainThreadOnly().current_use_case) { |
| 587 case UseCase::COMPOSITOR_GESTURE: | 593 case UseCase::COMPOSITOR_GESTURE: |
| 588 case UseCase::NONE: | 594 case UseCase::NONE: |
| 589 return MainThreadOnly().touchstart_expected_soon; | 595 return MainThreadOnly().touchstart_expected_soon; |
| 590 | 596 |
| 591 case UseCase::MAIN_THREAD_GESTURE: | 597 case UseCase::MAIN_THREAD_GESTURE: |
| 598 case UseCase::MAIN_THREAD_CUSTOM_INPUT_HANDLING: |
| 592 case UseCase::SYNCHRONIZED_GESTURE: | 599 case UseCase::SYNCHRONIZED_GESTURE: |
| 593 return compositor_task_runner_->HasPendingImmediateWork() || | 600 return compositor_task_runner_->HasPendingImmediateWork() || |
| 594 MainThreadOnly().touchstart_expected_soon; | 601 MainThreadOnly().touchstart_expected_soon; |
| 595 | 602 |
| 596 case UseCase::TOUCHSTART: | 603 case UseCase::TOUCHSTART: |
| 597 return true; | 604 return true; |
| 598 | 605 |
| 599 case UseCase::LOADING: | 606 case UseCase::LOADING: |
| 600 return false; | 607 return false; |
| 601 | 608 |
| (...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 732 new_policy.compositor_queue_policy.priority = | 739 new_policy.compositor_queue_policy.priority = |
| 733 main_thread_compositing_is_fast ? TaskQueue::HIGH_PRIORITY | 740 main_thread_compositing_is_fast ? TaskQueue::HIGH_PRIORITY |
| 734 : TaskQueue::NORMAL_PRIORITY; | 741 : TaskQueue::NORMAL_PRIORITY; |
| 735 if (touchstart_expected_soon) { | 742 if (touchstart_expected_soon) { |
| 736 expensive_task_policy = ExpensiveTaskPolicy::BLOCK; | 743 expensive_task_policy = ExpensiveTaskPolicy::BLOCK; |
| 737 } else { | 744 } else { |
| 738 expensive_task_policy = ExpensiveTaskPolicy::THROTTLE; | 745 expensive_task_policy = ExpensiveTaskPolicy::THROTTLE; |
| 739 } | 746 } |
| 740 break; | 747 break; |
| 741 | 748 |
| 742 case UseCase::MAIN_THREAD_GESTURE: | 749 case UseCase::MAIN_THREAD_CUSTOM_INPUT_HANDLING: |
| 743 // In main thread gestures we don't have perfect knowledge about which | 750 // In main thread input handling scenarios we don't have perfect knowledge |
| 744 // things we should be prioritizing, so we don't attempt to block | 751 // about which things we should be prioritizing, so we don't attempt to |
| 745 // expensive tasks because we don't know whether they were integral to the | 752 // block expensive tasks because we don't know whether they were integral |
| 746 // page's functionality or not. | 753 // to the page's functionality or not. |
| 747 new_policy.compositor_queue_policy.priority = | 754 new_policy.compositor_queue_policy.priority = |
| 748 main_thread_compositing_is_fast ? TaskQueue::HIGH_PRIORITY | 755 main_thread_compositing_is_fast ? TaskQueue::HIGH_PRIORITY |
| 749 : TaskQueue::NORMAL_PRIORITY; | 756 : TaskQueue::NORMAL_PRIORITY; |
| 750 break; | 757 break; |
| 751 | 758 |
| 759 case UseCase::MAIN_THREAD_GESTURE: |
| 760 // A main thread gesture is for example a scroll gesture which is handled |
| 761 // by the main thread. Since we know the established gesture type, we can |
| 762 // be a little more aggressive about prioritizing compositing and input |
| 763 // handling over other tasks. |
| 764 new_policy.compositor_queue_policy.priority = TaskQueue::HIGH_PRIORITY; |
| 765 if (touchstart_expected_soon) { |
| 766 expensive_task_policy = ExpensiveTaskPolicy::BLOCK; |
| 767 } else { |
| 768 expensive_task_policy = ExpensiveTaskPolicy::THROTTLE; |
| 769 } |
| 770 break; |
| 771 |
| 752 case UseCase::TOUCHSTART: | 772 case UseCase::TOUCHSTART: |
| 753 new_policy.compositor_queue_policy.priority = TaskQueue::HIGH_PRIORITY; | 773 new_policy.compositor_queue_policy.priority = TaskQueue::HIGH_PRIORITY; |
| 754 new_policy.loading_queue_policy.is_enabled = false; | 774 new_policy.loading_queue_policy.is_enabled = false; |
| 755 new_policy.timer_queue_policy.is_enabled = false; | 775 new_policy.timer_queue_policy.is_enabled = false; |
| 756 // NOTE this is a nop due to the above. | 776 // NOTE this is a nop due to the above. |
| 757 expensive_task_policy = ExpensiveTaskPolicy::BLOCK; | 777 expensive_task_policy = ExpensiveTaskPolicy::BLOCK; |
| 758 break; | 778 break; |
| 759 | 779 |
| 760 case UseCase::NONE: | 780 case UseCase::NONE: |
| 761 // It's only safe to block tasks that if we are expecting a compositor | 781 // It's only safe to block tasks that if we are expecting a compositor |
| (...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 904 *expected_use_case_duration = | 924 *expected_use_case_duration = |
| 905 AnyThread().user_model.TimeLeftInUserGesture(now); | 925 AnyThread().user_model.TimeLeftInUserGesture(now); |
| 906 if (*expected_use_case_duration > base::TimeDelta()) { | 926 if (*expected_use_case_duration > base::TimeDelta()) { |
| 907 // Has a gesture been fully established? | 927 // Has a gesture been fully established? |
| 908 if (AnyThread().awaiting_touch_start_response) { | 928 if (AnyThread().awaiting_touch_start_response) { |
| 909 // No, so arrange for compositor tasks to be run at the highest priority. | 929 // No, so arrange for compositor tasks to be run at the highest priority. |
| 910 return UseCase::TOUCHSTART; | 930 return UseCase::TOUCHSTART; |
| 911 } | 931 } |
| 912 | 932 |
| 913 // Yes a gesture has been established. Based on how the gesture is handled | 933 // Yes a gesture has been established. Based on how the gesture is handled |
| 914 // we need to choose between one of three use cases: | 934 // we need to choose between one of four use cases: |
| 915 // 1. COMPOSITOR_GESTURE where the gesture is processed only on the | 935 // 1. COMPOSITOR_GESTURE where the gesture is processed only on the |
| 916 // compositor thread. | 936 // compositor thread. |
| 917 // 2. MAIN_THREAD_GESTURE where the gesture is processed only on the main | 937 // 2. MAIN_THREAD_GESTURE where the gesture is processed only on the main |
| 918 // thread. | 938 // thread. |
| 919 // 3. SYNCHRONIZED_GESTURE where the gesture is processed on both threads. | 939 // 3. MAIN_THREAD_CUSTOM_INPUT_HANDLING where the main thread processes a |
| 940 // stream of input events and has prevented a default gesture from being |
| 941 // started. |
| 942 // 4. SYNCHRONIZED_GESTURE where the gesture is processed on both threads. |
| 920 // TODO(skyostil): Consider removing in_idle_period_ and | 943 // TODO(skyostil): Consider removing in_idle_period_ and |
| 921 // HadAnIdlePeriodRecently() unless we need them here. | 944 // HadAnIdlePeriodRecently() unless we need them here. |
| 922 if (AnyThread().last_gesture_was_compositor_driven) { | 945 if (AnyThread().last_gesture_was_compositor_driven) { |
| 923 if (AnyThread().begin_main_frame_on_critical_path) { | 946 if (AnyThread().begin_main_frame_on_critical_path) { |
| 924 return UseCase::SYNCHRONIZED_GESTURE; | 947 return UseCase::SYNCHRONIZED_GESTURE; |
| 925 } else { | 948 } else { |
| 926 return UseCase::COMPOSITOR_GESTURE; | 949 return UseCase::COMPOSITOR_GESTURE; |
| 927 } | 950 } |
| 928 } | 951 } |
| 929 return UseCase::MAIN_THREAD_GESTURE; | 952 if (AnyThread().default_gesture_prevented) { |
| 953 return UseCase::MAIN_THREAD_CUSTOM_INPUT_HANDLING; |
| 954 } else { |
| 955 return UseCase::MAIN_THREAD_GESTURE; |
| 956 } |
| 930 } | 957 } |
| 931 | 958 |
| 932 // TODO(alexclarke): return UseCase::LOADING if signals suggest the system is | 959 // TODO(alexclarke): return UseCase::LOADING if signals suggest the system is |
| 933 // in the initial 1s of RAIL loading. | 960 // in the initial 1s of RAIL loading. |
| 934 return UseCase::NONE; | 961 return UseCase::NONE; |
| 935 } | 962 } |
| 936 | 963 |
| 937 base::TimeDelta RendererSchedulerImpl::EstimateLongestJankFreeTaskDuration() | 964 base::TimeDelta RendererSchedulerImpl::EstimateLongestJankFreeTaskDuration() |
| 938 const { | 965 const { |
| 939 switch (MainThreadOnly().current_use_case) { | 966 switch (MainThreadOnly().current_use_case) { |
| 940 case UseCase::TOUCHSTART: | 967 case UseCase::TOUCHSTART: |
| 941 case UseCase::COMPOSITOR_GESTURE: | 968 case UseCase::COMPOSITOR_GESTURE: |
| 942 case UseCase::LOADING: | 969 case UseCase::LOADING: |
| 943 case UseCase::NONE: | 970 case UseCase::NONE: |
| 944 return base::TimeDelta::FromMilliseconds(kRailsResponseTimeMillis); | 971 return base::TimeDelta::FromMilliseconds(kRailsResponseTimeMillis); |
| 945 | 972 |
| 973 case UseCase::MAIN_THREAD_CUSTOM_INPUT_HANDLING: |
| 946 case UseCase::MAIN_THREAD_GESTURE: | 974 case UseCase::MAIN_THREAD_GESTURE: |
| 947 case UseCase::SYNCHRONIZED_GESTURE: | 975 case UseCase::SYNCHRONIZED_GESTURE: |
| 948 return MainThreadOnly().idle_time_estimator.GetExpectedIdleDuration( | 976 return MainThreadOnly().idle_time_estimator.GetExpectedIdleDuration( |
| 949 MainThreadOnly().compositor_frame_interval); | 977 MainThreadOnly().compositor_frame_interval); |
| 950 | 978 |
| 951 default: | 979 default: |
| 952 NOTREACHED(); | 980 NOTREACHED(); |
| 953 return base::TimeDelta::FromMilliseconds(kRailsResponseTimeMillis); | 981 return base::TimeDelta::FromMilliseconds(kRailsResponseTimeMillis); |
| 954 } | 982 } |
| 955 } | 983 } |
| (...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1089 MainThreadOnly().navigation_task_expected_count); | 1117 MainThreadOnly().navigation_task_expected_count); |
| 1090 state->SetDouble("last_idle_period_end_time", | 1118 state->SetDouble("last_idle_period_end_time", |
| 1091 (AnyThread().last_idle_period_end_time - base::TimeTicks()) | 1119 (AnyThread().last_idle_period_end_time - base::TimeTicks()) |
| 1092 .InMillisecondsF()); | 1120 .InMillisecondsF()); |
| 1093 state->SetBoolean("awaiting_touch_start_response", | 1121 state->SetBoolean("awaiting_touch_start_response", |
| 1094 AnyThread().awaiting_touch_start_response); | 1122 AnyThread().awaiting_touch_start_response); |
| 1095 state->SetBoolean("begin_main_frame_on_critical_path", | 1123 state->SetBoolean("begin_main_frame_on_critical_path", |
| 1096 AnyThread().begin_main_frame_on_critical_path); | 1124 AnyThread().begin_main_frame_on_critical_path); |
| 1097 state->SetBoolean("last_gesture_was_compositor_driven", | 1125 state->SetBoolean("last_gesture_was_compositor_driven", |
| 1098 AnyThread().last_gesture_was_compositor_driven); | 1126 AnyThread().last_gesture_was_compositor_driven); |
| 1127 state->SetBoolean("default_gesture_prevented", |
| 1128 AnyThread().default_gesture_prevented); |
| 1099 state->SetDouble("expected_loading_task_duration", | 1129 state->SetDouble("expected_loading_task_duration", |
| 1100 MainThreadOnly() | 1130 MainThreadOnly() |
| 1101 .loading_task_cost_estimator.expected_task_duration() | 1131 .loading_task_cost_estimator.expected_task_duration() |
| 1102 .InMillisecondsF()); | 1132 .InMillisecondsF()); |
| 1103 state->SetDouble("expected_timer_task_duration", | 1133 state->SetDouble("expected_timer_task_duration", |
| 1104 MainThreadOnly() | 1134 MainThreadOnly() |
| 1105 .timer_task_cost_estimator.expected_task_duration() | 1135 .timer_task_cost_estimator.expected_task_duration() |
| 1106 .InMillisecondsF()); | 1136 .InMillisecondsF()); |
| 1107 // TODO(skyostil): Can we somehow trace how accurate these estimates were? | 1137 // TODO(skyostil): Can we somehow trace how accurate these estimates were? |
| 1108 state->SetDouble( | 1138 state->SetDouble( |
| (...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1284 } | 1314 } |
| 1285 MainThreadOnly().have_reported_blocking_intervention_since_navigation = | 1315 MainThreadOnly().have_reported_blocking_intervention_since_navigation = |
| 1286 true; | 1316 true; |
| 1287 BroadcastConsoleWarning( | 1317 BroadcastConsoleWarning( |
| 1288 "Deferred long-running timer task(s) to improve scrolling smoothness. " | 1318 "Deferred long-running timer task(s) to improve scrolling smoothness. " |
| 1289 "See crbug.com/574343."); | 1319 "See crbug.com/574343."); |
| 1290 } | 1320 } |
| 1291 } | 1321 } |
| 1292 | 1322 |
| 1293 } // namespace scheduler | 1323 } // namespace scheduler |
| OLD | NEW |