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

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

Issue 2741473002: [scheduler] Move TimeBudgetPool to a separate file. (Closed)
Patch Set: Created 3 years, 9 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
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "platform/scheduler/renderer/budget_pool.h"
6
7 #include <cstdint>
8
9 #include "base/format_macros.h"
10 #include "base/logging.h"
11 #include "base/memory/ptr_util.h"
12 #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"
19 #include "platform/scheduler/renderer/throttled_time_domain.h"
20 #include "platform/scheduler/renderer/web_frame_scheduler_impl.h"
21
22 namespace blink {
23 namespace scheduler {
24
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() {}
36
37 TimeBudgetPool::TimeBudgetPool(
Sami 2017/03/08 16:18:01 Could we extract some unit tests for this too? (I
altimin 2017/03/08 16:50:32 Done.
38 const char* name,
39 TaskQueueThrottler* task_queue_throttler,
40 base::TimeTicks now,
41 base::Optional<base::TimeDelta> max_budget_level,
42 base::Optional<base::TimeDelta> max_throttling_duration)
43 : name_(name),
44 task_queue_throttler_(task_queue_throttler),
45 max_budget_level_(max_budget_level),
46 max_throttling_duration_(max_throttling_duration),
47 last_checkpoint_(now),
48 cpu_percentage_(1),
49 is_enabled_(true) {}
50
51 TimeBudgetPool::~TimeBudgetPool() {}
52
53 void TimeBudgetPool::SetTimeBudgetRecoveryRate(
54 base::TimeTicks now,
55 double cpu_percentage) {
56 Advance(now);
57 cpu_percentage_ = cpu_percentage;
58 EnforceBudgetLevelRestrictions();
59 }
60
61 void TimeBudgetPool::AddQueue(base::TimeTicks now, TaskQueue* queue) {
62 std::pair<TaskQueueThrottler::TaskQueueMap::iterator, bool> insert_result =
63 task_queue_throttler_->queue_details_.insert(
64 std::make_pair(queue, TaskQueueThrottler::Metadata()));
65 TaskQueueThrottler::Metadata& metadata = insert_result.first->second;
66 DCHECK(!metadata.time_budget_pool);
67 metadata.time_budget_pool = this;
68
69 associated_task_queues_.insert(queue);
70
71 if (!is_enabled_ || !task_queue_throttler_->IsThrottled(queue))
72 return;
73
74 queue->InsertFence(TaskQueue::InsertFencePosition::BEGINNING_OF_TIME);
75
76 task_queue_throttler_->MaybeSchedulePumpQueue(FROM_HERE, now, queue,
77 GetNextAllowedRunTime());
78 }
79
80 void TimeBudgetPool::RemoveQueue(base::TimeTicks now,
81 TaskQueue* queue) {
82 auto find_it = task_queue_throttler_->queue_details_.find(queue);
83 DCHECK(find_it != task_queue_throttler_->queue_details_.end() &&
84 find_it->second.time_budget_pool == this);
85 find_it->second.time_budget_pool = nullptr;
86 bool is_throttled = task_queue_throttler_->IsThrottled(queue);
87
88 task_queue_throttler_->MaybeDeleteQueueMetadata(find_it);
89 associated_task_queues_.erase(queue);
90
91 if (!is_enabled_ || !is_throttled)
92 return;
93
94 task_queue_throttler_->MaybeSchedulePumpQueue(FROM_HERE, now, queue,
95 base::nullopt);
96 }
97
98 void TimeBudgetPool::EnableThrottling(LazyNow* lazy_now) {
99 if (is_enabled_)
100 return;
101 is_enabled_ = true;
102
103 TRACE_EVENT0(task_queue_throttler_->tracing_category_,
104 "TaskQueueThrottler_TimeBudgetPool_EnableThrottling");
Sami 2017/03/08 16:18:00 Please remove TaskQueueThrottler from these trace
altimin 2017/03/08 16:50:32 Done.
105
106 BlockThrottledQueues(lazy_now->Now());
107 }
108
109 void TimeBudgetPool::DisableThrottling(LazyNow* lazy_now) {
110 if (!is_enabled_)
111 return;
112 is_enabled_ = false;
113
114 TRACE_EVENT0(task_queue_throttler_->tracing_category_,
115 "TaskQueueThrottler_TimeBudgetPool_DisableThrottling");
116
117 for (TaskQueue* queue : associated_task_queues_) {
118 if (!task_queue_throttler_->IsThrottled(queue))
119 continue;
120
121 task_queue_throttler_->MaybeSchedulePumpQueue(FROM_HERE, lazy_now->Now(),
122 queue, base::nullopt);
123 }
124
125 // TODO(altimin): We need to disable TimeBudgetQueues here or they will
126 // regenerate extra time budget when they are disabled.
127 }
128
129 bool TimeBudgetPool::IsThrottlingEnabled() const {
130 return is_enabled_;
131 }
132
133 void TimeBudgetPool::GrantAdditionalBudget(
134 base::TimeTicks now,
135 base::TimeDelta budget_level) {
136 Advance(now);
137 current_budget_level_ += budget_level;
138 EnforceBudgetLevelRestrictions();
139 }
140
141 void TimeBudgetPool::SetReportingCallback(
142 base::Callback<void(base::TimeDelta)> reporting_callback) {
143 reporting_callback_ = reporting_callback;
144 }
145
146 void TimeBudgetPool::Close() {
147 DCHECK_EQ(0u, associated_task_queues_.size());
148
149 task_queue_throttler_->time_budget_pools_.erase(this);
150 }
151
152 bool TimeBudgetPool::HasEnoughBudgetToRun(
153 base::TimeTicks now) {
154 Advance(now);
155 return !is_enabled_ || current_budget_level_.InMicroseconds() >= 0;
156 }
157
158 base::TimeTicks TimeBudgetPool::GetNextAllowedRunTime() {
159 if (!is_enabled_ || current_budget_level_.InMicroseconds() >= 0) {
160 return last_checkpoint_;
161 } else {
162 // Subtract because current_budget is negative.
163 return last_checkpoint_ - current_budget_level_ / cpu_percentage_;
164 }
165 }
166
167 void TimeBudgetPool::RecordTaskRunTime(
168 base::TimeTicks start_time,
169 base::TimeTicks end_time) {
170 DCHECK_LE(start_time, end_time);
171 Advance(end_time);
172 if (is_enabled_) {
173 base::TimeDelta old_budget_level = current_budget_level_;
174 current_budget_level_ -= (end_time - start_time);
175 EnforceBudgetLevelRestrictions();
176
177 if (!reporting_callback_.is_null() && old_budget_level.InSecondsF() > 0 &&
178 current_budget_level_.InSecondsF() < 0) {
179 reporting_callback_.Run(-current_budget_level_ / cpu_percentage_);
180 }
181 }
182 }
183
184 const char* TimeBudgetPool::Name() const {
185 return name_;
186 }
187
188 void TimeBudgetPool::AsValueInto(
189 base::trace_event::TracedValue* state,
190 base::TimeTicks now) const {
191 state->BeginDictionary(name_);
192
193 state->SetString("name", name_);
194 state->SetDouble("time_budget", cpu_percentage_);
195 state->SetDouble("time_budget_level_in_seconds",
196 current_budget_level_.InSecondsF());
197 state->SetDouble("last_checkpoint_seconds_ago",
198 (now - last_checkpoint_).InSecondsF());
199 state->SetBoolean("is_enabled", is_enabled_);
200
201 state->BeginArray("task_queues");
202 for (TaskQueue* queue : associated_task_queues_) {
203 state->AppendString(PointerToId(queue));
204 }
205 state->EndArray();
206
207 state->EndDictionary();
208 }
209
210 void TimeBudgetPool::Advance(base::TimeTicks now) {
211 if (now > last_checkpoint_) {
212 if (is_enabled_) {
213 current_budget_level_ += cpu_percentage_ * (now - last_checkpoint_);
214 EnforceBudgetLevelRestrictions();
215 }
216 last_checkpoint_ = now;
217 }
218 }
219
220 void TimeBudgetPool::BlockThrottledQueues(
221 base::TimeTicks now) {
222 for (TaskQueue* queue : associated_task_queues_) {
223 if (!task_queue_throttler_->IsThrottled(queue))
224 continue;
225
226 queue->InsertFence(TaskQueue::InsertFencePosition::BEGINNING_OF_TIME);
227 task_queue_throttler_->MaybeSchedulePumpQueue(FROM_HERE, now, queue,
228 base::nullopt);
229 }
230 }
231
232 void TimeBudgetPool::EnforceBudgetLevelRestrictions() {
233 if (max_budget_level_) {
234 current_budget_level_ =
235 std::min(current_budget_level_, max_budget_level_.value());
236 }
237 if (max_throttling_duration_) {
238 // Current budget level may be negative.
239 current_budget_level_ =
240 std::max(current_budget_level_,
241 -max_throttling_duration_.value() * cpu_percentage_);
242 }
243 }
244
245 } // namespace scheduler
246 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698