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 "platform/scheduler/renderer/renderer_scheduler_impl.h" | 5 #include "platform/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 205 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
216 rail_mode_observer(nullptr) {} | 216 rail_mode_observer(nullptr) {} |
217 | 217 |
218 RendererSchedulerImpl::MainThreadOnly::~MainThreadOnly() {} | 218 RendererSchedulerImpl::MainThreadOnly::~MainThreadOnly() {} |
219 | 219 |
220 RendererSchedulerImpl::AnyThread::AnyThread() | 220 RendererSchedulerImpl::AnyThread::AnyThread() |
221 : awaiting_touch_start_response(false), | 221 : awaiting_touch_start_response(false), |
222 in_idle_period(false), | 222 in_idle_period(false), |
223 begin_main_frame_on_critical_path(false), | 223 begin_main_frame_on_critical_path(false), |
224 last_gesture_was_compositor_driven(false), | 224 last_gesture_was_compositor_driven(false), |
225 default_gesture_prevented(true), | 225 default_gesture_prevented(true), |
226 have_seen_touchstart(false) {} | 226 have_seen_touchstart(false), |
| 227 waiting_for_meaningful_paint(false), |
| 228 have_seen_input_since_navigation(false) {} |
227 | 229 |
228 RendererSchedulerImpl::AnyThread::~AnyThread() {} | 230 RendererSchedulerImpl::AnyThread::~AnyThread() {} |
229 | 231 |
230 RendererSchedulerImpl::CompositorThreadOnly::CompositorThreadOnly() | 232 RendererSchedulerImpl::CompositorThreadOnly::CompositorThreadOnly() |
231 : last_input_type(blink::WebInputEvent::Undefined) {} | 233 : last_input_type(blink::WebInputEvent::Undefined) {} |
232 | 234 |
233 RendererSchedulerImpl::CompositorThreadOnly::~CompositorThreadOnly() {} | 235 RendererSchedulerImpl::CompositorThreadOnly::~CompositorThreadOnly() {} |
234 | 236 |
235 void RendererSchedulerImpl::Shutdown() { | 237 void RendererSchedulerImpl::Shutdown() { |
236 base::TimeTicks now = tick_clock()->NowTicks(); | 238 base::TimeTicks now = tick_clock()->NowTicks(); |
(...skipping 401 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
638 "type", static_cast<int>(type), "input_event_state", | 640 "type", static_cast<int>(type), "input_event_state", |
639 InputEventStateToString(input_event_state)); | 641 InputEventStateToString(input_event_state)); |
640 | 642 |
641 base::TimeDelta unused_policy_duration; | 643 base::TimeDelta unused_policy_duration; |
642 UseCase previous_use_case = | 644 UseCase previous_use_case = |
643 ComputeCurrentUseCase(now, &unused_policy_duration); | 645 ComputeCurrentUseCase(now, &unused_policy_duration); |
644 bool was_awaiting_touch_start_response = | 646 bool was_awaiting_touch_start_response = |
645 AnyThread().awaiting_touch_start_response; | 647 AnyThread().awaiting_touch_start_response; |
646 | 648 |
647 AnyThread().user_model.DidStartProcessingInputEvent(type, now); | 649 AnyThread().user_model.DidStartProcessingInputEvent(type, now); |
| 650 AnyThread().have_seen_input_since_navigation = true; |
648 | 651 |
649 if (input_event_state == InputEventState::EVENT_CONSUMED_BY_COMPOSITOR) | 652 if (input_event_state == InputEventState::EVENT_CONSUMED_BY_COMPOSITOR) |
650 AnyThread().user_model.DidFinishProcessingInputEvent(now); | 653 AnyThread().user_model.DidFinishProcessingInputEvent(now); |
651 | 654 |
652 switch (type) { | 655 switch (type) { |
653 case blink::WebInputEvent::TouchStart: | 656 case blink::WebInputEvent::TouchStart: |
654 AnyThread().awaiting_touch_start_response = true; | 657 AnyThread().awaiting_touch_start_response = true; |
655 // This is just a fail-safe to reset the state of | 658 // This is just a fail-safe to reset the state of |
656 // |last_gesture_was_compositor_driven| to the default. We don't know | 659 // |last_gesture_was_compositor_driven| to the default. We don't know |
657 // yet where the gesture will run. | 660 // yet where the gesture will run. |
(...skipping 339 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
997 // driven gesture. | 1000 // driven gesture. |
998 if (touchstart_expected_soon && | 1001 if (touchstart_expected_soon && |
999 AnyThread().last_gesture_was_compositor_driven) { | 1002 AnyThread().last_gesture_was_compositor_driven) { |
1000 new_policy.rail_mode = v8::PERFORMANCE_RESPONSE; | 1003 new_policy.rail_mode = v8::PERFORMANCE_RESPONSE; |
1001 expensive_task_policy = ExpensiveTaskPolicy::BLOCK; | 1004 expensive_task_policy = ExpensiveTaskPolicy::BLOCK; |
1002 } | 1005 } |
1003 break; | 1006 break; |
1004 | 1007 |
1005 case UseCase::LOADING: | 1008 case UseCase::LOADING: |
1006 new_policy.rail_mode = v8::PERFORMANCE_LOAD; | 1009 new_policy.rail_mode = v8::PERFORMANCE_LOAD; |
1007 new_policy.loading_queue_policy.priority = TaskQueue::HIGH_PRIORITY; | 1010 // TODO(skyostil): Experiment with increasing loading and default queue |
1008 new_policy.default_queue_policy.priority = TaskQueue::HIGH_PRIORITY; | 1011 // priorities and throttling rendering frame rate. |
1009 break; | 1012 break; |
1010 | 1013 |
1011 default: | 1014 default: |
1012 NOTREACHED(); | 1015 NOTREACHED(); |
1013 } | 1016 } |
1014 | 1017 |
1015 // TODO(skyostil): Add an idle state for foreground tabs too. | 1018 // TODO(skyostil): Add an idle state for foreground tabs too. |
1016 if (MainThreadOnly().renderer_hidden) | 1019 if (MainThreadOnly().renderer_hidden) |
1017 new_policy.rail_mode = v8::PERFORMANCE_IDLE; | 1020 new_policy.rail_mode = v8::PERFORMANCE_IDLE; |
1018 | 1021 |
(...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1209 return UseCase::COMPOSITOR_GESTURE; | 1212 return UseCase::COMPOSITOR_GESTURE; |
1210 } | 1213 } |
1211 } | 1214 } |
1212 if (AnyThread().default_gesture_prevented) { | 1215 if (AnyThread().default_gesture_prevented) { |
1213 return UseCase::MAIN_THREAD_CUSTOM_INPUT_HANDLING; | 1216 return UseCase::MAIN_THREAD_CUSTOM_INPUT_HANDLING; |
1214 } else { | 1217 } else { |
1215 return UseCase::MAIN_THREAD_GESTURE; | 1218 return UseCase::MAIN_THREAD_GESTURE; |
1216 } | 1219 } |
1217 } | 1220 } |
1218 | 1221 |
1219 // TODO(alexclarke): return UseCase::LOADING if signals suggest the system is | 1222 // Occasionally the meaningful paint fails to be detected, so as a fallback we |
1220 // in the initial 1s of RAIL loading. | 1223 // treat the presence of input as an indirect signal that there is meaningful |
| 1224 // content on the page. |
| 1225 if (AnyThread().waiting_for_meaningful_paint && |
| 1226 !AnyThread().have_seen_input_since_navigation) { |
| 1227 return UseCase::LOADING; |
| 1228 } |
1221 return UseCase::NONE; | 1229 return UseCase::NONE; |
1222 } | 1230 } |
1223 | 1231 |
1224 base::TimeDelta RendererSchedulerImpl::EstimateLongestJankFreeTaskDuration() | 1232 base::TimeDelta RendererSchedulerImpl::EstimateLongestJankFreeTaskDuration() |
1225 const { | 1233 const { |
1226 switch (MainThreadOnly().current_use_case) { | 1234 switch (MainThreadOnly().current_use_case) { |
1227 case UseCase::TOUCHSTART: | 1235 case UseCase::TOUCHSTART: |
1228 case UseCase::COMPOSITOR_GESTURE: | 1236 case UseCase::COMPOSITOR_GESTURE: |
1229 case UseCase::LOADING: | 1237 case UseCase::LOADING: |
1230 case UseCase::NONE: | 1238 case UseCase::NONE: |
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1355 state->SetBoolean("begin_frame_not_expected_soon", | 1363 state->SetBoolean("begin_frame_not_expected_soon", |
1356 MainThreadOnly().begin_frame_not_expected_soon); | 1364 MainThreadOnly().begin_frame_not_expected_soon); |
1357 state->SetBoolean("touchstart_expected_soon", | 1365 state->SetBoolean("touchstart_expected_soon", |
1358 MainThreadOnly().touchstart_expected_soon); | 1366 MainThreadOnly().touchstart_expected_soon); |
1359 state->SetString("idle_period_state", | 1367 state->SetString("idle_period_state", |
1360 IdleHelper::IdlePeriodStateToString( | 1368 IdleHelper::IdlePeriodStateToString( |
1361 idle_helper_.SchedulerIdlePeriodState())); | 1369 idle_helper_.SchedulerIdlePeriodState())); |
1362 state->SetBoolean("renderer_hidden", MainThreadOnly().renderer_hidden); | 1370 state->SetBoolean("renderer_hidden", MainThreadOnly().renderer_hidden); |
1363 state->SetBoolean("have_seen_a_begin_main_frame", | 1371 state->SetBoolean("have_seen_a_begin_main_frame", |
1364 MainThreadOnly().have_seen_a_begin_main_frame); | 1372 MainThreadOnly().have_seen_a_begin_main_frame); |
| 1373 state->SetBoolean("waiting_for_meaningful_paint", |
| 1374 AnyThread().waiting_for_meaningful_paint); |
| 1375 state->SetBoolean("have_seen_input_since_navigation", |
| 1376 AnyThread().have_seen_input_since_navigation); |
1365 state->SetBoolean( | 1377 state->SetBoolean( |
1366 "have_reported_blocking_intervention_in_current_policy", | 1378 "have_reported_blocking_intervention_in_current_policy", |
1367 MainThreadOnly().have_reported_blocking_intervention_in_current_policy); | 1379 MainThreadOnly().have_reported_blocking_intervention_in_current_policy); |
1368 state->SetBoolean( | 1380 state->SetBoolean( |
1369 "have_reported_blocking_intervention_since_navigation", | 1381 "have_reported_blocking_intervention_since_navigation", |
1370 MainThreadOnly().have_reported_blocking_intervention_since_navigation); | 1382 MainThreadOnly().have_reported_blocking_intervention_since_navigation); |
1371 state->SetBoolean("renderer_backgrounded", | 1383 state->SetBoolean("renderer_backgrounded", |
1372 MainThreadOnly().renderer_backgrounded); | 1384 MainThreadOnly().renderer_backgrounded); |
1373 state->SetBoolean("timer_queue_suspended_when_backgrounded", | 1385 state->SetBoolean("timer_queue_suspended_when_backgrounded", |
1374 MainThreadOnly().timer_queue_suspended_when_backgrounded); | 1386 MainThreadOnly().timer_queue_suspended_when_backgrounded); |
1375 state->SetInteger("timer_queue_suspend_count", | 1387 state->SetInteger("timer_queue_suspend_count", |
1376 MainThreadOnly().timer_queue_suspend_count); | 1388 MainThreadOnly().timer_queue_suspend_count); |
1377 state->SetDouble("now", (optional_now - base::TimeTicks()).InMillisecondsF()); | 1389 state->SetDouble("now", (optional_now - base::TimeTicks()).InMillisecondsF()); |
1378 state->SetDouble( | 1390 state->SetDouble( |
1379 "rails_loading_priority_deadline", | |
1380 (AnyThread().rails_loading_priority_deadline - base::TimeTicks()) | |
1381 .InMillisecondsF()); | |
1382 state->SetDouble( | |
1383 "fling_compositor_escalation_deadline", | 1391 "fling_compositor_escalation_deadline", |
1384 (AnyThread().fling_compositor_escalation_deadline - base::TimeTicks()) | 1392 (AnyThread().fling_compositor_escalation_deadline - base::TimeTicks()) |
1385 .InMillisecondsF()); | 1393 .InMillisecondsF()); |
1386 state->SetInteger("navigation_task_expected_count", | 1394 state->SetInteger("navigation_task_expected_count", |
1387 MainThreadOnly().navigation_task_expected_count); | 1395 MainThreadOnly().navigation_task_expected_count); |
1388 state->SetDouble("last_idle_period_end_time", | 1396 state->SetDouble("last_idle_period_end_time", |
1389 (AnyThread().last_idle_period_end_time - base::TimeTicks()) | 1397 (AnyThread().last_idle_period_end_time - base::TimeTicks()) |
1390 .InMillisecondsF()); | 1398 .InMillisecondsF()); |
1391 state->SetBoolean("awaiting_touch_start_response", | 1399 state->SetBoolean("awaiting_touch_start_response", |
1392 AnyThread().awaiting_touch_start_response); | 1400 AnyThread().awaiting_touch_start_response); |
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1507 MainThreadOnly().navigation_task_expected_count > 0) { | 1515 MainThreadOnly().navigation_task_expected_count > 0) { |
1508 MainThreadOnly().navigation_task_expected_count--; | 1516 MainThreadOnly().navigation_task_expected_count--; |
1509 UpdatePolicy(); | 1517 UpdatePolicy(); |
1510 } | 1518 } |
1511 } | 1519 } |
1512 | 1520 |
1513 void RendererSchedulerImpl::OnNavigationStarted() { | 1521 void RendererSchedulerImpl::OnNavigationStarted() { |
1514 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), | 1522 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), |
1515 "RendererSchedulerImpl::OnNavigationStarted"); | 1523 "RendererSchedulerImpl::OnNavigationStarted"); |
1516 base::AutoLock lock(any_thread_lock_); | 1524 base::AutoLock lock(any_thread_lock_); |
1517 AnyThread().rails_loading_priority_deadline = | |
1518 helper_.scheduler_tqm_delegate()->NowTicks() + | |
1519 base::TimeDelta::FromMilliseconds( | |
1520 kRailsInitialLoadingPrioritizationMillis); | |
1521 ResetForNavigationLocked(); | 1525 ResetForNavigationLocked(); |
1522 } | 1526 } |
1523 | 1527 |
| 1528 void RendererSchedulerImpl::OnFirstMeaningfulPaint() { |
| 1529 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), |
| 1530 "RendererSchedulerImpl::OnFirstMeaningfulPaint"); |
| 1531 base::AutoLock lock(any_thread_lock_); |
| 1532 AnyThread().waiting_for_meaningful_paint = false; |
| 1533 UpdatePolicyLocked(UpdateType::MAY_EARLY_OUT_IF_POLICY_UNCHANGED); |
| 1534 } |
| 1535 |
1524 void RendererSchedulerImpl::SuspendTimerQueueWhenBackgrounded() { | 1536 void RendererSchedulerImpl::SuspendTimerQueueWhenBackgrounded() { |
1525 DCHECK(MainThreadOnly().renderer_backgrounded); | 1537 DCHECK(MainThreadOnly().renderer_backgrounded); |
1526 if (MainThreadOnly().timer_queue_suspended_when_backgrounded) | 1538 if (MainThreadOnly().timer_queue_suspended_when_backgrounded) |
1527 return; | 1539 return; |
1528 | 1540 |
1529 MainThreadOnly().timer_queue_suspended_when_backgrounded = true; | 1541 MainThreadOnly().timer_queue_suspended_when_backgrounded = true; |
1530 ForceUpdatePolicy(); | 1542 ForceUpdatePolicy(); |
1531 } | 1543 } |
1532 | 1544 |
1533 void RendererSchedulerImpl::ResumeTimerQueueWhenForegroundedOrResumed() { | 1545 void RendererSchedulerImpl::ResumeTimerQueueWhenForegroundedOrResumed() { |
1534 DCHECK(!MainThreadOnly().renderer_backgrounded || | 1546 DCHECK(!MainThreadOnly().renderer_backgrounded || |
1535 (MainThreadOnly().renderer_backgrounded && | 1547 (MainThreadOnly().renderer_backgrounded && |
1536 !MainThreadOnly().renderer_suspended)); | 1548 !MainThreadOnly().renderer_suspended)); |
1537 if (!MainThreadOnly().timer_queue_suspended_when_backgrounded) | 1549 if (!MainThreadOnly().timer_queue_suspended_when_backgrounded) |
1538 return; | 1550 return; |
1539 | 1551 |
1540 MainThreadOnly().timer_queue_suspended_when_backgrounded = false; | 1552 MainThreadOnly().timer_queue_suspended_when_backgrounded = false; |
1541 ForceUpdatePolicy(); | 1553 ForceUpdatePolicy(); |
1542 } | 1554 } |
1543 | 1555 |
1544 void RendererSchedulerImpl::ResetForNavigationLocked() { | 1556 void RendererSchedulerImpl::ResetForNavigationLocked() { |
1545 helper_.CheckOnValidThread(); | 1557 helper_.CheckOnValidThread(); |
1546 any_thread_lock_.AssertAcquired(); | 1558 any_thread_lock_.AssertAcquired(); |
1547 AnyThread().user_model.Reset(helper_.scheduler_tqm_delegate()->NowTicks()); | 1559 AnyThread().user_model.Reset(helper_.scheduler_tqm_delegate()->NowTicks()); |
1548 AnyThread().have_seen_touchstart = false; | 1560 AnyThread().have_seen_touchstart = false; |
| 1561 AnyThread().waiting_for_meaningful_paint = true; |
| 1562 AnyThread().have_seen_input_since_navigation = false; |
1549 MainThreadOnly().loading_task_cost_estimator.Clear(); | 1563 MainThreadOnly().loading_task_cost_estimator.Clear(); |
1550 MainThreadOnly().timer_task_cost_estimator.Clear(); | 1564 MainThreadOnly().timer_task_cost_estimator.Clear(); |
1551 MainThreadOnly().idle_time_estimator.Clear(); | 1565 MainThreadOnly().idle_time_estimator.Clear(); |
1552 MainThreadOnly().have_seen_a_begin_main_frame = false; | 1566 MainThreadOnly().have_seen_a_begin_main_frame = false; |
1553 MainThreadOnly().have_reported_blocking_intervention_since_navigation = false; | 1567 MainThreadOnly().have_reported_blocking_intervention_since_navigation = false; |
1554 for (WebViewSchedulerImpl* web_view_scheduler : | 1568 for (WebViewSchedulerImpl* web_view_scheduler : |
1555 MainThreadOnly().web_view_schedulers) { | 1569 MainThreadOnly().web_view_schedulers) { |
1556 web_view_scheduler->OnNavigation(); | 1570 web_view_scheduler->OnNavigation(); |
1557 } | 1571 } |
1558 UpdatePolicyLocked(UpdateType::MAY_EARLY_OUT_IF_POLICY_UNCHANGED); | 1572 UpdatePolicyLocked(UpdateType::MAY_EARLY_OUT_IF_POLICY_UNCHANGED); |
(...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1794 case TimeDomainType::VIRTUAL: | 1808 case TimeDomainType::VIRTUAL: |
1795 return "virtual"; | 1809 return "virtual"; |
1796 default: | 1810 default: |
1797 NOTREACHED(); | 1811 NOTREACHED(); |
1798 return nullptr; | 1812 return nullptr; |
1799 } | 1813 } |
1800 } | 1814 } |
1801 | 1815 |
1802 } // namespace scheduler | 1816 } // namespace scheduler |
1803 } // namespace blink | 1817 } // namespace blink |
OLD | NEW |