| 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" |
| 11 #include "base/metrics/histogram_macros.h" | 11 #include "base/metrics/histogram_macros.h" |
| 12 #include "base/trace_event/trace_event.h" | 12 #include "base/trace_event/trace_event.h" |
| 13 #include "base/trace_event/trace_event_argument.h" | 13 #include "base/trace_event/trace_event_argument.h" |
| 14 #include "cc/output/begin_frame_args.h" | 14 #include "cc/output/begin_frame_args.h" |
| 15 #include "platform/scheduler/base/real_time_domain.h" | |
| 16 #include "platform/scheduler/base/task_queue_impl.h" | 15 #include "platform/scheduler/base/task_queue_impl.h" |
| 17 #include "platform/scheduler/base/task_queue_selector.h" | 16 #include "platform/scheduler/base/task_queue_selector.h" |
| 18 #include "platform/scheduler/base/virtual_time_domain.h" | 17 #include "platform/scheduler/base/virtual_time_domain.h" |
| 19 #include "platform/scheduler/child/scheduler_tqm_delegate.h" | 18 #include "platform/scheduler/child/scheduler_tqm_delegate.h" |
| 20 #include "platform/scheduler/renderer/auto_advancing_virtual_time_domain.h" | 19 #include "platform/scheduler/renderer/auto_advancing_virtual_time_domain.h" |
| 21 #include "platform/scheduler/renderer/task_queue_throttler.h" | 20 #include "platform/scheduler/renderer/task_queue_throttler.h" |
| 22 #include "platform/scheduler/renderer/web_view_scheduler_impl.h" | 21 #include "platform/scheduler/renderer/web_view_scheduler_impl.h" |
| 23 #include "platform/scheduler/renderer/webthread_impl_for_renderer_scheduler.h" | 22 #include "platform/scheduler/renderer/webthread_impl_for_renderer_scheduler.h" |
| 24 | 23 |
| 25 namespace blink { | 24 namespace blink { |
| 26 namespace scheduler { | 25 namespace scheduler { |
| 27 namespace { | 26 namespace { |
| 28 // The run time of loading tasks is strongly bimodal. The vast majority are | 27 // The run time of loading tasks is strongly bimodal. The vast majority are |
| 29 // very cheap, but there are usually a handful of very expensive tasks (e.g ~1 | 28 // very cheap, but there are usually a handful of very expensive tasks (e.g ~1 |
| 30 // second on a mobile device) so we take a very pessimistic view when estimating | 29 // second on a mobile device) so we take a very pessimistic view when estimating |
| 31 // the cost of loading tasks. | 30 // the cost of loading tasks. |
| 32 const int kLoadingTaskEstimationSampleCount = 1000; | 31 const int kLoadingTaskEstimationSampleCount = 1000; |
| 33 const double kLoadingTaskEstimationPercentile = 99; | 32 const double kLoadingTaskEstimationPercentile = 99; |
| 34 const int kTimerTaskEstimationSampleCount = 1000; | 33 const int kTimerTaskEstimationSampleCount = 1000; |
| 35 const double kTimerTaskEstimationPercentile = 99; | 34 const double kTimerTaskEstimationPercentile = 99; |
| 36 const int kShortIdlePeriodDurationSampleCount = 10; | 35 const int kShortIdlePeriodDurationSampleCount = 10; |
| 37 const double kShortIdlePeriodDurationPercentile = 50; | 36 const double kShortIdlePeriodDurationPercentile = 50; |
| 38 // Amount of idle time left in a frame (as a ratio of the vsync interval) above | 37 // Amount of idle time left in a frame (as a ratio of the vsync interval) above |
| 39 // which main thread compositing can be considered fast. | 38 // which main thread compositing can be considered fast. |
| 40 const double kFastCompositingIdleTimeThreshold = .2; | 39 const double kFastCompositingIdleTimeThreshold = .2; |
| 41 // We do not throttle anything while audio is played and shortly after that. | |
| 42 constexpr base::TimeDelta kThrottlingDelayAfterAudioIsPlayed = | |
| 43 base::TimeDelta::FromSeconds(5); | |
| 44 constexpr base::TimeDelta kThreadLoadTrackerReportingInterval = | 40 constexpr base::TimeDelta kThreadLoadTrackerReportingInterval = |
| 45 base::TimeDelta::FromMinutes(1); | 41 base::TimeDelta::FromMinutes(1); |
| 46 constexpr base::TimeDelta kThreadLoadTrackerWaitingPeriodBeforeReporting = | 42 constexpr base::TimeDelta kThreadLoadTrackerWaitingPeriodBeforeReporting = |
| 47 base::TimeDelta::FromMinutes(2); | 43 base::TimeDelta::FromMinutes(2); |
| 48 | 44 |
| 49 void ReportForegroundRendererTaskLoad(base::TimeTicks time, double load) { | 45 void ReportForegroundRendererTaskLoad(base::TimeTicks time, double load) { |
| 50 int load_percentage = static_cast<int>(load * 100); | 46 int load_percentage = static_cast<int>(load * 100); |
| 51 UMA_HISTOGRAM_PERCENTAGE("RendererScheduler.ForegroundRendererMainThreadLoad", | 47 UMA_HISTOGRAM_PERCENTAGE("RendererScheduler.ForegroundRendererMainThreadLoad", |
| 52 load_percentage); | 48 load_percentage); |
| 53 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), | 49 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), |
| (...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 182 loading_tasks_seem_expensive(false), | 178 loading_tasks_seem_expensive(false), |
| 183 timer_tasks_seem_expensive(false), | 179 timer_tasks_seem_expensive(false), |
| 184 touchstart_expected_soon(false), | 180 touchstart_expected_soon(false), |
| 185 have_seen_a_begin_main_frame(false), | 181 have_seen_a_begin_main_frame(false), |
| 186 have_reported_blocking_intervention_in_current_policy(false), | 182 have_reported_blocking_intervention_in_current_policy(false), |
| 187 have_reported_blocking_intervention_since_navigation(false), | 183 have_reported_blocking_intervention_since_navigation(false), |
| 188 has_visible_render_widget_with_touch_handler(false), | 184 has_visible_render_widget_with_touch_handler(false), |
| 189 begin_frame_not_expected_soon(false), | 185 begin_frame_not_expected_soon(false), |
| 190 in_idle_period_for_testing(false), | 186 in_idle_period_for_testing(false), |
| 191 use_virtual_time(false), | 187 use_virtual_time(false), |
| 192 is_audio_playing(false), | |
| 193 rail_mode_observer(nullptr) {} | 188 rail_mode_observer(nullptr) {} |
| 194 | 189 |
| 195 RendererSchedulerImpl::MainThreadOnly::~MainThreadOnly() {} | 190 RendererSchedulerImpl::MainThreadOnly::~MainThreadOnly() {} |
| 196 | 191 |
| 197 RendererSchedulerImpl::AnyThread::AnyThread() | 192 RendererSchedulerImpl::AnyThread::AnyThread() |
| 198 : awaiting_touch_start_response(false), | 193 : awaiting_touch_start_response(false), |
| 199 in_idle_period(false), | 194 in_idle_period(false), |
| 200 begin_main_frame_on_critical_path(false), | 195 begin_main_frame_on_critical_path(false), |
| 201 last_gesture_was_compositor_driven(false), | 196 last_gesture_was_compositor_driven(false), |
| 202 default_gesture_prevented(true), | 197 default_gesture_prevented(true), |
| (...skipping 279 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 482 MainThreadOnly().renderer_suspended = false; | 477 MainThreadOnly().renderer_suspended = false; |
| 483 | 478 |
| 484 base::TimeTicks now = tick_clock()->NowTicks(); | 479 base::TimeTicks now = tick_clock()->NowTicks(); |
| 485 MainThreadOnly().foreground_main_thread_load_tracker.Resume(now); | 480 MainThreadOnly().foreground_main_thread_load_tracker.Resume(now); |
| 486 MainThreadOnly().background_main_thread_load_tracker.Pause(now); | 481 MainThreadOnly().background_main_thread_load_tracker.Pause(now); |
| 487 | 482 |
| 488 suspend_timers_when_backgrounded_closure_.Cancel(); | 483 suspend_timers_when_backgrounded_closure_.Cancel(); |
| 489 ResumeTimerQueueWhenForegrounded(); | 484 ResumeTimerQueueWhenForegrounded(); |
| 490 } | 485 } |
| 491 | 486 |
| 492 void RendererSchedulerImpl::OnAudioStateChanged() { | |
| 493 bool is_audio_playing = false; | |
| 494 for (WebViewSchedulerImpl* web_view_scheduler : | |
| 495 MainThreadOnly().web_view_schedulers) { | |
| 496 is_audio_playing = is_audio_playing || web_view_scheduler->IsAudioPlaying(); | |
| 497 } | |
| 498 | |
| 499 if (is_audio_playing == MainThreadOnly().is_audio_playing) | |
| 500 return; | |
| 501 | |
| 502 MainThreadOnly().last_audio_state_change = | |
| 503 helper_.scheduler_tqm_delegate()->NowTicks(); | |
| 504 MainThreadOnly().is_audio_playing = is_audio_playing; | |
| 505 | |
| 506 UpdatePolicy(); | |
| 507 } | |
| 508 | |
| 509 void RendererSchedulerImpl::SuspendRenderer() { | 487 void RendererSchedulerImpl::SuspendRenderer() { |
| 510 helper_.CheckOnValidThread(); | 488 helper_.CheckOnValidThread(); |
| 511 DCHECK(MainThreadOnly().renderer_backgrounded); | 489 DCHECK(MainThreadOnly().renderer_backgrounded); |
| 512 if (helper_.IsShutdown()) | 490 if (helper_.IsShutdown()) |
| 513 return; | 491 return; |
| 514 suspend_timers_when_backgrounded_closure_.Cancel(); | 492 suspend_timers_when_backgrounded_closure_.Cancel(); |
| 515 // TODO(hajimehoshi): We might need to suspend not only timer queue but also | 493 // TODO(hajimehoshi): We might need to suspend not only timer queue but also |
| 516 // e.g. loading tasks or postMessage. | 494 // e.g. loading tasks or postMessage. |
| 517 MainThreadOnly().renderer_suspended = true; | 495 MainThreadOnly().renderer_suspended = true; |
| 518 SuspendTimerQueueWhenBackgrounded(); | 496 SuspendTimerQueueWhenBackgrounded(); |
| (...skipping 310 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 829 // The |new_policy_duration| is the minimum of |expected_use_case_duration| | 807 // The |new_policy_duration| is the minimum of |expected_use_case_duration| |
| 830 // and |touchstart_expected_flag_valid_for_duration| unless one is zero in | 808 // and |touchstart_expected_flag_valid_for_duration| unless one is zero in |
| 831 // which case we choose the other. | 809 // which case we choose the other. |
| 832 base::TimeDelta new_policy_duration = expected_use_case_duration; | 810 base::TimeDelta new_policy_duration = expected_use_case_duration; |
| 833 if (new_policy_duration.is_zero() || | 811 if (new_policy_duration.is_zero() || |
| 834 (touchstart_expected_flag_valid_for_duration > base::TimeDelta() && | 812 (touchstart_expected_flag_valid_for_duration > base::TimeDelta() && |
| 835 new_policy_duration > touchstart_expected_flag_valid_for_duration)) { | 813 new_policy_duration > touchstart_expected_flag_valid_for_duration)) { |
| 836 new_policy_duration = touchstart_expected_flag_valid_for_duration; | 814 new_policy_duration = touchstart_expected_flag_valid_for_duration; |
| 837 } | 815 } |
| 838 | 816 |
| 839 // Do not throttle while audio is playing or for a short period after that | |
| 840 // to make sure that pages playing short audio clips powered by timers | |
| 841 // work. | |
| 842 if (MainThreadOnly().last_audio_state_change && | |
| 843 !MainThreadOnly().is_audio_playing) { | |
| 844 base::TimeTicks audio_will_expire = | |
| 845 MainThreadOnly().last_audio_state_change.value() + | |
| 846 kThrottlingDelayAfterAudioIsPlayed; | |
| 847 | |
| 848 base::TimeDelta audio_will_expire_after = audio_will_expire - now; | |
| 849 | |
| 850 if (audio_will_expire_after > base::TimeDelta()) { | |
| 851 if (new_policy_duration.is_zero()) { | |
| 852 new_policy_duration = audio_will_expire_after; | |
| 853 } else { | |
| 854 new_policy_duration = | |
| 855 std::min(new_policy_duration, audio_will_expire_after); | |
| 856 } | |
| 857 } | |
| 858 } | |
| 859 | |
| 860 if (new_policy_duration > base::TimeDelta()) { | 817 if (new_policy_duration > base::TimeDelta()) { |
| 861 MainThreadOnly().current_policy_expiration_time = now + new_policy_duration; | 818 MainThreadOnly().current_policy_expiration_time = now + new_policy_duration; |
| 862 delayed_update_policy_runner_.SetDeadline(FROM_HERE, new_policy_duration, | 819 delayed_update_policy_runner_.SetDeadline(FROM_HERE, new_policy_duration, |
| 863 now); | 820 now); |
| 864 } else { | 821 } else { |
| 865 MainThreadOnly().current_policy_expiration_time = base::TimeTicks(); | 822 MainThreadOnly().current_policy_expiration_time = base::TimeTicks(); |
| 866 } | 823 } |
| 867 | 824 |
| 868 // Avoid prioritizing main thread compositing (e.g., rAF) if it is extremely | 825 // Avoid prioritizing main thread compositing (e.g., rAF) if it is extremely |
| 869 // slow, because that can cause starvation in other task sources. | 826 // slow, because that can cause starvation in other task sources. |
| (...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1005 } | 962 } |
| 1006 | 963 |
| 1007 if (MainThreadOnly().use_virtual_time) { | 964 if (MainThreadOnly().use_virtual_time) { |
| 1008 new_policy.compositor_queue_policy.time_domain_type = | 965 new_policy.compositor_queue_policy.time_domain_type = |
| 1009 TimeDomainType::VIRTUAL; | 966 TimeDomainType::VIRTUAL; |
| 1010 new_policy.default_queue_policy.time_domain_type = TimeDomainType::VIRTUAL; | 967 new_policy.default_queue_policy.time_domain_type = TimeDomainType::VIRTUAL; |
| 1011 new_policy.loading_queue_policy.time_domain_type = TimeDomainType::VIRTUAL; | 968 new_policy.loading_queue_policy.time_domain_type = TimeDomainType::VIRTUAL; |
| 1012 new_policy.timer_queue_policy.time_domain_type = TimeDomainType::VIRTUAL; | 969 new_policy.timer_queue_policy.time_domain_type = TimeDomainType::VIRTUAL; |
| 1013 } | 970 } |
| 1014 | 971 |
| 1015 new_policy.should_disable_throttling = | |
| 1016 ShouldDisableThrottlingBecauseOfAudio(now) || | |
| 1017 MainThreadOnly().use_virtual_time; | |
| 1018 | |
| 1019 // Tracing is done before the early out check, because it's quite possible we | 972 // Tracing is done before the early out check, because it's quite possible we |
| 1020 // will otherwise miss this information in traces. | 973 // will otherwise miss this information in traces. |
| 1021 CreateTraceEventObjectSnapshotLocked(); | 974 CreateTraceEventObjectSnapshotLocked(); |
| 1022 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), "use_case", | 975 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), "use_case", |
| 1023 use_case); | 976 use_case); |
| 1024 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), "rail_mode", | 977 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), "rail_mode", |
| 1025 new_policy.rail_mode); | 978 new_policy.rail_mode); |
| 1026 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), | 979 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), |
| 1027 "touchstart_expected_soon", | 980 "touchstart_expected_soon", |
| 1028 MainThreadOnly().touchstart_expected_soon); | 981 MainThreadOnly().touchstart_expected_soon); |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1064 // are mostly dispatched on the default queue) need to be preserved. | 1017 // are mostly dispatched on the default queue) need to be preserved. |
| 1065 ApplyTaskQueuePolicy(helper_.DefaultTaskRunner().get(), | 1018 ApplyTaskQueuePolicy(helper_.DefaultTaskRunner().get(), |
| 1066 MainThreadOnly().current_policy.default_queue_policy, | 1019 MainThreadOnly().current_policy.default_queue_policy, |
| 1067 new_policy.default_queue_policy); | 1020 new_policy.default_queue_policy); |
| 1068 if (MainThreadOnly().rail_mode_observer && | 1021 if (MainThreadOnly().rail_mode_observer && |
| 1069 new_policy.rail_mode != MainThreadOnly().current_policy.rail_mode) { | 1022 new_policy.rail_mode != MainThreadOnly().current_policy.rail_mode) { |
| 1070 MainThreadOnly().rail_mode_observer->OnRAILModeChanged( | 1023 MainThreadOnly().rail_mode_observer->OnRAILModeChanged( |
| 1071 new_policy.rail_mode); | 1024 new_policy.rail_mode); |
| 1072 } | 1025 } |
| 1073 | 1026 |
| 1074 if (new_policy.should_disable_throttling != | |
| 1075 MainThreadOnly().current_policy.should_disable_throttling) { | |
| 1076 if (new_policy.should_disable_throttling) { | |
| 1077 task_queue_throttler()->DisableThrottling(); | |
| 1078 } else { | |
| 1079 task_queue_throttler()->EnableThrottling(); | |
| 1080 } | |
| 1081 } | |
| 1082 | |
| 1083 DCHECK(compositor_task_runner_->IsQueueEnabled()); | 1027 DCHECK(compositor_task_runner_->IsQueueEnabled()); |
| 1084 MainThreadOnly().current_policy = new_policy; | 1028 MainThreadOnly().current_policy = new_policy; |
| 1085 } | 1029 } |
| 1086 | 1030 |
| 1087 void RendererSchedulerImpl::ApplyTaskQueuePolicy( | 1031 void RendererSchedulerImpl::ApplyTaskQueuePolicy( |
| 1088 TaskQueue* task_queue, | 1032 TaskQueue* task_queue, |
| 1089 const TaskQueuePolicy& old_task_queue_policy, | 1033 const TaskQueuePolicy& old_task_queue_policy, |
| 1090 const TaskQueuePolicy& new_task_queue_policy) const { | 1034 const TaskQueuePolicy& new_task_queue_policy) const { |
| 1091 if (old_task_queue_policy.is_enabled != new_task_queue_policy.is_enabled) { | 1035 if (old_task_queue_policy.is_enabled != new_task_queue_policy.is_enabled) { |
| 1092 task_queue_throttler_->SetQueueEnabled(task_queue, | 1036 task_queue_throttler_->SetQueueEnabled(task_queue, |
| (...skipping 502 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1595 } | 1539 } |
| 1596 | 1540 |
| 1597 void RendererSchedulerImpl::EnableVirtualTime() { | 1541 void RendererSchedulerImpl::EnableVirtualTime() { |
| 1598 MainThreadOnly().use_virtual_time = true; | 1542 MainThreadOnly().use_virtual_time = true; |
| 1599 | 1543 |
| 1600 // The |unthrottled_task_runners_| are not actively managed by UpdatePolicy(). | 1544 // The |unthrottled_task_runners_| are not actively managed by UpdatePolicy(). |
| 1601 AutoAdvancingVirtualTimeDomain* time_domain = GetVirtualTimeDomain(); | 1545 AutoAdvancingVirtualTimeDomain* time_domain = GetVirtualTimeDomain(); |
| 1602 for (const scoped_refptr<TaskQueue>& task_queue : unthrottled_task_runners_) | 1546 for (const scoped_refptr<TaskQueue>& task_queue : unthrottled_task_runners_) |
| 1603 task_queue->SetTimeDomain(time_domain); | 1547 task_queue->SetTimeDomain(time_domain); |
| 1604 | 1548 |
| 1549 task_queue_throttler_->EnableVirtualTime(); |
| 1550 |
| 1605 ForceUpdatePolicy(); | 1551 ForceUpdatePolicy(); |
| 1606 } | 1552 } |
| 1607 | 1553 |
| 1608 bool RendererSchedulerImpl::ShouldDisableThrottlingBecauseOfAudio( | |
| 1609 base::TimeTicks now) { | |
| 1610 if (!MainThreadOnly().last_audio_state_change) | |
| 1611 return false; | |
| 1612 | |
| 1613 if (MainThreadOnly().is_audio_playing) | |
| 1614 return true; | |
| 1615 | |
| 1616 return MainThreadOnly().last_audio_state_change.value() + | |
| 1617 kThrottlingDelayAfterAudioIsPlayed > | |
| 1618 now; | |
| 1619 } | |
| 1620 | |
| 1621 TimeDomain* RendererSchedulerImpl::GetActiveTimeDomain() { | |
| 1622 if (MainThreadOnly().use_virtual_time) { | |
| 1623 return GetVirtualTimeDomain(); | |
| 1624 } else { | |
| 1625 return real_time_domain(); | |
| 1626 } | |
| 1627 } | |
| 1628 | |
| 1629 // static | 1554 // static |
| 1630 const char* RendererSchedulerImpl::UseCaseToString(UseCase use_case) { | 1555 const char* RendererSchedulerImpl::UseCaseToString(UseCase use_case) { |
| 1631 switch (use_case) { | 1556 switch (use_case) { |
| 1632 case UseCase::NONE: | 1557 case UseCase::NONE: |
| 1633 return "none"; | 1558 return "none"; |
| 1634 case UseCase::COMPOSITOR_GESTURE: | 1559 case UseCase::COMPOSITOR_GESTURE: |
| 1635 return "compositor_gesture"; | 1560 return "compositor_gesture"; |
| 1636 case UseCase::MAIN_THREAD_CUSTOM_INPUT_HANDLING: | 1561 case UseCase::MAIN_THREAD_CUSTOM_INPUT_HANDLING: |
| 1637 return "main_thread_custom_input_handling"; | 1562 return "main_thread_custom_input_handling"; |
| 1638 case UseCase::SYNCHRONIZED_GESTURE: | 1563 case UseCase::SYNCHRONIZED_GESTURE: |
| (...skipping 22 matching lines...) Expand all Loading... |
| 1661 case v8::PERFORMANCE_LOAD: | 1586 case v8::PERFORMANCE_LOAD: |
| 1662 return "load"; | 1587 return "load"; |
| 1663 default: | 1588 default: |
| 1664 NOTREACHED(); | 1589 NOTREACHED(); |
| 1665 return nullptr; | 1590 return nullptr; |
| 1666 } | 1591 } |
| 1667 } | 1592 } |
| 1668 | 1593 |
| 1669 } // namespace scheduler | 1594 } // namespace scheduler |
| 1670 } // namespace blink | 1595 } // namespace blink |
| OLD | NEW |