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

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: Addressed comments from skyostil@ 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(
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(base::TimeTicks now,
54 double cpu_percentage) {
55 Advance(now);
56 cpu_percentage_ = cpu_percentage;
57 EnforceBudgetLevelRestrictions();
58 }
59
60 void TimeBudgetPool::AddQueue(base::TimeTicks now, TaskQueue* queue) {
61 std::pair<TaskQueueThrottler::TaskQueueMap::iterator, bool> insert_result =
62 task_queue_throttler_->queue_details_.insert(
63 std::make_pair(queue, TaskQueueThrottler::Metadata()));
64 TaskQueueThrottler::Metadata& metadata = insert_result.first->second;
65 DCHECK(!metadata.time_budget_pool);
66 metadata.time_budget_pool = this;
67
68 associated_task_queues_.insert(queue);
69
70 if (!is_enabled_ || !task_queue_throttler_->IsThrottled(queue))
71 return;
72
73 queue->InsertFence(TaskQueue::InsertFencePosition::BEGINNING_OF_TIME);
74
75 task_queue_throttler_->MaybeSchedulePumpQueue(FROM_HERE, now, queue,
76 GetNextAllowedRunTime());
77 }
78
79 void TimeBudgetPool::RemoveQueue(base::TimeTicks now, TaskQueue* queue) {
80 auto find_it = task_queue_throttler_->queue_details_.find(queue);
81 DCHECK(find_it != task_queue_throttler_->queue_details_.end() &&
82 find_it->second.time_budget_pool == this);
83 find_it->second.time_budget_pool = nullptr;
84 bool is_throttled = task_queue_throttler_->IsThrottled(queue);
85
86 task_queue_throttler_->MaybeDeleteQueueMetadata(find_it);
87 associated_task_queues_.erase(queue);
88
89 if (!is_enabled_ || !is_throttled)
90 return;
91
92 task_queue_throttler_->MaybeSchedulePumpQueue(FROM_HERE, now, queue,
93 base::nullopt);
94 }
95
96 void TimeBudgetPool::EnableThrottling(LazyNow* lazy_now) {
97 if (is_enabled_)
98 return;
99 is_enabled_ = true;
100
101 TRACE_EVENT0(task_queue_throttler_->tracing_category_,
102 "TimeBudgetPool_EnableThrottling");
103
104 BlockThrottledQueues(lazy_now->Now());
105 }
106
107 void TimeBudgetPool::DisableThrottling(LazyNow* lazy_now) {
108 if (!is_enabled_)
109 return;
110 is_enabled_ = false;
111
112 TRACE_EVENT0(task_queue_throttler_->tracing_category_,
113 "TimeBudgetPool_DisableThrottling");
114
115 for (TaskQueue* queue : associated_task_queues_) {
116 if (!task_queue_throttler_->IsThrottled(queue))
117 continue;
118
119 task_queue_throttler_->MaybeSchedulePumpQueue(FROM_HERE, lazy_now->Now(),
120 queue, base::nullopt);
121 }
122
123 // TODO(altimin): We need to disable TimeBudgetQueues here or they will
124 // regenerate extra time budget when they are disabled.
125 }
126
127 bool TimeBudgetPool::IsThrottlingEnabled() const {
128 return is_enabled_;
129 }
130
131 void TimeBudgetPool::GrantAdditionalBudget(base::TimeTicks now,
132 base::TimeDelta budget_level) {
133 Advance(now);
134 current_budget_level_ += budget_level;
135 EnforceBudgetLevelRestrictions();
136 }
137
138 void TimeBudgetPool::SetReportingCallback(
139 base::Callback<void(base::TimeDelta)> reporting_callback) {
140 reporting_callback_ = reporting_callback;
141 }
142
143 void TimeBudgetPool::Close() {
144 DCHECK_EQ(0u, associated_task_queues_.size());
145
146 task_queue_throttler_->time_budget_pools_.erase(this);
147 }
148
149 bool TimeBudgetPool::HasEnoughBudgetToRun(base::TimeTicks now) {
150 Advance(now);
151 return !is_enabled_ || current_budget_level_.InMicroseconds() >= 0;
152 }
153
154 base::TimeTicks TimeBudgetPool::GetNextAllowedRunTime() {
155 if (!is_enabled_ || current_budget_level_.InMicroseconds() >= 0) {
156 return last_checkpoint_;
157 } else {
158 // Subtract because current_budget is negative.
159 return last_checkpoint_ - current_budget_level_ / cpu_percentage_;
160 }
161 }
162
163 void TimeBudgetPool::RecordTaskRunTime(base::TimeTicks start_time,
164 base::TimeTicks end_time) {
165 DCHECK_LE(start_time, end_time);
166 Advance(end_time);
167 if (is_enabled_) {
168 base::TimeDelta old_budget_level = current_budget_level_;
169 current_budget_level_ -= (end_time - start_time);
170 EnforceBudgetLevelRestrictions();
171
172 if (!reporting_callback_.is_null() && old_budget_level.InSecondsF() > 0 &&
173 current_budget_level_.InSecondsF() < 0) {
174 reporting_callback_.Run(-current_budget_level_ / cpu_percentage_);
175 }
176 }
177 }
178
179 const char* TimeBudgetPool::Name() const {
180 return name_;
181 }
182
183 void TimeBudgetPool::AsValueInto(base::trace_event::TracedValue* state,
184 base::TimeTicks now) const {
185 state->BeginDictionary(name_);
186
187 state->SetString("name", name_);
188 state->SetDouble("time_budget", cpu_percentage_);
189 state->SetDouble("time_budget_level_in_seconds",
190 current_budget_level_.InSecondsF());
191 state->SetDouble("last_checkpoint_seconds_ago",
192 (now - last_checkpoint_).InSecondsF());
193 state->SetBoolean("is_enabled", is_enabled_);
194
195 state->BeginArray("task_queues");
196 for (TaskQueue* queue : associated_task_queues_) {
197 state->AppendString(PointerToId(queue));
198 }
199 state->EndArray();
200
201 state->EndDictionary();
202 }
203
204 void TimeBudgetPool::Advance(base::TimeTicks now) {
205 if (now > last_checkpoint_) {
206 if (is_enabled_) {
207 current_budget_level_ += cpu_percentage_ * (now - last_checkpoint_);
208 EnforceBudgetLevelRestrictions();
209 }
210 last_checkpoint_ = now;
211 }
212 }
213
214 void TimeBudgetPool::BlockThrottledQueues(base::TimeTicks now) {
215 for (TaskQueue* queue : associated_task_queues_) {
216 if (!task_queue_throttler_->IsThrottled(queue))
217 continue;
218
219 queue->InsertFence(TaskQueue::InsertFencePosition::BEGINNING_OF_TIME);
220 task_queue_throttler_->MaybeSchedulePumpQueue(FROM_HERE, now, queue,
221 base::nullopt);
222 }
223 }
224
225 void TimeBudgetPool::EnforceBudgetLevelRestrictions() {
226 if (max_budget_level_) {
227 current_budget_level_ =
228 std::min(current_budget_level_, max_budget_level_.value());
229 }
230 if (max_throttling_duration_) {
231 // Current budget level may be negative.
232 current_budget_level_ =
233 std::max(current_budget_level_,
234 -max_throttling_duration_.value() * cpu_percentage_);
235 }
236 }
237
238 } // namespace scheduler
239 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698