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

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

Issue 2798563003: [scheduler] Add TaskQueue::Observer (Closed)
Patch Set: Rebased Created 3 years, 8 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 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 #include "platform/scheduler/renderer/task_queue_throttler.h" 5 #include "platform/scheduler/renderer/task_queue_throttler.h"
6 6
7 #include <cstdint> 7 #include <cstdint>
8 8
9 #include "base/format_macros.h" 9 #include "base/format_macros.h"
10 #include "base/logging.h" 10 #include "base/logging.h"
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
72 72
73 } // namespace 73 } // namespace
74 74
75 TaskQueueThrottler::TaskQueueThrottler( 75 TaskQueueThrottler::TaskQueueThrottler(
76 RendererSchedulerImpl* renderer_scheduler, 76 RendererSchedulerImpl* renderer_scheduler,
77 const char* tracing_category) 77 const char* tracing_category)
78 : task_runner_(renderer_scheduler->ControlTaskRunner()), 78 : task_runner_(renderer_scheduler->ControlTaskRunner()),
79 renderer_scheduler_(renderer_scheduler), 79 renderer_scheduler_(renderer_scheduler),
80 tick_clock_(renderer_scheduler->tick_clock()), 80 tick_clock_(renderer_scheduler->tick_clock()),
81 tracing_category_(tracing_category), 81 tracing_category_(tracing_category),
82 time_domain_(new ThrottledTimeDomain(this, tracing_category)), 82 time_domain_(new ThrottledTimeDomain(tracing_category)),
83 allow_throttling_(true), 83 allow_throttling_(true),
84 weak_factory_(this) { 84 weak_factory_(this) {
85 pump_throttled_tasks_closure_.Reset(base::Bind( 85 pump_throttled_tasks_closure_.Reset(base::Bind(
86 &TaskQueueThrottler::PumpThrottledTasks, weak_factory_.GetWeakPtr())); 86 &TaskQueueThrottler::PumpThrottledTasks, weak_factory_.GetWeakPtr()));
87 forward_immediate_work_callback_ = 87 forward_immediate_work_callback_ =
88 base::Bind(&TaskQueueThrottler::OnTimeDomainHasImmediateWork, 88 base::Bind(&TaskQueueThrottler::OnQueueNextWakeUpChanged,
89 weak_factory_.GetWeakPtr()); 89 weak_factory_.GetWeakPtr());
90 90
91 renderer_scheduler_->RegisterTimeDomain(time_domain_.get()); 91 renderer_scheduler_->RegisterTimeDomain(time_domain_.get());
92 } 92 }
93 93
94 TaskQueueThrottler::~TaskQueueThrottler() { 94 TaskQueueThrottler::~TaskQueueThrottler() {
95 // It's possible for queues to be still throttled, so we need to tidy up 95 // It's possible for queues to be still throttled, so we need to tidy up
96 // before unregistering the time domain. 96 // before unregistering the time domain.
97 for (const TaskQueueMap::value_type& map_entry : queue_details_) { 97 for (const TaskQueueMap::value_type& map_entry : queue_details_) {
98 TaskQueue* task_queue = map_entry.first; 98 TaskQueue* task_queue = map_entry.first;
99 if (IsThrottled(task_queue)) { 99 if (IsThrottled(task_queue)) {
100 task_queue->SetTimeDomain(renderer_scheduler_->real_time_domain()); 100 task_queue->SetTimeDomain(renderer_scheduler_->real_time_domain());
101 task_queue->RemoveFence(); 101 task_queue->RemoveFence();
102 } 102 }
103 if (map_entry.second.throttling_ref_count != 0)
104 task_queue->SetObserver(nullptr);
103 } 105 }
104 106
105 renderer_scheduler_->UnregisterTimeDomain(time_domain_.get()); 107 renderer_scheduler_->UnregisterTimeDomain(time_domain_.get());
106 } 108 }
107 109
108 void TaskQueueThrottler::IncreaseThrottleRefCount(TaskQueue* task_queue) { 110 void TaskQueueThrottler::IncreaseThrottleRefCount(TaskQueue* task_queue) {
109 DCHECK_NE(task_queue, task_runner_.get()); 111 DCHECK_NE(task_queue, task_runner_.get());
110 112
111 std::pair<TaskQueueMap::iterator, bool> insert_result = 113 std::pair<TaskQueueMap::iterator, bool> insert_result =
112 queue_details_.insert(std::make_pair(task_queue, Metadata())); 114 queue_details_.insert(std::make_pair(task_queue, Metadata()));
113 insert_result.first->second.throttling_ref_count++; 115 insert_result.first->second.throttling_ref_count++;
114 116
115 // If ref_count is 1, the task queue is newly throttled. 117 // If ref_count is 1, the task queue is newly throttled.
116 if (insert_result.first->second.throttling_ref_count != 1) 118 if (insert_result.first->second.throttling_ref_count != 1)
117 return; 119 return;
118 120
119 TRACE_EVENT1(tracing_category_, "TaskQueueThrottler_TaskQueueThrottled", 121 TRACE_EVENT1(tracing_category_, "TaskQueueThrottler_TaskQueueThrottled",
120 "task_queue", task_queue); 122 "task_queue", task_queue);
121 123
124 task_queue->SetObserver(this);
125
122 if (!allow_throttling_) 126 if (!allow_throttling_)
123 return; 127 return;
124 128
125 task_queue->SetTimeDomain(time_domain_.get()); 129 task_queue->SetTimeDomain(time_domain_.get());
126 // This blocks any tasks from |task_queue| until PumpThrottledTasks() to 130 // This blocks any tasks from |task_queue| until PumpThrottledTasks() to
127 // enforce task alignment. 131 // enforce task alignment.
128 task_queue->InsertFence(TaskQueue::InsertFencePosition::BEGINNING_OF_TIME); 132 task_queue->InsertFence(TaskQueue::InsertFencePosition::BEGINNING_OF_TIME);
129 133
130 if (!task_queue->IsQueueEnabled()) 134 if (!task_queue->IsQueueEnabled())
131 return; 135 return;
132 136
133 if (!task_queue->IsEmpty()) { 137 if (!task_queue->IsEmpty()) {
134 if (task_queue->HasPendingImmediateWork()) { 138 LazyNow lazy_now(tick_clock_);
135 OnTimeDomainHasImmediateWork(task_queue); 139 OnQueueNextWakeUpChanged(task_queue,
136 } else { 140 NextTaskRunTime(&lazy_now, task_queue).value());
137 OnTimeDomainHasDelayedWork(task_queue);
138 }
139 } 141 }
140 } 142 }
141 143
142 void TaskQueueThrottler::DecreaseThrottleRefCount(TaskQueue* task_queue) { 144 void TaskQueueThrottler::DecreaseThrottleRefCount(TaskQueue* task_queue) {
143 TaskQueueMap::iterator iter = queue_details_.find(task_queue); 145 TaskQueueMap::iterator iter = queue_details_.find(task_queue);
144 146
145 if (iter == queue_details_.end() || 147 if (iter == queue_details_.end() ||
146 --iter->second.throttling_ref_count != 0) { 148 --iter->second.throttling_ref_count != 0) {
147 return; 149 return;
148 } 150 }
149 151
150 TRACE_EVENT1(tracing_category_, "TaskQueueThrottler_TaskQueueUnthrottled", 152 TRACE_EVENT1(tracing_category_, "TaskQueueThrottler_TaskQueueUnthrottled",
151 "task_queue", task_queue); 153 "task_queue", task_queue);
152 154
155 task_queue->SetObserver(nullptr);
156
153 MaybeDeleteQueueMetadata(iter); 157 MaybeDeleteQueueMetadata(iter);
154 158
155 if (!allow_throttling_) 159 if (!allow_throttling_)
156 return; 160 return;
157 161
158 task_queue->SetTimeDomain(renderer_scheduler_->real_time_domain()); 162 task_queue->SetTimeDomain(renderer_scheduler_->real_time_domain());
159 task_queue->RemoveFence(); 163 task_queue->RemoveFence();
160 } 164 }
161 165
162 bool TaskQueueThrottler::IsThrottled(TaskQueue* task_queue) const { 166 bool TaskQueueThrottler::IsThrottled(TaskQueue* task_queue) const {
(...skipping 13 matching lines...) Expand all
176 180
177 LazyNow lazy_now(tick_clock_); 181 LazyNow lazy_now(tick_clock_);
178 std::unordered_set<BudgetPool*> budget_pools = find_it->second.budget_pools; 182 std::unordered_set<BudgetPool*> budget_pools = find_it->second.budget_pools;
179 for (BudgetPool* budget_pool : budget_pools) { 183 for (BudgetPool* budget_pool : budget_pools) {
180 budget_pool->RemoveQueue(lazy_now.Now(), task_queue); 184 budget_pool->RemoveQueue(lazy_now.Now(), task_queue);
181 } 185 }
182 186
183 // Iterator may have been deleted by BudgetPool::RemoveQueue, so don't 187 // Iterator may have been deleted by BudgetPool::RemoveQueue, so don't
184 // use it here. 188 // use it here.
185 queue_details_.erase(task_queue); 189 queue_details_.erase(task_queue);
190
191 // NOTE: Observer is automatically unregistered when unregistering task queue.
186 } 192 }
187 193
188 void TaskQueueThrottler::OnTimeDomainHasImmediateWork(TaskQueue* queue) { 194 void TaskQueueThrottler::OnQueueNextWakeUpChanged(
189 // Forward to the main thread if called from another thread 195 TaskQueue* queue,
196 base::TimeTicks next_wake_up) {
190 if (!task_runner_->RunsTasksOnCurrentThread()) { 197 if (!task_runner_->RunsTasksOnCurrentThread()) {
191 task_runner_->PostTask(FROM_HERE, 198 task_runner_->PostTask(
192 base::Bind(forward_immediate_work_callback_, queue)); 199 FROM_HERE,
200 base::Bind(forward_immediate_work_callback_, queue, next_wake_up));
193 return; 201 return;
194 } 202 }
203
195 TRACE_EVENT0(tracing_category_, 204 TRACE_EVENT0(tracing_category_,
196 "TaskQueueThrottler::OnTimeDomainHasImmediateWork"); 205 "TaskQueueThrottler::OnQueueNextWakeUpChanged");
197 206
198 // We don't expect this to get called for disabled queues, but we can't DCHECK 207 // We don't expect this to get called for disabled queues, but we can't DCHECK
199 // because of the above thread hop. Just bail out if the queue is disabled. 208 // because of the above thread hop. Just bail out if the queue is disabled.
200 if (!queue->IsQueueEnabled()) 209 if (!queue->IsQueueEnabled())
201 return; 210 return;
202 211
203 base::TimeTicks now = tick_clock_->NowTicks(); 212 base::TimeTicks now = tick_clock_->NowTicks();
204 base::TimeTicks next_allowed_run_time = GetNextAllowedRunTime(now, queue); 213 MaybeSchedulePumpThrottledTasks(
205 MaybeSchedulePumpThrottledTasks(FROM_HERE, now, next_allowed_run_time); 214 FROM_HERE, now,
206 } 215 std::max(GetNextAllowedRunTime(now, queue), next_wake_up));
207
208 void TaskQueueThrottler::OnTimeDomainHasDelayedWork(TaskQueue* queue) {
209 TRACE_EVENT0(tracing_category_,
210 "TaskQueueThrottler::OnTimeDomainHasDelayedWork");
211 DCHECK(queue->IsQueueEnabled());
212 base::TimeTicks now = tick_clock_->NowTicks();
213 LazyNow lazy_now(now);
214
215 base::Optional<base::TimeTicks> next_scheduled_delayed_task =
216 NextTaskRunTime(&lazy_now, queue);
217 DCHECK(next_scheduled_delayed_task);
218 MaybeSchedulePumpThrottledTasks(FROM_HERE, now,
219 next_scheduled_delayed_task.value());
220 } 216 }
221 217
222 void TaskQueueThrottler::PumpThrottledTasks() { 218 void TaskQueueThrottler::PumpThrottledTasks() {
223 TRACE_EVENT0(tracing_category_, "TaskQueueThrottler::PumpThrottledTasks"); 219 TRACE_EVENT0(tracing_category_, "TaskQueueThrottler::PumpThrottledTasks");
224 pending_pump_throttled_tasks_runtime_.reset(); 220 pending_pump_throttled_tasks_runtime_.reset();
225 221
226 LazyNow lazy_now(tick_clock_); 222 LazyNow lazy_now(tick_clock_);
227 base::Optional<base::TimeTicks> next_scheduled_delayed_task; 223 base::Optional<base::TimeTicks> next_scheduled_delayed_task;
228 224
229 for (const TaskQueueMap::value_type& map_entry : queue_details_) { 225 for (const TaskQueueMap::value_type& map_entry : queue_details_) {
(...skipping 258 matching lines...) Expand 10 before | Expand all | Expand 10 after
488 queue->InsertFence(TaskQueue::InsertFencePosition::BEGINNING_OF_TIME); 484 queue->InsertFence(TaskQueue::InsertFencePosition::BEGINNING_OF_TIME);
489 queue->SetTimeDomain(time_domain_.get()); 485 queue->SetTimeDomain(time_domain_.get());
490 SchedulePumpQueue(FROM_HERE, lazy_now.Now(), queue); 486 SchedulePumpQueue(FROM_HERE, lazy_now.Now(), queue);
491 } 487 }
492 488
493 TRACE_EVENT0(tracing_category_, "TaskQueueThrottler_EnableThrottling"); 489 TRACE_EVENT0(tracing_category_, "TaskQueueThrottler_EnableThrottling");
494 } 490 }
495 491
496 } // namespace scheduler 492 } // namespace scheduler
497 } // namespace blink 493 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698