OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 "content/renderer/scheduler/task_queue_manager.h" | 5 #include "content/renderer/scheduler/task_queue_manager.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/debug/trace_event.h" | 8 #include "base/debug/trace_event.h" |
| 9 #include "base/debug/trace_event_argument.h" |
9 #include "content/renderer/scheduler/task_queue_selector.h" | 10 #include "content/renderer/scheduler/task_queue_selector.h" |
10 | 11 |
11 namespace content { | 12 namespace content { |
12 namespace internal { | 13 namespace internal { |
13 | 14 |
14 class TaskQueue : public base::SingleThreadTaskRunner { | 15 class TaskQueue : public base::SingleThreadTaskRunner { |
15 public: | 16 public: |
16 TaskQueue(TaskQueueManager* task_queue_manager); | 17 TaskQueue(TaskQueueManager* task_queue_manager); |
17 | 18 |
18 // base::SingleThreadTaskRunner implementation. | 19 // base::SingleThreadTaskRunner implementation. |
(...skipping 15 matching lines...) Expand all Loading... |
34 void SetAutoPump(bool auto_pump); | 35 void SetAutoPump(bool auto_pump); |
35 void PumpQueue(); | 36 void PumpQueue(); |
36 | 37 |
37 bool UpdateWorkQueue(); | 38 bool UpdateWorkQueue(); |
38 base::PendingTask TakeTaskFromWorkQueue(); | 39 base::PendingTask TakeTaskFromWorkQueue(); |
39 | 40 |
40 void WillDeleteTaskQueueManager(); | 41 void WillDeleteTaskQueueManager(); |
41 | 42 |
42 base::TaskQueue& work_queue() { return work_queue_; } | 43 base::TaskQueue& work_queue() { return work_queue_; } |
43 | 44 |
| 45 void set_name(const char* name) { name_ = name; } |
| 46 |
| 47 void AsValueInto(base::debug::TracedValue* state) const; |
| 48 |
44 private: | 49 private: |
45 ~TaskQueue() override; | 50 ~TaskQueue() override; |
46 | 51 |
47 void PumpQueueLocked(); | 52 void PumpQueueLocked(); |
48 void EnqueueTaskLocked(const base::PendingTask& pending_task); | 53 void EnqueueTaskLocked(const base::PendingTask& pending_task); |
49 | 54 |
| 55 void TraceWorkQueueSize() const; |
| 56 static void QueueAsValueInto(const base::TaskQueue& queue, |
| 57 base::debug::TracedValue* state); |
| 58 static void TaskAsValueInto(const base::PendingTask& task, |
| 59 base::debug::TracedValue* state); |
| 60 |
50 // This lock protects all members except the work queue. | 61 // This lock protects all members except the work queue. |
51 mutable base::Lock lock_; | 62 mutable base::Lock lock_; |
52 TaskQueueManager* task_queue_manager_; | 63 TaskQueueManager* task_queue_manager_; |
53 base::TaskQueue incoming_queue_; | 64 base::TaskQueue incoming_queue_; |
54 bool auto_pump_; | 65 bool auto_pump_; |
| 66 const char* name_; |
55 | 67 |
56 base::TaskQueue work_queue_; | 68 base::TaskQueue work_queue_; |
57 | 69 |
58 DISALLOW_COPY_AND_ASSIGN(TaskQueue); | 70 DISALLOW_COPY_AND_ASSIGN(TaskQueue); |
59 }; | 71 }; |
60 | 72 |
61 TaskQueue::TaskQueue(TaskQueueManager* task_queue_manager) | 73 TaskQueue::TaskQueue(TaskQueueManager* task_queue_manager) |
62 : task_queue_manager_(task_queue_manager), auto_pump_(true) { | 74 : task_queue_manager_(task_queue_manager), |
| 75 auto_pump_(true), |
| 76 name_(nullptr) { |
63 } | 77 } |
64 | 78 |
65 TaskQueue::~TaskQueue() { | 79 TaskQueue::~TaskQueue() { |
66 } | 80 } |
67 | 81 |
68 void TaskQueue::WillDeleteTaskQueueManager() { | 82 void TaskQueue::WillDeleteTaskQueueManager() { |
69 base::AutoLock lock(lock_); | 83 base::AutoLock lock(lock_); |
70 task_queue_manager_ = nullptr; | 84 task_queue_manager_ = nullptr; |
71 } | 85 } |
72 | 86 |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
118 | 132 |
119 bool TaskQueue::UpdateWorkQueue() { | 133 bool TaskQueue::UpdateWorkQueue() { |
120 if (!work_queue_.empty()) | 134 if (!work_queue_.empty()) |
121 return true; | 135 return true; |
122 | 136 |
123 { | 137 { |
124 base::AutoLock lock(lock_); | 138 base::AutoLock lock(lock_); |
125 if (!auto_pump_ || incoming_queue_.empty()) | 139 if (!auto_pump_ || incoming_queue_.empty()) |
126 return false; | 140 return false; |
127 work_queue_.Swap(&incoming_queue_); | 141 work_queue_.Swap(&incoming_queue_); |
| 142 TraceWorkQueueSize(); |
128 return true; | 143 return true; |
129 } | 144 } |
130 } | 145 } |
131 | 146 |
132 base::PendingTask TaskQueue::TakeTaskFromWorkQueue() { | 147 base::PendingTask TaskQueue::TakeTaskFromWorkQueue() { |
133 base::PendingTask pending_task = work_queue_.front(); | 148 base::PendingTask pending_task = work_queue_.front(); |
134 work_queue_.pop(); | 149 work_queue_.pop(); |
| 150 TraceWorkQueueSize(); |
135 return pending_task; | 151 return pending_task; |
136 } | 152 } |
137 | 153 |
| 154 void TaskQueue::TraceWorkQueueSize() const { |
| 155 if (!name_) |
| 156 return; |
| 157 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), name_, |
| 158 work_queue_.size()); |
| 159 } |
| 160 |
138 void TaskQueue::EnqueueTask(const base::PendingTask& pending_task) { | 161 void TaskQueue::EnqueueTask(const base::PendingTask& pending_task) { |
139 base::AutoLock lock(lock_); | 162 base::AutoLock lock(lock_); |
140 EnqueueTaskLocked(pending_task); | 163 EnqueueTaskLocked(pending_task); |
141 } | 164 } |
142 | 165 |
143 void TaskQueue::EnqueueTaskLocked(const base::PendingTask& pending_task) { | 166 void TaskQueue::EnqueueTaskLocked(const base::PendingTask& pending_task) { |
144 lock_.AssertAcquired(); | 167 lock_.AssertAcquired(); |
145 if (!task_queue_manager_) | 168 if (!task_queue_manager_) |
146 return; | 169 return; |
147 if (auto_pump_ && incoming_queue_.empty()) | 170 if (auto_pump_ && incoming_queue_.empty()) |
(...skipping 19 matching lines...) Expand all Loading... |
167 } | 190 } |
168 if (!work_queue_.empty()) | 191 if (!work_queue_.empty()) |
169 task_queue_manager_->PostDoWorkOnMainRunner(); | 192 task_queue_manager_->PostDoWorkOnMainRunner(); |
170 } | 193 } |
171 | 194 |
172 void TaskQueue::PumpQueue() { | 195 void TaskQueue::PumpQueue() { |
173 base::AutoLock lock(lock_); | 196 base::AutoLock lock(lock_); |
174 PumpQueueLocked(); | 197 PumpQueueLocked(); |
175 } | 198 } |
176 | 199 |
177 } // namespace | 200 void TaskQueue::AsValueInto(base::debug::TracedValue* state) const { |
| 201 base::AutoLock lock(lock_); |
| 202 state->BeginDictionary(); |
| 203 if (name_) |
| 204 state->SetString("name", name_); |
| 205 state->SetBoolean("auto_pump", auto_pump_); |
| 206 state->BeginArray("incoming_queue"); |
| 207 QueueAsValueInto(incoming_queue_, state); |
| 208 state->EndArray(); |
| 209 state->BeginArray("work_queue"); |
| 210 QueueAsValueInto(work_queue_, state); |
| 211 state->EndArray(); |
| 212 state->EndDictionary(); |
| 213 } |
| 214 |
| 215 // static |
| 216 void TaskQueue::QueueAsValueInto(const base::TaskQueue& queue, |
| 217 base::debug::TracedValue* state) { |
| 218 base::TaskQueue queue_copy(queue); |
| 219 while (!queue_copy.empty()) { |
| 220 TaskAsValueInto(queue_copy.front(), state); |
| 221 queue_copy.pop(); |
| 222 } |
| 223 } |
| 224 |
| 225 // static |
| 226 void TaskQueue::TaskAsValueInto(const base::PendingTask& task, |
| 227 base::debug::TracedValue* state) { |
| 228 state->BeginDictionary(); |
| 229 state->SetString("posted_from", task.posted_from.ToString()); |
| 230 state->SetInteger("sequence_num", task.sequence_num); |
| 231 state->SetBoolean("nestable", task.nestable); |
| 232 state->SetBoolean("is_high_res", task.is_high_res); |
| 233 state->SetDouble( |
| 234 "time_posted", |
| 235 (task.time_posted - base::TimeTicks()).InMicroseconds() / 1000.0L); |
| 236 state->SetDouble( |
| 237 "delayed_run_time", |
| 238 (task.delayed_run_time - base::TimeTicks()).InMicroseconds() / 1000.0L); |
| 239 state->EndDictionary(); |
| 240 } |
| 241 |
| 242 } // namespace internal |
178 | 243 |
179 TaskQueueManager::TaskQueueManager( | 244 TaskQueueManager::TaskQueueManager( |
180 size_t task_queue_count, | 245 size_t task_queue_count, |
181 scoped_refptr<base::SingleThreadTaskRunner> main_task_runner, | 246 scoped_refptr<base::SingleThreadTaskRunner> main_task_runner, |
182 TaskQueueSelector* selector) | 247 TaskQueueSelector* selector) |
183 : main_task_runner_(main_task_runner), | 248 : main_task_runner_(main_task_runner), |
184 selector_(selector), | 249 selector_(selector), |
185 weak_factory_(this) { | 250 weak_factory_(this) { |
186 DCHECK(main_task_runner->RunsTasksOnCurrentThread()); | 251 DCHECK(main_task_runner->RunsTasksOnCurrentThread()); |
| 252 TRACE_EVENT_OBJECT_CREATED_WITH_ID( |
| 253 TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), "TaskQueueManager", |
| 254 this); |
187 | 255 |
188 task_queue_manager_weak_ptr_ = weak_factory_.GetWeakPtr(); | 256 task_queue_manager_weak_ptr_ = weak_factory_.GetWeakPtr(); |
189 for (size_t i = 0; i < task_queue_count; i++) { | 257 for (size_t i = 0; i < task_queue_count; i++) { |
190 scoped_refptr<internal::TaskQueue> queue( | 258 scoped_refptr<internal::TaskQueue> queue( |
191 make_scoped_refptr(new internal::TaskQueue(this))); | 259 make_scoped_refptr(new internal::TaskQueue(this))); |
192 queues_.push_back(queue); | 260 queues_.push_back(queue); |
193 } | 261 } |
194 | 262 |
195 std::vector<const base::TaskQueue*> work_queues; | 263 std::vector<const base::TaskQueue*> work_queues; |
196 for (const auto& queue: queues_) | 264 for (const auto& queue: queues_) |
197 work_queues.push_back(&queue->work_queue()); | 265 work_queues.push_back(&queue->work_queue()); |
198 selector_->RegisterWorkQueues(work_queues); | 266 selector_->RegisterWorkQueues(work_queues); |
199 } | 267 } |
200 | 268 |
201 TaskQueueManager::~TaskQueueManager() { | 269 TaskQueueManager::~TaskQueueManager() { |
| 270 TRACE_EVENT_OBJECT_DELETED_WITH_ID( |
| 271 TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), "TaskQueueManager", |
| 272 this); |
202 for (auto& queue : queues_) | 273 for (auto& queue : queues_) |
203 queue->WillDeleteTaskQueueManager(); | 274 queue->WillDeleteTaskQueueManager(); |
204 } | 275 } |
205 | 276 |
206 internal::TaskQueue* TaskQueueManager::Queue(size_t queue_index) const { | 277 internal::TaskQueue* TaskQueueManager::Queue(size_t queue_index) const { |
207 DCHECK_LT(queue_index, queues_.size()); | 278 DCHECK_LT(queue_index, queues_.size()); |
208 return queues_[queue_index].get(); | 279 return queues_[queue_index].get(); |
209 } | 280 } |
210 | 281 |
211 scoped_refptr<base::SingleThreadTaskRunner> | 282 scoped_refptr<base::SingleThreadTaskRunner> |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
245 main_task_runner_->PostTask( | 316 main_task_runner_->PostTask( |
246 FROM_HERE, Bind(&TaskQueueManager::DoWork, task_queue_manager_weak_ptr_)); | 317 FROM_HERE, Bind(&TaskQueueManager::DoWork, task_queue_manager_weak_ptr_)); |
247 } | 318 } |
248 | 319 |
249 void TaskQueueManager::DoWork() { | 320 void TaskQueueManager::DoWork() { |
250 main_thread_checker_.CalledOnValidThread(); | 321 main_thread_checker_.CalledOnValidThread(); |
251 if (!UpdateWorkQueues()) | 322 if (!UpdateWorkQueues()) |
252 return; | 323 return; |
253 | 324 |
254 size_t queue_index; | 325 size_t queue_index; |
255 if (!selector_->SelectWorkQueueToService(&queue_index)) | 326 if (!SelectWorkQueueToService(&queue_index)) |
256 return; | 327 return; |
257 PostDoWorkOnMainRunner(); | 328 PostDoWorkOnMainRunner(); |
258 RunTaskFromWorkQueue(queue_index); | 329 RunTaskFromWorkQueue(queue_index); |
259 } | 330 } |
260 | 331 |
| 332 bool TaskQueueManager::SelectWorkQueueToService(size_t* out_queue_index) { |
| 333 bool should_run = selector_->SelectWorkQueueToService(out_queue_index); |
| 334 TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID( |
| 335 TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), "TaskQueueManager", this, |
| 336 AsValueWithSelectorResult(should_run, *out_queue_index)); |
| 337 return should_run; |
| 338 } |
| 339 |
261 void TaskQueueManager::DidQueueTask(base::PendingTask* pending_task) { | 340 void TaskQueueManager::DidQueueTask(base::PendingTask* pending_task) { |
262 pending_task->sequence_num = task_sequence_num_.GetNext(); | 341 pending_task->sequence_num = task_sequence_num_.GetNext(); |
263 task_annotator_.DidQueueTask("TaskQueueManager::PostTask", *pending_task); | 342 task_annotator_.DidQueueTask("TaskQueueManager::PostTask", *pending_task); |
264 } | 343 } |
265 | 344 |
266 void TaskQueueManager::RunTaskFromWorkQueue(size_t queue_index) { | 345 void TaskQueueManager::RunTaskFromWorkQueue(size_t queue_index) { |
267 main_thread_checker_.CalledOnValidThread(); | 346 main_thread_checker_.CalledOnValidThread(); |
268 internal::TaskQueue* queue = Queue(queue_index); | 347 internal::TaskQueue* queue = Queue(queue_index); |
269 base::PendingTask pending_task = queue->TakeTaskFromWorkQueue(); | 348 base::PendingTask pending_task = queue->TakeTaskFromWorkQueue(); |
270 task_annotator_.RunTask( | 349 task_annotator_.RunTask( |
(...skipping 13 matching lines...) Expand all Loading... |
284 } | 363 } |
285 | 364 |
286 bool TaskQueueManager::PostNonNestableDelayedTask( | 365 bool TaskQueueManager::PostNonNestableDelayedTask( |
287 const tracked_objects::Location& from_here, | 366 const tracked_objects::Location& from_here, |
288 const base::Closure& task, | 367 const base::Closure& task, |
289 base::TimeDelta delay) { | 368 base::TimeDelta delay) { |
290 // Defer non-nestable work to the main task runner. | 369 // Defer non-nestable work to the main task runner. |
291 return main_task_runner_->PostNonNestableDelayedTask(from_here, task, delay); | 370 return main_task_runner_->PostNonNestableDelayedTask(from_here, task, delay); |
292 } | 371 } |
293 | 372 |
| 373 void TaskQueueManager::SetQueueName(size_t queue_index, const char* name) { |
| 374 main_thread_checker_.CalledOnValidThread(); |
| 375 internal::TaskQueue* queue = Queue(queue_index); |
| 376 queue->set_name(name); |
| 377 } |
| 378 |
| 379 scoped_refptr<base::debug::ConvertableToTraceFormat> |
| 380 TaskQueueManager::AsValueWithSelectorResult(bool should_run, |
| 381 size_t selected_queue) const { |
| 382 main_thread_checker_.CalledOnValidThread(); |
| 383 scoped_refptr<base::debug::TracedValue> state = |
| 384 new base::debug::TracedValue(); |
| 385 state->BeginArray("queues"); |
| 386 for (auto& queue : queues_) |
| 387 queue->AsValueInto(state.get()); |
| 388 state->EndArray(); |
| 389 state->BeginDictionary("selector"); |
| 390 selector_->AsValueInto(state.get()); |
| 391 state->EndDictionary(); |
| 392 if (should_run) |
| 393 state->SetInteger("selected_queue", selected_queue); |
| 394 return state; |
| 395 } |
| 396 |
294 } // namespace content | 397 } // namespace content |
OLD | NEW |