Chromium Code Reviews| 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_TASK_QUEUE_THROTTL ER_H_ | 5 #ifndef THIRD_PARTY_WEBKIT_SOURCE_PLATFORM_SCHEDULER_RENDERER_TASK_QUEUE_THROTTL ER_H_ |
| 6 #define THIRD_PARTY_WEBKIT_SOURCE_PLATFORM_SCHEDULER_RENDERER_TASK_QUEUE_THROTTL ER_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 "platform/scheduler/renderer/budget_pool.h" | |
| 17 #include "public/platform/WebViewScheduler.h" | 18 #include "public/platform/WebViewScheduler.h" |
| 18 | 19 |
| 19 namespace base { | 20 namespace base { |
| 20 namespace trace_event { | 21 namespace trace_event { |
| 21 class TracedValue; | 22 class TracedValue; |
| 22 } | 23 } |
| 23 } | 24 } |
| 24 | 25 |
| 25 namespace blink { | 26 namespace blink { |
| 26 namespace scheduler { | 27 namespace scheduler { |
| 27 | 28 |
| 28 class BudgetPool; | 29 class BudgetPool; |
| 29 class RendererSchedulerImpl; | 30 class RendererSchedulerImpl; |
| 30 class ThrottledTimeDomain; | 31 class ThrottledTimeDomain; |
| 31 class CPUTimeBudgetPool; | 32 class CPUTimeBudgetPool; |
| 32 | 33 |
| 34 // Interface for BudgetPool to interact with TaskQueueThrottler. | |
| 35 class BLINK_PLATFORM_EXPORT BudgetPoolController { | |
| 36 public: | |
| 37 virtual ~BudgetPoolController() {} | |
| 38 | |
| 39 // To be used by BudgetPool only, use BudgetPool::{Add,Remove}Queue | |
| 40 // methods instead. | |
| 41 virtual void AddQueueToBudgetPool(TaskQueue* queue, | |
| 42 BudgetPool* budget_pool) = 0; | |
| 43 virtual void RemoveQueueFromBudgetPool(TaskQueue* queue, | |
| 44 BudgetPool* budget_pool) = 0; | |
| 45 | |
| 46 // Deletes the budget pool. | |
| 47 virtual void UnregisterBudgetPool(BudgetPool* budget_pool) = 0; | |
| 48 | |
| 49 // Insert a fence to prevent tasks from running and schedule a wakeup at | |
| 50 // an appropriate time. | |
| 51 virtual void BlockQueue(base::TimeTicks now, TaskQueue* queue) = 0; | |
| 52 | |
| 53 // Schedule a call to unblock queue at an appropriate moment. | |
| 54 virtual void UnblockQueue(base::TimeTicks now, TaskQueue* queue) = 0; | |
| 55 | |
| 56 // Returns true if the |queue| is throttled (i.e. added to TaskQueueThrottler | |
| 57 // and throttling is not disabled). | |
| 58 virtual bool IsThrottled(TaskQueue* queue) const = 0; | |
| 59 }; | |
| 60 | |
| 33 // The job of the TaskQueueThrottler is to control when tasks posted on | 61 // The job of the TaskQueueThrottler is to control when tasks posted on |
| 34 // throttled queues get run. The TaskQueueThrottler: | 62 // throttled queues get run. The TaskQueueThrottler: |
| 35 // - runs throttled tasks once per second, | 63 // - runs throttled tasks once per second, |
| 36 // - controls time budget for task queues grouped in CPUTimeBudgetPools. | 64 // - controls time budget for task queues grouped in CPUTimeBudgetPools. |
| 37 // | 65 // |
| 38 // This is done by disabling throttled queues and running | 66 // This is done by disabling throttled queues and running |
| 39 // a special "heart beat" function |PumpThrottledTasks| which when run | 67 // a special "heart beat" function |PumpThrottledTasks| which when run |
| 40 // temporarily enables throttled queues and inserts a fence to ensure tasks | 68 // temporarily enables throttled queues and inserts a fence to ensure tasks |
| 41 // posted from a throttled task run next time the queue is pumped. | 69 // posted from a throttled task run next time the queue is pumped. |
| 42 // | 70 // |
| 43 // Of course the TaskQueueThrottler isn't the only sub-system that wants to | 71 // Of course the TaskQueueThrottler isn't the only sub-system that wants to |
| 44 // enable or disable queues. E.g. RendererSchedulerImpl also does this for | 72 // enable or disable queues. E.g. RendererSchedulerImpl also does this for |
| 45 // policy reasons. To prevent the systems from fighting, clients of | 73 // policy reasons. To prevent the systems from fighting, clients of |
| 46 // TaskQueueThrottler must use SetQueueEnabled rather than calling the function | 74 // TaskQueueThrottler must use SetQueueEnabled rather than calling the function |
| 47 // directly on the queue. | 75 // directly on the queue. |
| 48 // | 76 // |
| 49 // There may be more than one system that wishes to throttle a queue (e.g. | 77 // There may be more than one system that wishes to throttle a queue (e.g. |
| 50 // renderer suspension vs tab level suspension) so the TaskQueueThrottler keeps | 78 // renderer suspension vs tab level suspension) so the TaskQueueThrottler keeps |
| 51 // a count of the number of systems that wish a queue to be throttled. | 79 // a count of the number of systems that wish a queue to be throttled. |
| 52 // See IncreaseThrottleRefCount & DecreaseThrottleRefCount. | 80 // See IncreaseThrottleRefCount & DecreaseThrottleRefCount. |
| 53 // | 81 // |
| 54 // This class is main-thread only. | 82 // This class is main-thread only. |
| 55 class BLINK_PLATFORM_EXPORT TaskQueueThrottler : public TimeDomain::Observer { | 83 class BLINK_PLATFORM_EXPORT TaskQueueThrottler : public TimeDomain::Observer, |
| 84 BudgetPoolController { | |
|
Sami
2017/03/15 15:08:08
nit: public inheritance plz
altimin
2017/03/15 18:20:56
Done.
| |
| 56 public: | 85 public: |
| 57 // TODO(altimin): Do not pass tracing category as const char*, | 86 // TODO(altimin): Do not pass tracing category as const char*, |
| 58 // hard-code string instead. | 87 // hard-code string instead. |
| 59 TaskQueueThrottler(RendererSchedulerImpl* renderer_scheduler, | 88 TaskQueueThrottler(RendererSchedulerImpl* renderer_scheduler, |
| 60 const char* tracing_category); | 89 const char* tracing_category); |
| 61 | 90 |
| 62 ~TaskQueueThrottler() override; | 91 ~TaskQueueThrottler() override; |
| 63 | 92 |
| 64 // TimeDomain::Observer implementation: | 93 // TimeDomain::Observer implementation: |
| 65 void OnTimeDomainHasImmediateWork(TaskQueue*) override; | 94 void OnTimeDomainHasImmediateWork(TaskQueue*) override; |
| 66 void OnTimeDomainHasDelayedWork(TaskQueue*) override; | 95 void OnTimeDomainHasDelayedWork(TaskQueue*) override; |
| 67 | 96 |
| 97 // BudgetPoolController implementation: | |
| 98 void AddQueueToBudgetPool(TaskQueue* queue, BudgetPool* budget_pool) override; | |
| 99 void RemoveQueueFromBudgetPool(TaskQueue* queue, | |
| 100 BudgetPool* budget_pool) override; | |
| 101 void UnregisterBudgetPool(BudgetPool* budget_pool) override; | |
| 102 void BlockQueue(base::TimeTicks now, TaskQueue* queue) override; | |
| 103 void UnblockQueue(base::TimeTicks now, TaskQueue* queue) override; | |
| 104 bool IsThrottled(TaskQueue* queue) const override; | |
| 105 | |
| 68 // Increments the throttled refcount and causes |task_queue| to be throttled | 106 // Increments the throttled refcount and causes |task_queue| to be throttled |
| 69 // if its not already throttled. | 107 // if its not already throttled. |
| 70 void IncreaseThrottleRefCount(TaskQueue* task_queue); | 108 void IncreaseThrottleRefCount(TaskQueue* task_queue); |
| 71 | 109 |
| 72 // If the refcouint is non-zero it's decremented. If the throttled refcount | 110 // If the refcouint is non-zero it's decremented. If the throttled refcount |
| 73 // becomes zero then |task_queue| is unthrottled. If the refcount was already | 111 // becomes zero then |task_queue| is unthrottled. If the refcount was already |
| 74 // zero this function does nothing. | 112 // zero this function does nothing. |
| 75 void DecreaseThrottleRefCount(TaskQueue* task_queue); | 113 void DecreaseThrottleRefCount(TaskQueue* task_queue); |
| 76 | 114 |
| 77 // Removes |task_queue| from |queue_details| and from appropriate budget pool. | 115 // Removes |task_queue| from |queue_details| and from appropriate budget pool. |
| 78 void UnregisterTaskQueue(TaskQueue* task_queue); | 116 void UnregisterTaskQueue(TaskQueue* task_queue); |
| 79 | 117 |
| 80 // Returns true if the |task_queue| is throttled. | |
| 81 bool IsThrottled(TaskQueue* task_queue) const; | |
| 82 | |
| 83 // Disable throttling for all queues, this setting takes precedence over | 118 // Disable throttling for all queues, this setting takes precedence over |
| 84 // all other throttling settings. Designed to be used when a global event | 119 // all other throttling settings. Designed to be used when a global event |
| 85 // disabling throttling happens (e.g. audio is playing). | 120 // disabling throttling happens (e.g. audio is playing). |
| 86 void DisableThrottling(); | 121 void DisableThrottling(); |
| 87 | 122 |
| 88 // Enable back global throttling. | 123 // Enable back global throttling. |
| 89 void EnableThrottling(); | 124 void EnableThrottling(); |
| 90 | 125 |
| 91 const ThrottledTimeDomain* time_domain() const { return time_domain_.get(); } | 126 const ThrottledTimeDomain* time_domain() const { return time_domain_.get(); } |
| 92 | 127 |
| 93 static base::TimeTicks AlignedThrottledRunTime( | 128 static base::TimeTicks AlignedThrottledRunTime( |
| 94 base::TimeTicks unthrottled_runtime); | 129 base::TimeTicks unthrottled_runtime); |
| 95 | 130 |
| 96 const scoped_refptr<TaskQueue>& task_runner() const { return task_runner_; } | 131 const scoped_refptr<TaskQueue>& task_runner() const { return task_runner_; } |
| 97 | 132 |
| 98 // Returned object is owned by |TaskQueueThrottler|. | 133 // Returned object is owned by |TaskQueueThrottler|. |
| 99 CPUTimeBudgetPool* CreateCPUTimeBudgetPool( | 134 CPUTimeBudgetPool* CreateCPUTimeBudgetPool( |
| 100 const char* name, | 135 const char* name, |
| 101 base::Optional<base::TimeDelta> max_budget_level, | 136 base::Optional<base::TimeDelta> max_budget_level, |
| 102 base::Optional<base::TimeDelta> max_throttling_duration); | 137 base::Optional<base::TimeDelta> max_throttling_duration); |
| 103 | 138 |
| 104 // Accounts for given task for cpu-based throttling needs. | 139 // Accounts for given task for cpu-based throttling needs. |
| 105 void OnTaskRunTimeReported(TaskQueue* task_queue, | 140 void OnTaskRunTimeReported(TaskQueue* task_queue, |
| 106 base::TimeTicks start_time, | 141 base::TimeTicks start_time, |
| 107 base::TimeTicks end_time); | 142 base::TimeTicks end_time); |
| 108 | 143 |
| 109 void AsValueInto(base::trace_event::TracedValue* state, | 144 void AsValueInto(base::trace_event::TracedValue* state, |
| 110 base::TimeTicks now) const; | 145 base::TimeTicks now) const; |
| 111 | |
| 112 private: | 146 private: |
| 113 friend class BudgetPool; | |
| 114 friend class CPUTimeBudgetPool; | |
| 115 | |
| 116 struct Metadata { | 147 struct Metadata { |
| 117 Metadata() : throttling_ref_count(0), time_budget_pool(nullptr) {} | 148 Metadata() : throttling_ref_count(0), budget_pool(nullptr) {} |
| 118 | 149 |
| 119 size_t throttling_ref_count; | 150 size_t throttling_ref_count; |
| 120 | 151 |
| 121 CPUTimeBudgetPool* time_budget_pool; | 152 BudgetPool* budget_pool; |
| 122 }; | 153 }; |
| 123 using TaskQueueMap = std::unordered_map<TaskQueue*, Metadata>; | 154 using TaskQueueMap = std::unordered_map<TaskQueue*, Metadata>; |
| 124 | 155 |
| 125 void PumpThrottledTasks(); | 156 void PumpThrottledTasks(); |
| 126 | 157 |
| 127 // Note |unthrottled_runtime| might be in the past. When this happens we | 158 // Note |unthrottled_runtime| might be in the past. When this happens we |
| 128 // compute the delay to the next runtime based on now rather than | 159 // compute the delay to the next runtime based on now rather than |
| 129 // unthrottled_runtime. | 160 // unthrottled_runtime. |
| 130 void MaybeSchedulePumpThrottledTasks( | 161 void MaybeSchedulePumpThrottledTasks( |
| 131 const tracked_objects::Location& from_here, | 162 const tracked_objects::Location& from_here, |
| 132 base::TimeTicks now, | 163 base::TimeTicks now, |
| 133 base::TimeTicks runtime); | 164 base::TimeTicks runtime); |
| 134 | 165 |
| 135 CPUTimeBudgetPool* GetTimeBudgetPoolForQueue(TaskQueue* queue); | 166 BudgetPool* GetBudgetPoolForQueue(TaskQueue* queue); |
| 136 | |
| 137 // Schedule pumping because of given task queue. | |
| 138 void MaybeSchedulePumpQueue( | |
| 139 const tracked_objects::Location& from_here, | |
| 140 base::TimeTicks now, | |
| 141 TaskQueue* queue, | |
| 142 base::Optional<base::TimeTicks> next_possible_run_time); | |
| 143 | 167 |
| 144 // Return next possible time when queue is allowed to run in accordance | 168 // Return next possible time when queue is allowed to run in accordance |
| 145 // with throttling policy. | 169 // with throttling policy. |
| 146 base::TimeTicks GetNextAllowedRunTime(base::TimeTicks now, TaskQueue* queue); | 170 base::TimeTicks GetNextAllowedRunTime(base::TimeTicks now, TaskQueue* queue); |
| 147 | 171 |
| 148 void MaybeDeleteQueueMetadata(TaskQueueMap::iterator it); | 172 void MaybeDeleteQueueMetadata(TaskQueueMap::iterator it); |
| 149 | 173 |
| 174 // Schedule a call PumpThrottledTasks at an appropriate moment for this queue. | |
| 175 void SchedulePumpQueue(const tracked_objects::Location& from_here, | |
| 176 base::TimeTicks now, | |
| 177 TaskQueue* queue); | |
| 178 | |
| 150 TaskQueueMap queue_details_; | 179 TaskQueueMap queue_details_; |
| 151 base::Callback<void(TaskQueue*)> forward_immediate_work_callback_; | 180 base::Callback<void(TaskQueue*)> forward_immediate_work_callback_; |
| 152 scoped_refptr<TaskQueue> task_runner_; | 181 scoped_refptr<TaskQueue> task_runner_; |
| 153 RendererSchedulerImpl* renderer_scheduler_; // NOT OWNED | 182 RendererSchedulerImpl* renderer_scheduler_; // NOT OWNED |
| 154 base::TickClock* tick_clock_; // NOT OWNED | 183 base::TickClock* tick_clock_; // NOT OWNED |
| 155 const char* tracing_category_; // NOT OWNED | 184 const char* tracing_category_; // NOT OWNED |
| 156 std::unique_ptr<ThrottledTimeDomain> time_domain_; | 185 std::unique_ptr<ThrottledTimeDomain> time_domain_; |
| 157 | 186 |
| 158 CancelableClosureHolder pump_throttled_tasks_closure_; | 187 CancelableClosureHolder pump_throttled_tasks_closure_; |
| 159 base::Optional<base::TimeTicks> pending_pump_throttled_tasks_runtime_; | 188 base::Optional<base::TimeTicks> pending_pump_throttled_tasks_runtime_; |
| 160 bool allow_throttling_; | 189 bool allow_throttling_; |
| 161 | 190 |
| 162 std::unordered_map<BudgetPool*, std::unique_ptr<BudgetPool>> | 191 std::unordered_map<BudgetPool*, std::unique_ptr<BudgetPool>> budget_pools_; |
| 163 time_budget_pools_; | |
| 164 | 192 |
| 165 base::WeakPtrFactory<TaskQueueThrottler> weak_factory_; | 193 base::WeakPtrFactory<TaskQueueThrottler> weak_factory_; |
| 166 | 194 |
| 167 DISALLOW_COPY_AND_ASSIGN(TaskQueueThrottler); | 195 DISALLOW_COPY_AND_ASSIGN(TaskQueueThrottler); |
| 168 }; | 196 }; |
| 169 | 197 |
| 170 } // namespace scheduler | 198 } // namespace scheduler |
| 171 } // namespace blink | 199 } // namespace blink |
| 172 | 200 |
| 173 #endif // THIRD_PARTY_WEBKIT_SOURCE_PLATFORM_SCHEDULER_RENDERER_TASK_QUEUE_THRO TTLER_H_ | 201 #endif // THIRD_PARTY_WEBKIT_SOURCE_PLATFORM_SCHEDULER_RENDERER_TASK_QUEUE_THRO TTLER_H_ |
| OLD | NEW |