| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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 THIRD_PARTY_WEBKIT_SOURCE_PLATFORM_SCHEDULER_RENDERER_THROTTLING_HELPER_
H_ | 5 #ifndef THIRD_PARTY_WEBKIT_SOURCE_PLATFORM_SCHEDULER_RENDERER_TASK_QUEUE_THROTTL
ER_H_ |
| 6 #define THIRD_PARTY_WEBKIT_SOURCE_PLATFORM_SCHEDULER_RENDERER_THROTTLING_HELPER_
H_ | 6 #define THIRD_PARTY_WEBKIT_SOURCE_PLATFORM_SCHEDULER_RENDERER_TASK_QUEUE_THROTTL
ER_H_ |
| 7 | 7 |
| 8 #include <set> | 8 #include <set> |
| 9 #include <unordered_map> | 9 #include <unordered_map> |
| 10 | 10 |
| 11 #include "base/logging.h" | 11 #include "base/logging.h" |
| 12 #include "base/macros.h" | 12 #include "base/macros.h" |
| 13 #include "base/optional.h" | 13 #include "base/optional.h" |
| 14 #include "base/threading/thread_checker.h" | 14 #include "base/threading/thread_checker.h" |
| 15 #include "platform/scheduler/base/cancelable_closure_holder.h" | 15 #include "platform/scheduler/base/cancelable_closure_holder.h" |
| 16 #include "platform/scheduler/base/time_domain.h" | 16 #include "platform/scheduler/base/time_domain.h" |
| 17 #include "public/platform/WebViewScheduler.h" | 17 #include "public/platform/WebViewScheduler.h" |
| 18 | 18 |
| 19 namespace base { |
| 20 namespace trace_event { |
| 21 class TracedValue; |
| 22 } |
| 23 } |
| 24 |
| 19 namespace blink { | 25 namespace blink { |
| 20 namespace scheduler { | 26 namespace scheduler { |
| 21 | 27 |
| 28 class BudgetPool; |
| 22 class RendererSchedulerImpl; | 29 class RendererSchedulerImpl; |
| 23 class ThrottledTimeDomain; | 30 class ThrottledTimeDomain; |
| 31 class TimeBudgetPool; |
| 24 | 32 |
| 25 // The job of the TaskQueueThrottler is to control when tasks posted on | 33 // The job of the TaskQueueThrottler is to control when tasks posted on |
| 26 // throttled queues get run. The TaskQueueThrottler: | 34 // throttled queues get run. The TaskQueueThrottler: |
| 27 // - runs throttled tasks once per second, | 35 // - runs throttled tasks once per second, |
| 28 // - controls time budget for task queues grouped in TimeBudgetPools. | 36 // - controls time budget for task queues grouped in TimeBudgetPools. |
| 29 // | 37 // |
| 30 // This is done by disabling throttled queues and running | 38 // This is done by disabling throttled queues and running |
| 31 // a special "heart beat" function |PumpThrottledTasks| which when run | 39 // a special "heart beat" function |PumpThrottledTasks| which when run |
| 32 // temporarily enables throttled queues and inserts a fence to ensure tasks | 40 // temporarily enables throttled queues and inserts a fence to ensure tasks |
| 33 // posted from a throttled task run next time the queue is pumped. | 41 // posted from a throttled task run next time the queue is pumped. |
| 34 // | 42 // |
| 35 // Of course the TaskQueueThrottler isn't the only sub-system that wants to | 43 // Of course the TaskQueueThrottler isn't the only sub-system that wants to |
| 36 // enable or disable queues. E.g. RendererSchedulerImpl also does this for | 44 // enable or disable queues. E.g. RendererSchedulerImpl also does this for |
| 37 // policy reasons. To prevent the systems from fighting, clients of | 45 // policy reasons. To prevent the systems from fighting, clients of |
| 38 // TaskQueueThrottler must use SetQueueEnabled rather than calling the function | 46 // TaskQueueThrottler must use SetQueueEnabled rather than calling the function |
| 39 // directly on the queue. | 47 // directly on the queue. |
| 40 // | 48 // |
| 41 // There may be more than one system that wishes to throttle a queue (e.g. | 49 // There may be more than one system that wishes to throttle a queue (e.g. |
| 42 // renderer suspension vs tab level suspension) so the TaskQueueThrottler keeps | 50 // renderer suspension vs tab level suspension) so the TaskQueueThrottler keeps |
| 43 // a count of the number of systems that wish a queue to be throttled. | 51 // a count of the number of systems that wish a queue to be throttled. |
| 44 // See IncreaseThrottleRefCount & DecreaseThrottleRefCount. | 52 // See IncreaseThrottleRefCount & DecreaseThrottleRefCount. |
| 45 // | 53 // |
| 46 // This class is main-thread only. | 54 // This class is main-thread only. |
| 47 class BLINK_PLATFORM_EXPORT TaskQueueThrottler : public TimeDomain::Observer { | 55 class BLINK_PLATFORM_EXPORT TaskQueueThrottler : public TimeDomain::Observer { |
| 48 public: | 56 public: |
| 49 // TimeBudgetPool represents a group of task queues which share a limit | |
| 50 // on execution time. This limit applies when task queues are already | |
| 51 // throttled by TaskQueueThrottler. | |
| 52 class BLINK_PLATFORM_EXPORT TimeBudgetPool { | |
| 53 public: | |
| 54 ~TimeBudgetPool(); | |
| 55 | |
| 56 // Throttle task queues from this time budget pool if tasks are running | |
| 57 // for more than |cpu_percentage| per cent of wall time. | |
| 58 // This function does not affect internal time budget level. | |
| 59 void SetTimeBudgetRecoveryRate(base::TimeTicks now, double cpu_percentage); | |
| 60 | |
| 61 // Adds |queue| to given pool. If the pool restriction does not allow | |
| 62 // a task to be run immediately and |queue| is throttled, |queue| becomes | |
| 63 // disabled. | |
| 64 void AddQueue(base::TimeTicks now, TaskQueue* queue); | |
| 65 | |
| 66 // Removes |queue| from given pool. If it is throttled, it does not | |
| 67 // become enabled immediately, but a call to |PumpThrottledTasks| | |
| 68 // is scheduled. | |
| 69 void RemoveQueue(base::TimeTicks now, TaskQueue* queue); | |
| 70 | |
| 71 void RecordTaskRunTime(base::TimeTicks start_time, | |
| 72 base::TimeTicks end_time); | |
| 73 | |
| 74 // Enables this time budget pool. Queues from this pool will be | |
| 75 // throttled based on their run time. | |
| 76 void EnableThrottling(LazyNow* now); | |
| 77 | |
| 78 // Disables with time budget pool. Queues from this pool will not be | |
| 79 // throttled based on their run time. A call to |PumpThrottledTasks| | |
| 80 // will be scheduled to enable this queues back again and respect | |
| 81 // timer alignment. Internal budget level will not regenerate with time. | |
| 82 void DisableThrottling(LazyNow* now); | |
| 83 | |
| 84 bool IsThrottlingEnabled() const; | |
| 85 | |
| 86 // Increase budget level by given value. This function DOES NOT unblock | |
| 87 // queues even if they are allowed to run with increased budget level. | |
| 88 void GrantAdditionalBudget(base::TimeTicks now, | |
| 89 base::TimeDelta budget_level); | |
| 90 | |
| 91 const char* Name() const; | |
| 92 | |
| 93 // Set callback which will be called every time when this budget pool | |
| 94 // is throttled. Throttling duration (time until the queue is allowed | |
| 95 // to run again) is passed as a parameter to callback. | |
| 96 void SetReportingCallback( | |
| 97 base::Callback<void(base::TimeDelta)> reporting_callback); | |
| 98 | |
| 99 // All queues should be removed before calling Close(). | |
| 100 void Close(); | |
| 101 | |
| 102 private: | |
| 103 friend class TaskQueueThrottler; | |
| 104 | |
| 105 FRIEND_TEST_ALL_PREFIXES(TaskQueueThrottlerTest, TimeBudgetPool); | |
| 106 | |
| 107 TimeBudgetPool(const char* name, | |
| 108 TaskQueueThrottler* task_queue_throttler, | |
| 109 base::TimeTicks now, | |
| 110 base::Optional<base::TimeDelta> max_budget_level, | |
| 111 base::Optional<base::TimeDelta> max_throttling_duration); | |
| 112 | |
| 113 bool HasEnoughBudgetToRun(base::TimeTicks now); | |
| 114 base::TimeTicks GetNextAllowedRunTime(); | |
| 115 | |
| 116 // Advances |last_checkpoint_| to |now| if needed and recalculates | |
| 117 // budget level. | |
| 118 void Advance(base::TimeTicks now); | |
| 119 | |
| 120 // Returns state for tracing. | |
| 121 void AsValueInto(base::trace_event::TracedValue* state, | |
| 122 base::TimeTicks now) const; | |
| 123 | |
| 124 // Disable all associated throttled queues. | |
| 125 void BlockThrottledQueues(base::TimeTicks now); | |
| 126 | |
| 127 // Increase |current_budget_level_| to satisfy max throttling duration | |
| 128 // condition if necessary. | |
| 129 // Decrease |current_budget_level_| to satisfy max budget level | |
| 130 // condition if necessary. | |
| 131 void EnforceBudgetLevelRestrictions(); | |
| 132 | |
| 133 const char* name_; // NOT OWNED | |
| 134 | |
| 135 TaskQueueThrottler* task_queue_throttler_; | |
| 136 | |
| 137 // Max budget level which we can accrue. | |
| 138 // Tasks will be allowed to run for this time before being throttled | |
| 139 // after a very long period of inactivity. | |
| 140 base::Optional<base::TimeDelta> max_budget_level_; | |
| 141 // Max throttling duration places a lower limit on time budget level, | |
| 142 // ensuring that one long task does not cause extremely long throttling. | |
| 143 // Note that this is not the guarantee that every task will run | |
| 144 // after desired run time + max throttling duration, but a guarantee | |
| 145 // that at least one task will be run every max_throttling_duration. | |
| 146 base::Optional<base::TimeDelta> max_throttling_duration_; | |
| 147 | |
| 148 base::TimeDelta current_budget_level_; | |
| 149 base::TimeTicks last_checkpoint_; | |
| 150 double cpu_percentage_; | |
| 151 bool is_enabled_; | |
| 152 | |
| 153 std::unordered_set<TaskQueue*> associated_task_queues_; | |
| 154 | |
| 155 base::Callback<void(base::TimeDelta)> reporting_callback_; | |
| 156 | |
| 157 DISALLOW_COPY_AND_ASSIGN(TimeBudgetPool); | |
| 158 }; | |
| 159 | |
| 160 // TODO(altimin): Do not pass tracing category as const char*, | 57 // TODO(altimin): Do not pass tracing category as const char*, |
| 161 // hard-code string instead. | 58 // hard-code string instead. |
| 162 TaskQueueThrottler(RendererSchedulerImpl* renderer_scheduler, | 59 TaskQueueThrottler(RendererSchedulerImpl* renderer_scheduler, |
| 163 const char* tracing_category); | 60 const char* tracing_category); |
| 164 | 61 |
| 165 ~TaskQueueThrottler() override; | 62 ~TaskQueueThrottler() override; |
| 166 | 63 |
| 167 // TimeDomain::Observer implementation: | 64 // TimeDomain::Observer implementation: |
| 168 void OnTimeDomainHasImmediateWork(TaskQueue*) override; | 65 void OnTimeDomainHasImmediateWork(TaskQueue*) override; |
| 169 void OnTimeDomainHasDelayedWork(TaskQueue*) override; | 66 void OnTimeDomainHasDelayedWork(TaskQueue*) override; |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 206 | 103 |
| 207 // Accounts for given task for cpu-based throttling needs. | 104 // Accounts for given task for cpu-based throttling needs. |
| 208 void OnTaskRunTimeReported(TaskQueue* task_queue, | 105 void OnTaskRunTimeReported(TaskQueue* task_queue, |
| 209 base::TimeTicks start_time, | 106 base::TimeTicks start_time, |
| 210 base::TimeTicks end_time); | 107 base::TimeTicks end_time); |
| 211 | 108 |
| 212 void AsValueInto(base::trace_event::TracedValue* state, | 109 void AsValueInto(base::trace_event::TracedValue* state, |
| 213 base::TimeTicks now) const; | 110 base::TimeTicks now) const; |
| 214 | 111 |
| 215 private: | 112 private: |
| 113 friend class BudgetPool; |
| 114 friend class TimeBudgetPool; |
| 115 |
| 216 struct Metadata { | 116 struct Metadata { |
| 217 Metadata() : throttling_ref_count(0), time_budget_pool(nullptr) {} | 117 Metadata() : throttling_ref_count(0), time_budget_pool(nullptr) {} |
| 218 | 118 |
| 219 size_t throttling_ref_count; | 119 size_t throttling_ref_count; |
| 220 | 120 |
| 221 TimeBudgetPool* time_budget_pool; | 121 TimeBudgetPool* time_budget_pool; |
| 222 }; | 122 }; |
| 223 using TaskQueueMap = std::unordered_map<TaskQueue*, Metadata>; | 123 using TaskQueueMap = std::unordered_map<TaskQueue*, Metadata>; |
| 224 | 124 |
| 225 void PumpThrottledTasks(); | 125 void PumpThrottledTasks(); |
| (...skipping 26 matching lines...) Expand all Loading... |
| 252 scoped_refptr<TaskQueue> task_runner_; | 152 scoped_refptr<TaskQueue> task_runner_; |
| 253 RendererSchedulerImpl* renderer_scheduler_; // NOT OWNED | 153 RendererSchedulerImpl* renderer_scheduler_; // NOT OWNED |
| 254 base::TickClock* tick_clock_; // NOT OWNED | 154 base::TickClock* tick_clock_; // NOT OWNED |
| 255 const char* tracing_category_; // NOT OWNED | 155 const char* tracing_category_; // NOT OWNED |
| 256 std::unique_ptr<ThrottledTimeDomain> time_domain_; | 156 std::unique_ptr<ThrottledTimeDomain> time_domain_; |
| 257 | 157 |
| 258 CancelableClosureHolder pump_throttled_tasks_closure_; | 158 CancelableClosureHolder pump_throttled_tasks_closure_; |
| 259 base::Optional<base::TimeTicks> pending_pump_throttled_tasks_runtime_; | 159 base::Optional<base::TimeTicks> pending_pump_throttled_tasks_runtime_; |
| 260 bool allow_throttling_; | 160 bool allow_throttling_; |
| 261 | 161 |
| 262 std::unordered_map<TimeBudgetPool*, std::unique_ptr<TimeBudgetPool>> | 162 std::unordered_map<BudgetPool*, std::unique_ptr<BudgetPool>> |
| 263 time_budget_pools_; | 163 time_budget_pools_; |
| 264 | 164 |
| 265 base::WeakPtrFactory<TaskQueueThrottler> weak_factory_; | 165 base::WeakPtrFactory<TaskQueueThrottler> weak_factory_; |
| 266 | 166 |
| 267 DISALLOW_COPY_AND_ASSIGN(TaskQueueThrottler); | 167 DISALLOW_COPY_AND_ASSIGN(TaskQueueThrottler); |
| 268 }; | 168 }; |
| 269 | 169 |
| 270 } // namespace scheduler | 170 } // namespace scheduler |
| 271 } // namespace blink | 171 } // namespace blink |
| 272 | 172 |
| 273 #endif // THIRD_PARTY_WEBKIT_SOURCE_PLATFORM_SCHEDULER_RENDERER_THROTTLING_HELP
ER_H_ | 173 #endif // THIRD_PARTY_WEBKIT_SOURCE_PLATFORM_SCHEDULER_RENDERER_TASK_QUEUE_THRO
TTLER_H_ |
| OLD | NEW |