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; | |
Sami
2017/03/08 16:18:01
I guess these will be removed later?
altimin
2017/03/08 16:50:33
Yep, the comment in the patch description.
| |
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 |