Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(90)

Side by Side Diff: third_party/WebKit/Source/platform/scheduler/renderer/budget_pool.cc

Issue 2778123003: [scheduler] Add WakeupBudgetPool. (Closed)
Patch Set: Addressed comments from alexclarke@ Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2017 The Chromium Authors. All rights reserved. 1 // Copyright 2017 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/budget_pool.h" 5 #include "platform/scheduler/renderer/budget_pool.h"
6 6
7 #include <cstdint> 7 #include <cstdint>
8 8
9 #include "base/format_macros.h"
10 #include "base/logging.h"
11 #include "base/memory/ptr_util.h" 9 #include "base/memory/ptr_util.h"
12 #include "base/optional.h" 10 #include "base/optional.h"
13 #include "base/strings/stringprintf.h"
14 #include "platform/WebFrameScheduler.h"
15 #include "platform/scheduler/base/real_time_domain.h"
16 #include "platform/scheduler/child/scheduler_tqm_delegate.h"
17 #include "platform/scheduler/renderer/renderer_scheduler_impl.h"
18 #include "platform/scheduler/renderer/task_queue_throttler.h" 11 #include "platform/scheduler/renderer/task_queue_throttler.h"
19 #include "platform/scheduler/renderer/throttled_time_domain.h"
20 #include "platform/scheduler/renderer/web_frame_scheduler_impl.h"
21 12
22 namespace blink { 13 namespace blink {
23 namespace scheduler { 14 namespace scheduler {
24 15
25 namespace {
26
27 std::string PointerToId(void* pointer) {
28 return base::StringPrintf(
29 "0x%" PRIx64,
30 static_cast<uint64_t>(reinterpret_cast<uintptr_t>(pointer)));
31 }
32
33 } // namespace
34
35 BudgetPool::BudgetPool(const char* name, 16 BudgetPool::BudgetPool(const char* name,
36 BudgetPoolController* budget_pool_controller) 17 BudgetPoolController* budget_pool_controller)
37 : name_(name), 18 : name_(name),
38 budget_pool_controller_(budget_pool_controller), 19 budget_pool_controller_(budget_pool_controller),
39 is_enabled_(true) {} 20 is_enabled_(true) {}
40 21
41 BudgetPool::~BudgetPool() {} 22 BudgetPool::~BudgetPool() {}
42 23
43 const char* BudgetPool::Name() const { 24 const char* BudgetPool::Name() const {
44 return name_; 25 return name_;
45 } 26 }
46 27
47 void BudgetPool::AddQueue(base::TimeTicks now, TaskQueue* queue) { 28 void BudgetPool::AddQueue(base::TimeTicks now, TaskQueue* queue) {
48 budget_pool_controller_->AddQueueToBudgetPool(queue, this); 29 budget_pool_controller_->AddQueueToBudgetPool(queue, this);
49 associated_task_queues_.insert(queue); 30 associated_task_queues_.insert(queue);
50 31
51 if (!is_enabled_ || !budget_pool_controller_->IsThrottled(queue)) 32 if (!is_enabled_)
52 return; 33 return;
34 budget_pool_controller_->UpdateQueueThrottlingState(now, queue);
35 }
53 36
54 budget_pool_controller_->BlockQueue(now, queue); 37 void BudgetPool::UnregisterQueue(TaskQueue* queue) {
38 DissociateQueue(queue);
55 } 39 }
56 40
57 void BudgetPool::RemoveQueue(base::TimeTicks now, TaskQueue* queue) { 41 void BudgetPool::RemoveQueue(base::TimeTicks now, TaskQueue* queue) {
42 DissociateQueue(queue);
43
44 if (!is_enabled_)
45 return;
46
47 budget_pool_controller_->UpdateQueueThrottlingState(now, queue);
48 }
49
50 void BudgetPool::DissociateQueue(TaskQueue* queue) {
58 budget_pool_controller_->RemoveQueueFromBudgetPool(queue, this); 51 budget_pool_controller_->RemoveQueueFromBudgetPool(queue, this);
59 associated_task_queues_.erase(queue); 52 associated_task_queues_.erase(queue);
60
61 if (!is_enabled_ || !budget_pool_controller_->IsThrottled(queue))
62 return;
63
64 budget_pool_controller_->UnblockQueue(now, queue);
65 } 53 }
66 54
67 void BudgetPool::EnableThrottling(LazyNow* lazy_now) { 55 void BudgetPool::EnableThrottling(LazyNow* lazy_now) {
68 if (is_enabled_) 56 if (is_enabled_)
69 return; 57 return;
70 is_enabled_ = true; 58 is_enabled_ = true;
71 59
72 TRACE_EVENT0("renderer.scheduler", "BudgetPool_EnableThrottling"); 60 TRACE_EVENT0("renderer.scheduler", "BudgetPool_EnableThrottling");
73 61
74 BlockThrottledQueues(lazy_now->Now()); 62 BlockThrottledQueues(lazy_now->Now());
75 } 63 }
76 64
77 void BudgetPool::DisableThrottling(LazyNow* lazy_now) { 65 void BudgetPool::DisableThrottling(LazyNow* lazy_now) {
78 if (!is_enabled_) 66 if (!is_enabled_)
79 return; 67 return;
80 is_enabled_ = false; 68 is_enabled_ = false;
81 69
82 TRACE_EVENT0("renderer.scheduler", "BudgetPool_DisableThrottling"); 70 TRACE_EVENT0("renderer.scheduler", "BudgetPool_DisableThrottling");
83 71
84 for (TaskQueue* queue : associated_task_queues_) { 72 for (TaskQueue* queue : associated_task_queues_) {
85 if (!budget_pool_controller_->IsThrottled(queue)) 73 budget_pool_controller_->UpdateQueueThrottlingState(lazy_now->Now(), queue);
86 continue;
87
88 budget_pool_controller_->UnblockQueue(lazy_now->Now(), queue);
89 } 74 }
90 75
91 // TODO(altimin): We need to disable TimeBudgetQueues here or they will 76 // TODO(altimin): We need to disable TimeBudgetQueues here or they will
92 // regenerate extra time budget when they are disabled. 77 // regenerate extra time budget when they are disabled.
93 } 78 }
94 79
95 bool BudgetPool::IsThrottlingEnabled() const { 80 bool BudgetPool::IsThrottlingEnabled() const {
96 return is_enabled_; 81 return is_enabled_;
97 } 82 }
98 83
99 void BudgetPool::Close() { 84 void BudgetPool::Close() {
100 DCHECK_EQ(0u, associated_task_queues_.size()); 85 DCHECK_EQ(0u, associated_task_queues_.size());
101 86
102 budget_pool_controller_->UnregisterBudgetPool(this); 87 budget_pool_controller_->UnregisterBudgetPool(this);
103 } 88 }
104 89
105 void BudgetPool::BlockThrottledQueues(base::TimeTicks now) { 90 void BudgetPool::BlockThrottledQueues(base::TimeTicks now) {
106 for (TaskQueue* queue : associated_task_queues_) 91 for (TaskQueue* queue : associated_task_queues_)
107 budget_pool_controller_->BlockQueue(now, queue); 92 budget_pool_controller_->UpdateQueueThrottlingState(now, queue);
108 }
109
110 CPUTimeBudgetPool::CPUTimeBudgetPool(
111 const char* name,
112 BudgetPoolController* budget_pool_controller,
113 base::TimeTicks now)
114 : BudgetPool(name, budget_pool_controller),
115 last_checkpoint_(now),
116 cpu_percentage_(1) {}
117
118 CPUTimeBudgetPool::~CPUTimeBudgetPool() {}
119
120 void CPUTimeBudgetPool::SetMaxBudgetLevel(
121 base::TimeTicks now,
122 base::Optional<base::TimeDelta> max_budget_level) {
123 Advance(now);
124 max_budget_level_ = max_budget_level;
125 EnforceBudgetLevelRestrictions();
126 }
127
128 void CPUTimeBudgetPool::SetMaxThrottlingDelay(
129 base::TimeTicks now,
130 base::Optional<base::TimeDelta> max_throttling_delay) {
131 Advance(now);
132 max_throttling_delay_ = max_throttling_delay;
133 EnforceBudgetLevelRestrictions();
134 }
135
136 void CPUTimeBudgetPool::SetMinBudgetLevelToRun(
137 base::TimeTicks now,
138 base::TimeDelta min_budget_level_to_run) {
139 Advance(now);
140 min_budget_level_to_run_ = min_budget_level_to_run;
141 }
142
143 void CPUTimeBudgetPool::SetTimeBudgetRecoveryRate(base::TimeTicks now,
144 double cpu_percentage) {
145 Advance(now);
146 cpu_percentage_ = cpu_percentage;
147 EnforceBudgetLevelRestrictions();
148 }
149
150 void CPUTimeBudgetPool::GrantAdditionalBudget(base::TimeTicks now,
151 base::TimeDelta budget_level) {
152 Advance(now);
153 current_budget_level_ += budget_level;
154 EnforceBudgetLevelRestrictions();
155 }
156
157 void CPUTimeBudgetPool::SetReportingCallback(
158 base::Callback<void(base::TimeDelta)> reporting_callback) {
159 reporting_callback_ = reporting_callback;
160 }
161
162 bool CPUTimeBudgetPool::HasEnoughBudgetToRun(base::TimeTicks now) {
163 return now >= GetNextAllowedRunTime();
164 }
165
166 base::TimeTicks CPUTimeBudgetPool::GetNextAllowedRunTime() {
167 if (!is_enabled_ || current_budget_level_.InMicroseconds() >= 0) {
168 return last_checkpoint_;
169 } else {
170 // Subtract because current_budget is negative.
171 return last_checkpoint_ +
172 (-current_budget_level_ + min_budget_level_to_run_) /
173 cpu_percentage_;
174 }
175 }
176
177 void CPUTimeBudgetPool::RecordTaskRunTime(base::TimeTicks start_time,
178 base::TimeTicks end_time) {
179 DCHECK_LE(start_time, end_time);
180 Advance(end_time);
181 if (is_enabled_) {
182 base::TimeDelta old_budget_level = current_budget_level_;
183 current_budget_level_ -= (end_time - start_time);
184 EnforceBudgetLevelRestrictions();
185
186 if (!reporting_callback_.is_null() && old_budget_level.InSecondsF() > 0 &&
187 current_budget_level_.InSecondsF() < 0) {
188 reporting_callback_.Run(-current_budget_level_ / cpu_percentage_);
189 }
190 }
191 }
192
193 void CPUTimeBudgetPool::AsValueInto(base::trace_event::TracedValue* state,
194 base::TimeTicks now) const {
195 state->BeginDictionary(name_);
196
197 state->SetString("name", name_);
198 state->SetDouble("time_budget", cpu_percentage_);
199 state->SetDouble("time_budget_level_in_seconds",
200 current_budget_level_.InSecondsF());
201 state->SetDouble("last_checkpoint_seconds_ago",
202 (now - last_checkpoint_).InSecondsF());
203 state->SetBoolean("is_enabled", is_enabled_);
204 state->SetDouble("min_budget_level_to_run_in_seconds",
205 min_budget_level_to_run_.InSecondsF());
206
207 if (max_throttling_delay_) {
208 state->SetDouble("max_throttling_delay_in_seconds",
209 max_throttling_delay_.value().InSecondsF());
210 }
211 if (max_budget_level_) {
212 state->SetDouble("max_budget_level_in_seconds",
213 max_budget_level_.value().InSecondsF());
214 }
215
216 state->BeginArray("task_queues");
217 for (TaskQueue* queue : associated_task_queues_) {
218 state->AppendString(PointerToId(queue));
219 }
220 state->EndArray();
221
222 state->EndDictionary();
223 }
224
225 void CPUTimeBudgetPool::Advance(base::TimeTicks now) {
226 if (now > last_checkpoint_) {
227 if (is_enabled_) {
228 current_budget_level_ += cpu_percentage_ * (now - last_checkpoint_);
229 EnforceBudgetLevelRestrictions();
230 }
231 last_checkpoint_ = now;
232 }
233 }
234
235 void CPUTimeBudgetPool::EnforceBudgetLevelRestrictions() {
236 if (max_budget_level_) {
237 current_budget_level_ =
238 std::min(current_budget_level_, max_budget_level_.value());
239 }
240 if (max_throttling_delay_) {
241 // Current budget level may be negative.
242 current_budget_level_ =
243 std::max(current_budget_level_,
244 -max_throttling_delay_.value() * cpu_percentage_);
245 }
246 } 93 }
247 94
248 } // namespace scheduler 95 } // namespace scheduler
249 } // namespace blink 96 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698