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

Side by Side Diff: content/renderer/raster_worker_pool.cc

Issue 1576133002: Add category handling to RasterWorkerPool (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@hihi
Patch Set: Created 4 years, 11 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 "content/renderer/raster_worker_pool.h" 5 #include "content/renderer/raster_worker_pool.h"
6 6
7 #include <stddef.h> 7 #include <string>
8 #include <stdint.h>
9
10 #include <utility> 8 #include <utility>
9 #include <vector>
11 10
12 #include "base/strings/stringprintf.h" 11 #include "base/strings/stringprintf.h"
13 #include "base/threading/thread_restrictions.h" 12 #include "base/threading/thread_restrictions.h"
14 #include "base/trace_event/trace_event.h" 13 #include "base/trace_event/trace_event.h"
14 #include "cc/base/math_util.h"
15 #include "cc/raster/task_category.h"
15 16
16 namespace content { 17 namespace content {
18 namespace {
19
20 // A thread which forwards to RasterWorkerPool::Run with the runnable
21 // categories.
22 class RasterWorkerPoolThread : public base::SimpleThread {
23 public:
24 explicit RasterWorkerPoolThread(const std::string& name_prefix,
25 const Options& options,
26 RasterWorkerPool* pool,
27 std::vector<cc::TaskCategory> categories)
28 : SimpleThread(name_prefix, options),
29 pool_(pool),
30 categories_(categories) {}
31
32 void Run() override { pool_->Run(categories_); }
33
34 private:
35 RasterWorkerPool* const pool_;
36 const std::vector<cc::TaskCategory> categories_;
37 };
38
39 } // namespace
17 40
18 // A sequenced task runner which posts tasks to a RasterWorkerPool. 41 // A sequenced task runner which posts tasks to a RasterWorkerPool.
19 class RasterWorkerPool::RasterWorkerPoolSequencedTaskRunner 42 class RasterWorkerPool::RasterWorkerPoolSequencedTaskRunner
20 : public base::SequencedTaskRunner { 43 : public base::SequencedTaskRunner {
21 public: 44 public:
22 explicit RasterWorkerPoolSequencedTaskRunner( 45 explicit RasterWorkerPoolSequencedTaskRunner(
23 cc::TaskGraphRunner* task_graph_runner) 46 cc::TaskGraphRunner* task_graph_runner)
24 : task_graph_runner_(task_graph_runner), 47 : task_graph_runner_(task_graph_runner),
25 namespace_token_(task_graph_runner->GetNamespaceToken()) {} 48 namespace_token_(task_graph_runner->GetNamespaceToken()) {}
26 49
(...skipping 18 matching lines...) Expand all
45 68
46 tasks_.erase(tasks_.begin(), tasks_.begin() + completed_tasks_.size()); 69 tasks_.erase(tasks_.begin(), tasks_.begin() + completed_tasks_.size());
47 70
48 tasks_.push_back(make_scoped_refptr(new ClosureTask(task))); 71 tasks_.push_back(make_scoped_refptr(new ClosureTask(task)));
49 graph_.Reset(); 72 graph_.Reset();
50 for (const auto& graph_task : tasks_) { 73 for (const auto& graph_task : tasks_) {
51 int dependencies = 0; 74 int dependencies = 0;
52 if (!graph_.nodes.empty()) 75 if (!graph_.nodes.empty())
53 dependencies = 1; 76 dependencies = 1;
54 77
55 cc::TaskGraph::Node node(graph_task.get(), 0u /* category */, 78 // Treat any tasks that are enqueued through the SequencedTaskRunner as
79 // FOREGROUND priority. We don't have enough information to know the
80 // actual priority of such tasks, so we run them as soon as possible.
81 cc::TaskGraph::Node node(graph_task.get(), cc::TASK_CATEGORY_FOREGROUND,
56 0u /* priority */, dependencies); 82 0u /* priority */, dependencies);
57 if (dependencies) { 83 if (dependencies) {
58 graph_.edges.push_back( 84 graph_.edges.push_back(
59 cc::TaskGraph::Edge(graph_.nodes.back().task, node.task)); 85 cc::TaskGraph::Edge(graph_.nodes.back().task, node.task));
60 } 86 }
61 graph_.nodes.push_back(node); 87 graph_.nodes.push_back(node);
62 } 88 }
63 task_graph_runner_->ScheduleTasks(namespace_token_, &graph_); 89 task_graph_runner_->ScheduleTasks(namespace_token_, &graph_);
64 completed_tasks_.clear(); 90 completed_tasks_.clear();
65 return true; 91 return true;
(...skipping 23 matching lines...) Expand all
89 }; 115 };
90 116
91 RasterWorkerPool::RasterWorkerPool() 117 RasterWorkerPool::RasterWorkerPool()
92 : namespace_token_(GetNamespaceToken()), 118 : namespace_token_(GetNamespaceToken()),
93 has_ready_to_run_tasks_cv_(&lock_), 119 has_ready_to_run_tasks_cv_(&lock_),
94 has_namespaces_with_finished_running_tasks_cv_(&lock_), 120 has_namespaces_with_finished_running_tasks_cv_(&lock_),
95 shutdown_(false) {} 121 shutdown_(false) {}
96 122
97 void RasterWorkerPool::Start( 123 void RasterWorkerPool::Start(
98 int num_threads, 124 int num_threads,
125 bool use_single_thread_for_background_raster_tasks,
99 const base::SimpleThread::Options& thread_options) { 126 const base::SimpleThread::Options& thread_options) {
100 DCHECK(threads_.empty()); 127 DCHECK(threads_.empty());
101 while (threads_.size() < static_cast<size_t>(num_threads)) { 128 while (threads_.size() < static_cast<size_t>(num_threads)) {
102 scoped_ptr<base::DelegateSimpleThread> thread( 129 // Determine the categories that each thread can run.
103 new base::DelegateSimpleThread( 130 std::vector<cc::TaskCategory> task_categories;
104 this, base::StringPrintf("CompositorTileWorker%u", 131
105 static_cast<unsigned>(threads_.size() + 1)) 132 // The first thread can run nonconcurrent tasks.
106 .c_str(), 133 if (threads_.size() == 0) {
107 thread_options)); 134 task_categories.push_back(cc::TASK_CATEGORY_NONCONCURRENT_FOREGROUND);
135 }
136
137 // All threads can run foreground tasks.
138 task_categories.push_back(cc::TASK_CATEGORY_FOREGROUND);
139
140 // If we've enabled the use of a single thread for background tasks, only
141 // the first thread will run background tasks. Otherwise all threads may run
142 // them.
143 if (threads_.size() == 0 ||
reveman 2016/01/13 23:09:30 hm, should we avoid using the same thread as NONCO
ericrk 2016/01/21 01:19:44 with this setup, low priority tasks will never run
reveman 2016/01/21 17:12:24 Sgtm
144 !use_single_thread_for_background_raster_tasks) {
145 task_categories.push_back(cc::TASK_CATEGORY_BACKGROUND);
146 }
147
148 scoped_ptr<base::SimpleThread> thread(new RasterWorkerPoolThread(
149 base::StringPrintf("CompositorTileWorker%u",
150 static_cast<unsigned>(threads_.size() + 1))
151 .c_str(),
152 thread_options, this, task_categories));
108 thread->Start(); 153 thread->Start();
109 threads_.push_back(std::move(thread)); 154 threads_.push_back(std::move(thread));
110 } 155 }
111 } 156 }
112 157
113 void RasterWorkerPool::Shutdown() { 158 void RasterWorkerPool::Shutdown() {
114 WaitForTasksToFinishRunning(namespace_token_); 159 WaitForTasksToFinishRunning(namespace_token_);
115 CollectCompletedTasks(namespace_token_, &completed_tasks_); 160 CollectCompletedTasks(namespace_token_, &completed_tasks_);
116 // Shutdown raster threads. 161 // Shutdown raster threads.
117 { 162 {
(...skipping 28 matching lines...) Expand all
146 cc::Task::Vector::iterator end = std::remove_if( 191 cc::Task::Vector::iterator end = std::remove_if(
147 tasks_.begin(), tasks_.end(), [this](const scoped_refptr<cc::Task>& e) { 192 tasks_.begin(), tasks_.end(), [this](const scoped_refptr<cc::Task>& e) {
148 return std::find(this->completed_tasks_.begin(), 193 return std::find(this->completed_tasks_.begin(),
149 this->completed_tasks_.end(), 194 this->completed_tasks_.end(),
150 e) != this->completed_tasks_.end(); 195 e) != this->completed_tasks_.end();
151 }); 196 });
152 tasks_.erase(end, tasks_.end()); 197 tasks_.erase(end, tasks_.end());
153 198
154 tasks_.push_back(make_scoped_refptr(new ClosureTask(task))); 199 tasks_.push_back(make_scoped_refptr(new ClosureTask(task)));
155 graph_.Reset(); 200 graph_.Reset();
156 for (const auto& graph_task : tasks_) 201 for (const auto& graph_task : tasks_) {
202 // Delayed tasks are assigned FOREGROUND category, ensuring that they run as
203 // soon as possible once their delay has expired.
157 graph_.nodes.push_back( 204 graph_.nodes.push_back(
158 cc::TaskGraph::Node(graph_task.get(), 0u /* category */, 205 cc::TaskGraph::Node(graph_task.get(), cc::TASK_CATEGORY_FOREGROUND,
159 0u /* priority */, 0u /* dependencies */)); 206 0u /* priority */, 0u /* dependencies */));
207 }
160 208
161 ScheduleTasksWithLockAcquired(namespace_token_, &graph_); 209 ScheduleTasksWithLockAcquired(namespace_token_, &graph_);
162 completed_tasks_.clear(); 210 completed_tasks_.clear();
163 return true; 211 return true;
164 } 212 }
165 213
166 bool RasterWorkerPool::RunsTasksOnCurrentThread() const { 214 bool RasterWorkerPool::RunsTasksOnCurrentThread() const {
167 return true; 215 return true;
168 } 216 }
169 217
170 // Overridden from base::DelegateSimpleThread::Delegate: 218 void RasterWorkerPool::Run(const std::vector<cc::TaskCategory>& categories) {
171 void RasterWorkerPool::Run() {
172 base::AutoLock lock(lock_); 219 base::AutoLock lock(lock_);
173 220
174 while (true) { 221 while (true) {
175 if (!RunTaskWithLockAcquired()) { 222 cc::TaskCategory category_to_run;
223 bool should_run = false;
224 for (const auto& category : categories) {
225 if (work_queue_.HasReadyToRunTasksForCategory(category)) {
226 should_run = true;
227 category_to_run = category;
228 }
229 }
reveman 2016/01/13 23:09:30 nit: move this code into a new utility function th
ericrk 2016/01/21 01:19:44 Good suggestion.
230
231 if (!should_run) {
176 // Exit when shutdown is set and no more tasks are pending. 232 // Exit when shutdown is set and no more tasks are pending.
177 if (shutdown_) 233 if (shutdown_)
178 break; 234 break;
179 235
180 // Wait for more tasks. 236 // Wait for more tasks.
181 has_ready_to_run_tasks_cv_.Wait(); 237 has_ready_to_run_tasks_cv_.Wait();
182 continue; 238 continue;
183 } 239 }
240 RunTaskWithLockAcquired(category_to_run);
184 } 241 }
185 } 242 }
186 243
187 void RasterWorkerPool::FlushForTesting() { 244 void RasterWorkerPool::FlushForTesting() {
188 base::AutoLock lock(lock_); 245 base::AutoLock lock(lock_);
189 246
190 while (!work_queue_.HasFinishedRunningTasksInAllNamespaces()) { 247 while (!work_queue_.HasFinishedRunningTasksInAllNamespaces()) {
191 has_namespaces_with_finished_running_tasks_cv_.Wait(); 248 has_namespaces_with_finished_running_tasks_cv_.Wait();
192 } 249 }
193 } 250 }
(...skipping 21 matching lines...) Expand all
215 } 272 }
216 273
217 void RasterWorkerPool::ScheduleTasksWithLockAcquired(cc::NamespaceToken token, 274 void RasterWorkerPool::ScheduleTasksWithLockAcquired(cc::NamespaceToken token,
218 cc::TaskGraph* graph) { 275 cc::TaskGraph* graph) {
219 DCHECK(token.IsValid()); 276 DCHECK(token.IsValid());
220 DCHECK(!cc::TaskGraphWorkQueue::DependencyMismatch(graph)); 277 DCHECK(!cc::TaskGraphWorkQueue::DependencyMismatch(graph));
221 DCHECK(!shutdown_); 278 DCHECK(!shutdown_);
222 279
223 work_queue_.ScheduleTasks(token, graph); 280 work_queue_.ScheduleTasks(token, graph);
224 281
225 // If there is more work available, wake up worker thread. 282 // If there is more work available, wake up the other worker threads.
226 if (work_queue_.HasReadyToRunTasks()) 283 if (work_queue_.HasReadyToRunTasks())
227 has_ready_to_run_tasks_cv_.Signal(); 284 has_ready_to_run_tasks_cv_.Broadcast();
228 } 285 }
229 286
230 void RasterWorkerPool::WaitForTasksToFinishRunning(cc::NamespaceToken token) { 287 void RasterWorkerPool::WaitForTasksToFinishRunning(cc::NamespaceToken token) {
231 TRACE_EVENT0("cc", "RasterWorkerPool::WaitForTasksToFinishRunning"); 288 TRACE_EVENT0("cc", "RasterWorkerPool::WaitForTasksToFinishRunning");
232 289
233 DCHECK(token.IsValid()); 290 DCHECK(token.IsValid());
234 291
235 { 292 {
236 base::AutoLock lock(lock_); 293 base::AutoLock lock(lock_);
237 base::ThreadRestrictions::ScopedAllowWait allow_wait; 294 base::ThreadRestrictions::ScopedAllowWait allow_wait;
(...skipping 19 matching lines...) Expand all
257 } 314 }
258 } 315 }
259 316
260 void RasterWorkerPool::CollectCompletedTasksWithLockAcquired( 317 void RasterWorkerPool::CollectCompletedTasksWithLockAcquired(
261 cc::NamespaceToken token, 318 cc::NamespaceToken token,
262 cc::Task::Vector* completed_tasks) { 319 cc::Task::Vector* completed_tasks) {
263 DCHECK(token.IsValid()); 320 DCHECK(token.IsValid());
264 work_queue_.CollectCompletedTasks(token, completed_tasks); 321 work_queue_.CollectCompletedTasks(token, completed_tasks);
265 } 322 }
266 323
267 bool RasterWorkerPool::RunTaskWithLockAcquired() { 324 void RasterWorkerPool::RunTaskWithLockAcquired(cc::TaskCategory category) {
268 TRACE_EVENT0("toplevel", "TaskGraphRunner::RunTask"); 325 TRACE_EVENT0("toplevel", "TaskGraphRunner::RunTask");
269 326
270 lock_.AssertAcquired(); 327 lock_.AssertAcquired();
271 328
272 // Find the first category with any tasks to run. This task graph runner
273 // treats categories as an additional priority.
274 // TODO(ericrk): Add more category/thread logic.
275 const auto& ready_to_run_namespaces = work_queue_.ready_to_run_namespaces();
276 auto found = std::find_if(
277 ready_to_run_namespaces.cbegin(), ready_to_run_namespaces.cend(),
278 [](const std::pair<uint16_t,
279 cc::TaskGraphWorkQueue::TaskNamespace::Vector>& pair) {
280 return !pair.second.empty();
281 });
282
283 if (found == ready_to_run_namespaces.cend()) {
284 return false;
285 }
286
287 const uint16_t category = found->first;
288 auto prioritized_task = work_queue_.GetNextTaskToRun(category); 329 auto prioritized_task = work_queue_.GetNextTaskToRun(category);
289 cc::Task* task = prioritized_task.task; 330 cc::Task* task = prioritized_task.task;
290 331
291 // There may be more work available, so wake up another worker thread.
292 if (work_queue_.HasReadyToRunTasks())
293 has_ready_to_run_tasks_cv_.Signal();
294
295 // Call WillRun() before releasing |lock_| and running task. 332 // Call WillRun() before releasing |lock_| and running task.
296 task->WillRun(); 333 task->WillRun();
297 334
298 { 335 {
299 base::AutoUnlock unlock(lock_); 336 base::AutoUnlock unlock(lock_);
300 337
301 task->RunOnWorkerThread(); 338 task->RunOnWorkerThread();
302 } 339 }
303 340
304 // This will mark task as finished running. 341 // This will mark task as finished running.
305 task->DidRun(); 342 task->DidRun();
306 343
307 work_queue_.CompleteTask(prioritized_task); 344 work_queue_.CompleteTask(prioritized_task);
308 345
346 // We may have just dequeued more tasks, wake up the other worker threads.
347 if (work_queue_.HasReadyToRunTasks())
348 has_ready_to_run_tasks_cv_.Broadcast();
349
309 // If namespace has finished running all tasks, wake up origin threads. 350 // If namespace has finished running all tasks, wake up origin threads.
310 if (work_queue_.HasFinishedRunningTasksInNamespace( 351 if (work_queue_.HasFinishedRunningTasksInNamespace(
311 prioritized_task.task_namespace)) 352 prioritized_task.task_namespace))
312 has_namespaces_with_finished_running_tasks_cv_.Broadcast(); 353 has_namespaces_with_finished_running_tasks_cv_.Broadcast();
313
314 return true;
315 } 354 }
316 355
317 RasterWorkerPool::ClosureTask::ClosureTask(const base::Closure& closure) 356 RasterWorkerPool::ClosureTask::ClosureTask(const base::Closure& closure)
318 : closure_(closure) {} 357 : closure_(closure) {}
319 358
320 // Overridden from cc::Task: 359 // Overridden from cc::Task:
321 void RasterWorkerPool::ClosureTask::RunOnWorkerThread() { 360 void RasterWorkerPool::ClosureTask::RunOnWorkerThread() {
322 closure_.Run(); 361 closure_.Run();
323 closure_.Reset(); 362 closure_.Reset();
324 } 363 }
325 364
326 RasterWorkerPool::ClosureTask::~ClosureTask() {} 365 RasterWorkerPool::ClosureTask::~ClosureTask() {}
327 366
328 } // namespace content 367 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698