| 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 #ifndef COMPONENTS_SCHEDULER_RENDERER_RENDERER_SCHEDULER_IMPL_H_ | 5 #ifndef COMPONENTS_SCHEDULER_RENDERER_RENDERER_SCHEDULER_IMPL_H_ |
| 6 #define COMPONENTS_SCHEDULER_RENDERER_RENDERER_SCHEDULER_IMPL_H_ | 6 #define COMPONENTS_SCHEDULER_RENDERER_RENDERER_SCHEDULER_IMPL_H_ |
| 7 | 7 |
| 8 #include "base/atomicops.h" | 8 #include "base/atomicops.h" |
| 9 #include "base/synchronization/lock.h" | 9 #include "base/synchronization/lock.h" |
| 10 #include "components/scheduler/child/idle_helper.h" | 10 #include "components/scheduler/child/idle_helper.h" |
| 11 #include "components/scheduler/child/pollable_thread_safe_flag.h" | 11 #include "components/scheduler/child/pollable_thread_safe_flag.h" |
| 12 #include "components/scheduler/child/scheduler_helper.h" | 12 #include "components/scheduler/child/scheduler_helper.h" |
| 13 #include "components/scheduler/renderer/deadline_task_runner.h" | 13 #include "components/scheduler/renderer/deadline_task_runner.h" |
| 14 #include "components/scheduler/renderer/renderer_scheduler.h" | 14 #include "components/scheduler/renderer/renderer_scheduler.h" |
| 15 #include "components/scheduler/renderer/task_cost_estimator.h" | 15 #include "components/scheduler/renderer/task_cost_estimator.h" |
| 16 #include "components/scheduler/renderer/user_model.h" |
| 16 #include "components/scheduler/scheduler_export.h" | 17 #include "components/scheduler/scheduler_export.h" |
| 17 | 18 |
| 18 namespace base { | 19 namespace base { |
| 19 namespace trace_event { | 20 namespace trace_event { |
| 20 class ConvertableToTraceFormat; | 21 class ConvertableToTraceFormat; |
| 21 } | 22 } |
| 22 } | 23 } |
| 23 | 24 |
| 24 namespace scheduler { | 25 namespace scheduler { |
| 25 | 26 |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 61 void ResumeTimerQueue() override; | 62 void ResumeTimerQueue() override; |
| 62 void SetTimerQueueSuspensionWhenBackgroundedEnabled(bool enabled) override; | 63 void SetTimerQueueSuspensionWhenBackgroundedEnabled(bool enabled) override; |
| 63 | 64 |
| 64 SchedulerHelper* GetSchedulerHelperForTesting(); | 65 SchedulerHelper* GetSchedulerHelperForTesting(); |
| 65 base::TimeTicks CurrentIdleTaskDeadlineForTesting() const; | 66 base::TimeTicks CurrentIdleTaskDeadlineForTesting() const; |
| 66 | 67 |
| 67 private: | 68 private: |
| 68 friend class RendererSchedulerImplTest; | 69 friend class RendererSchedulerImplTest; |
| 69 friend class RendererSchedulerImplForTest; | 70 friend class RendererSchedulerImplForTest; |
| 70 | 71 |
| 71 // Keep RendererSchedulerImpl::PolicyToString in sync with this enum. | 72 struct Policy { |
| 72 enum class Policy { | 73 Policy(); |
| 73 NORMAL, | 74 |
| 74 COMPOSITOR_PRIORITY, | 75 TaskQueue::QueuePriority compositor_queue_priority; |
| 75 COMPOSITOR_CRITICAL_PATH_PRIORITY, | 76 TaskQueue::QueuePriority loading_queue_priority; |
| 76 TOUCHSTART_PRIORITY, | 77 TaskQueue::QueuePriority timer_queue_priority; |
| 77 LOADING_PRIORITY, | 78 TaskQueue::QueuePriority default_queue_priority; |
| 78 // Must be the last entry. | 79 |
| 79 POLICY_COUNT, | 80 bool operator==(const Policy& other) const { |
| 80 FIRST_POLICY = NORMAL, | 81 return compositor_queue_priority == other.compositor_queue_priority && |
| 82 loading_queue_priority == other.loading_queue_priority && |
| 83 timer_queue_priority == other.timer_queue_priority && |
| 84 default_queue_priority == other.default_queue_priority; |
| 85 } |
| 81 }; | 86 }; |
| 82 | 87 |
| 83 class PollableNeedsUpdateFlag { | 88 class PollableNeedsUpdateFlag { |
| 84 public: | 89 public: |
| 85 PollableNeedsUpdateFlag(base::Lock* write_lock); | 90 PollableNeedsUpdateFlag(base::Lock* write_lock); |
| 86 ~PollableNeedsUpdateFlag(); | 91 ~PollableNeedsUpdateFlag(); |
| 87 | 92 |
| 88 // Set the flag. May only be called if |write_lock| is held. | 93 // Set the flag. May only be called if |write_lock| is held. |
| 89 void SetWhileLocked(bool value); | 94 void SetWhileLocked(bool value); |
| 90 | 95 |
| (...skipping 15 matching lines...) Expand all Loading... |
| 106 void OnIdlePeriodStarted() override; | 111 void OnIdlePeriodStarted() override; |
| 107 void OnIdlePeriodEnded() override; | 112 void OnIdlePeriodEnded() override; |
| 108 | 113 |
| 109 void EndIdlePeriod(); | 114 void EndIdlePeriod(); |
| 110 | 115 |
| 111 // Returns the serialized scheduler state for tracing. | 116 // Returns the serialized scheduler state for tracing. |
| 112 scoped_refptr<base::trace_event::ConvertableToTraceFormat> AsValue( | 117 scoped_refptr<base::trace_event::ConvertableToTraceFormat> AsValue( |
| 113 base::TimeTicks optional_now) const; | 118 base::TimeTicks optional_now) const; |
| 114 scoped_refptr<base::trace_event::ConvertableToTraceFormat> AsValueLocked( | 119 scoped_refptr<base::trace_event::ConvertableToTraceFormat> AsValueLocked( |
| 115 base::TimeTicks optional_now) const; | 120 base::TimeTicks optional_now) const; |
| 116 static const char* PolicyToString(Policy policy); | |
| 117 | 121 |
| 118 static bool ShouldPrioritizeInputEvent( | 122 static bool ShouldPrioritizeInputEvent( |
| 119 const blink::WebInputEvent& web_input_event); | 123 const blink::WebInputEvent& web_input_event); |
| 120 | 124 |
| 121 // The time we should stay in a priority-escalated mode after an input event. | |
| 122 static const int kPriorityEscalationAfterInputMillis = 100; | |
| 123 | |
| 124 // The amount of time which idle periods can continue being scheduled when the | 125 // The amount of time which idle periods can continue being scheduled when the |
| 125 // renderer has been hidden, before going to sleep for good. | 126 // renderer has been hidden, before going to sleep for good. |
| 126 static const int kEndIdleWhenHiddenDelayMillis = 10000; | 127 static const int kEndIdleWhenHiddenDelayMillis = 10000; |
| 127 | 128 |
| 128 // The amount of time for which loading tasks will be prioritized over | 129 // The amount of time for which loading tasks will be prioritized over |
| 129 // other tasks during the initial page load. | 130 // other tasks during the initial page load. |
| 130 static const int kRailsInitialLoadingPrioritizationMillis = 1000; | 131 static const int kRailsInitialLoadingPrioritizationMillis = 1000; |
| 131 | 132 |
| 132 // For the purposes of deciding whether or not it's safe to turn timers and | 133 // For the purposes of deciding whether or not it's safe to turn timers and |
| 133 // loading tasks on only in idle periods, we regard the system as being as | 134 // loading tasks on only in idle periods, we regard the system as being as |
| 134 // being "idle period" starved if there hasn't been an idle period in the last | 135 // being "idle period" starved if there hasn't been an idle period in the last |
| 135 // 10 seconds. This was chosen to be long enough to cover most anticipated | 136 // 10 seconds. This was chosen to be long enough to cover most anticipated |
| 136 // user gestures. | 137 // user gestures. |
| 137 static const int kIdlePeriodStarvationThresholdMillis = 10000; | 138 static const int kIdlePeriodStarvationThresholdMillis = 10000; |
| 138 | 139 |
| 139 // The amount of time to wait before suspending shared timers after the | 140 // The amount of time to wait before suspending shared timers after the |
| 140 // renderer has been backgrounded. This is use donly if background suspension | 141 // renderer has been backgrounded. This is used only if background suspension |
| 141 // of shared timers is enabled. | 142 // of shared timers is enabled. |
| 142 static const int kSuspendTimersWhenBackgroundedDelayMillis = 5 * 60 * 1000; | 143 static const int kSuspendTimersWhenBackgroundedDelayMillis = 5 * 60 * 1000; |
| 143 | 144 |
| 144 // Schedules an immediate PolicyUpdate, if there isn't one already pending and | 145 // Schedules an immediate PolicyUpdate, if there isn't one already pending and |
| 145 // sets |policy_may_need_update_|. Note |any_thread_lock_| must be | 146 // sets |policy_may_need_update_|. Note |any_thread_lock_| must be |
| 146 // locked. | 147 // locked. |
| 147 void EnsureUrgentPolicyUpdatePostedOnMainThread( | 148 void EnsureUrgentPolicyUpdatePostedOnMainThread( |
| 148 const tracked_objects::Location& from_here); | 149 const tracked_objects::Location& from_here); |
| 149 | 150 |
| 150 // Update the policy if a new signal has arrived. Must be called from the main | 151 // Update the policy if a new signal has arrived. Must be called from the main |
| 151 // thread. | 152 // thread. |
| 152 void MaybeUpdatePolicy(); | 153 void MaybeUpdatePolicy(); |
| 153 | 154 |
| 154 // Locks |any_thread_lock_| and updates the scheduler policy. May early | 155 // Locks |any_thread_lock_| and updates the scheduler policy. May early |
| 155 // out if the policy is unchanged. Must be called from the main thread. | 156 // out if the policy is unchanged. Must be called from the main thread. |
| 156 void UpdatePolicy(); | 157 void UpdatePolicy(); |
| 157 | 158 |
| 158 // Like UpdatePolicy, except it doesn't early out. | 159 // Like UpdatePolicy, except it doesn't early out. |
| 159 void ForceUpdatePolicy(); | 160 void ForceUpdatePolicy(); |
| 160 | 161 |
| 161 enum class UpdateType { | 162 enum class UpdateType { |
| 162 MAY_EARLY_OUT_IF_POLICY_UNCHANGED, | 163 MAY_EARLY_OUT_IF_POLICY_UNCHANGED, |
| 163 FORCE_UPDATE, | 164 FORCE_UPDATE, |
| 164 }; | 165 }; |
| 165 | 166 |
| 166 // The implelemtation of UpdatePolicy & ForceUpdatePolicy. It is allowed to | 167 // The implelemtation of UpdatePolicy & ForceUpdatePolicy. It is allowed to |
| 167 // early out if |update_type| is MAY_EARLY_OUT_IF_POLICY_UNCHANGED. | 168 // early out if |update_type| is MAY_EARLY_OUT_IF_POLICY_UNCHANGED. |
| 168 virtual void UpdatePolicyLocked(UpdateType update_type); | 169 virtual void UpdatePolicyLocked(UpdateType update_type); |
| 169 | 170 |
| 170 // Returns the amount of time left in the current input escalated priority | 171 // Helper for computing the use case. |expected_usecase_duration| will be |
| 171 // policy. Can be called from any thread. | 172 // filled with the amount of time after which the use case should be updated |
| 172 base::TimeDelta TimeLeftInInputEscalatedPolicy(base::TimeTicks now) const; | 173 // again. If the duration is zero, a new use case update should not be |
| 174 // scheduled. Must be called with |any_thread_lock_| held. Can be called from |
| 175 // any thread. |
| 176 UseCase ComputeCurrentUseCase( |
| 177 base::TimeTicks now, |
| 178 base::TimeDelta* expected_use_case_duration) const; |
| 173 | 179 |
| 174 // Helper for computing the new policy. |new_policy_duration| will be filled | 180 // Works out if a gesture appears to be in progress based on the current |
| 175 // with the amount of time after which the policy should be updated again. If | 181 // input signals. Can be called from any thread. |
| 176 // the duration is zero, a new policy update will not be scheduled. Must be | 182 bool InputSignalsSuggestGestureInProgress(base::TimeTicks now) const; |
| 177 // called with |any_thread_lock_| held. Can be called from any thread. | |
| 178 Policy ComputeNewPolicy(base::TimeTicks now, | |
| 179 base::TimeDelta* new_policy_duration) const; | |
| 180 | |
| 181 // Works out if compositor tasks would be prioritized based on the current | |
| 182 // input signals. Can be called from any thread. | |
| 183 bool InputSignalsSuggestCompositorPriority(base::TimeTicks now) const; | |
| 184 | 183 |
| 185 // An input event of some sort happened, the policy may need updating. | 184 // An input event of some sort happened, the policy may need updating. |
| 186 void UpdateForInputEventOnCompositorThread(blink::WebInputEvent::Type type, | 185 void UpdateForInputEventOnCompositorThread(blink::WebInputEvent::Type type, |
| 187 InputEventState input_event_state); | 186 InputEventState input_event_state); |
| 188 | 187 |
| 189 // Returns true if there has been at least one idle period in the last | 188 // Returns true if there has been at least one idle period in the last |
| 190 // |kIdlePeriodStarvationThresholdMillis|. | 189 // |kIdlePeriodStarvationThresholdMillis|. |
| 191 bool HadAnIdlePeriodRecently(base::TimeTicks now) const; | 190 bool HadAnIdlePeriodRecently(base::TimeTicks now) const; |
| 192 | 191 |
| 193 // Helpers for safely suspending/resuming the timer queue after a | 192 // Helpers for safely suspending/resuming the timer queue after a |
| 194 // background/foreground signal. | 193 // background/foreground signal. |
| 195 void SuspendTimerQueueWhenBackgrounded(); | 194 void SuspendTimerQueueWhenBackgrounded(); |
| 196 void ResumeTimerQueueWhenForegrounded(); | 195 void ResumeTimerQueueWhenForegrounded(); |
| 197 | 196 |
| 197 // The task cost estimators and the UserModel need to be reset upon page |
| 198 // nagigation. This function does that. Must be called from the main thread. |
| 199 void ResetForNavigationLocked(); |
| 200 |
| 198 SchedulerHelper helper_; | 201 SchedulerHelper helper_; |
| 199 IdleHelper idle_helper_; | 202 IdleHelper idle_helper_; |
| 200 | 203 |
| 201 const scoped_refptr<TaskQueue> control_task_runner_; | 204 const scoped_refptr<TaskQueue> control_task_runner_; |
| 202 const scoped_refptr<TaskQueue> compositor_task_runner_; | 205 const scoped_refptr<TaskQueue> compositor_task_runner_; |
| 203 const scoped_refptr<TaskQueue> loading_task_runner_; | 206 const scoped_refptr<TaskQueue> loading_task_runner_; |
| 204 const scoped_refptr<TaskQueue> timer_task_runner_; | 207 const scoped_refptr<TaskQueue> timer_task_runner_; |
| 205 | 208 |
| 206 base::Closure update_policy_closure_; | 209 base::Closure update_policy_closure_; |
| 207 DeadlineTaskRunner delayed_update_policy_runner_; | 210 DeadlineTaskRunner delayed_update_policy_runner_; |
| 208 CancelableClosureHolder end_renderer_hidden_idle_period_closure_; | 211 CancelableClosureHolder end_renderer_hidden_idle_period_closure_; |
| 209 CancelableClosureHolder suspend_timers_when_backgrounded_closure_; | 212 CancelableClosureHolder suspend_timers_when_backgrounded_closure_; |
| 210 | 213 |
| 211 // We have decided to improve thread safety at the cost of some boilerplate | 214 // We have decided to improve thread safety at the cost of some boilerplate |
| 212 // (the accessors) for the following data members. | 215 // (the accessors) for the following data members. |
| 213 | 216 |
| 214 struct MainThreadOnly { | 217 struct MainThreadOnly { |
| 215 MainThreadOnly(); | 218 MainThreadOnly(); |
| 216 ~MainThreadOnly(); | 219 ~MainThreadOnly(); |
| 217 | 220 |
| 218 TaskCostEstimator timer_task_cost_estimator_; | 221 TaskCostEstimator loading_task_cost_estimator; |
| 219 cc::RollingTimeDeltaHistory short_idle_period_duration_; | 222 TaskCostEstimator timer_task_cost_estimator; |
| 220 Policy current_policy_; | 223 cc::RollingTimeDeltaHistory short_idle_period_duration; |
| 221 base::TimeTicks current_policy_expiration_time_; | 224 UseCase current_use_case; |
| 222 base::TimeTicks estimated_next_frame_begin_; | 225 Policy current_policy; |
| 223 base::TimeDelta expected_short_idle_period_duration_; | 226 base::TimeTicks current_policy_expiration_time; |
| 224 int timer_queue_suspend_count_; // TIMER_TASK_QUEUE suspended if non-zero. | 227 base::TimeTicks estimated_next_frame_begin; |
| 225 bool renderer_hidden_; | 228 base::TimeDelta expected_short_idle_period_duration; |
| 226 bool renderer_backgrounded_; | 229 int timer_queue_suspend_count; // TIMER_TASK_QUEUE suspended if non-zero. |
| 227 bool timer_queue_suspension_when_backgrounded_enabled_; | 230 bool renderer_hidden; |
| 228 bool timer_queue_suspended_when_backgrounded_; | 231 bool renderer_backgrounded; |
| 229 bool was_shutdown_; | 232 bool timer_queue_suspension_when_backgrounded_enabled; |
| 233 bool timer_queue_suspended_when_backgrounded; |
| 234 bool was_shutdown; |
| 235 bool loading_tasks_seem_expensive; |
| 236 bool timer_tasks_seem_expensive; |
| 237 bool touchstart_expected_soon; |
| 238 bool have_seen_a_begin_main_frame; |
| 230 }; | 239 }; |
| 231 | 240 |
| 232 struct AnyThread { | 241 struct AnyThread { |
| 233 AnyThread(); | 242 AnyThread(); |
| 234 | 243 |
| 235 base::TimeTicks last_input_signal_time_; | 244 base::TimeTicks last_idle_period_end_time; |
| 236 base::TimeTicks last_idle_period_end_time_; | 245 base::TimeTicks rails_loading_priority_deadline; |
| 237 base::TimeTicks rails_loading_priority_deadline_; | 246 UserModel user_model; |
| 238 int pending_main_thread_input_event_count_; | 247 bool awaiting_touch_start_response; |
| 239 bool awaiting_touch_start_response_; | 248 bool in_idle_period; |
| 240 bool in_idle_period_; | 249 bool begin_main_frame_on_critical_path; |
| 241 bool begin_main_frame_on_critical_path_; | |
| 242 bool timer_tasks_seem_expensive_; | |
| 243 }; | 250 }; |
| 244 | 251 |
| 245 struct CompositorThreadOnly { | 252 struct CompositorThreadOnly { |
| 246 CompositorThreadOnly(); | 253 CompositorThreadOnly(); |
| 247 ~CompositorThreadOnly(); | 254 ~CompositorThreadOnly(); |
| 248 | 255 |
| 249 blink::WebInputEvent::Type last_input_type_; | 256 blink::WebInputEvent::Type last_input_type; |
| 250 scoped_ptr<base::ThreadChecker> compositor_thread_checker_; | 257 scoped_ptr<base::ThreadChecker> compositor_thread_checker; |
| 251 | 258 |
| 252 void CheckOnValidThread() { | 259 void CheckOnValidThread() { |
| 253 #if DCHECK_IS_ON() | 260 #if DCHECK_IS_ON() |
| 254 // We don't actually care which thread this called from, just so long as | 261 // We don't actually care which thread this called from, just so long as |
| 255 // its consistent. | 262 // its consistent. |
| 256 if (!compositor_thread_checker_) | 263 if (!compositor_thread_checker) |
| 257 compositor_thread_checker_.reset(new base::ThreadChecker()); | 264 compositor_thread_checker.reset(new base::ThreadChecker()); |
| 258 DCHECK(compositor_thread_checker_->CalledOnValidThread()); | 265 DCHECK(compositor_thread_checker->CalledOnValidThread()); |
| 259 #endif | 266 #endif |
| 260 } | 267 } |
| 261 }; | 268 }; |
| 262 | 269 |
| 263 // Don't access main_thread_only_, instead use MainThreadOnly(). | 270 // Don't access main_thread_only_, instead use MainThreadOnly(). |
| 264 MainThreadOnly main_thread_only_; | 271 MainThreadOnly main_thread_only_; |
| 265 MainThreadOnly& MainThreadOnly() { | 272 MainThreadOnly& MainThreadOnly() { |
| 266 helper_.CheckOnValidThread(); | 273 helper_.CheckOnValidThread(); |
| 267 return main_thread_only_; | 274 return main_thread_only_; |
| 268 } | 275 } |
| (...skipping 23 matching lines...) Expand all Loading... |
| 292 | 299 |
| 293 PollableThreadSafeFlag policy_may_need_update_; | 300 PollableThreadSafeFlag policy_may_need_update_; |
| 294 base::WeakPtrFactory<RendererSchedulerImpl> weak_factory_; | 301 base::WeakPtrFactory<RendererSchedulerImpl> weak_factory_; |
| 295 | 302 |
| 296 DISALLOW_COPY_AND_ASSIGN(RendererSchedulerImpl); | 303 DISALLOW_COPY_AND_ASSIGN(RendererSchedulerImpl); |
| 297 }; | 304 }; |
| 298 | 305 |
| 299 } // namespace scheduler | 306 } // namespace scheduler |
| 300 | 307 |
| 301 #endif // COMPONENTS_SCHEDULER_RENDERER_RENDERER_SCHEDULER_IMPL_H_ | 308 #endif // COMPONENTS_SCHEDULER_RENDERER_RENDERER_SCHEDULER_IMPL_H_ |
| OLD | NEW |