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

Side by Side Diff: cc/worker_pool.cc

Issue 12194015: cc: Rasterize cheap tiles immediately (Closed) Base URL: http://git.chromium.org/git/chromium.git@trunk
Patch Set: David's comments. Created 7 years, 10 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 | Annotate | Revision Log
« no previous file with comments | « cc/worker_pool.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 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 "cc/worker_pool.h" 5 #include "cc/worker_pool.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/debug/trace_event.h"
10 #include "base/stl_util.h" 11 #include "base/stl_util.h"
11 #include "base/stringprintf.h" 12 #include "base/stringprintf.h"
12 13
13 #if defined(OS_ANDROID) 14 #if defined(OS_ANDROID)
14 // TODO(epenner): Move thread priorities to base. (crbug.com/170549) 15 // TODO(epenner): Move thread priorities to base. (crbug.com/170549)
15 #include <sys/resource.h> 16 #include <sys/resource.h>
16 #endif 17 #endif
17 18
18 namespace cc { 19 namespace cc {
19 20
20 namespace { 21 namespace {
21 22
22 class WorkerPoolTaskImpl : public internal::WorkerPoolTask { 23 class WorkerPoolTaskImpl : public internal::WorkerPoolTask {
23 public: 24 public:
24 WorkerPoolTaskImpl(const WorkerPool::Callback& task, 25 WorkerPoolTaskImpl(const WorkerPool::Callback& task,
25 const base::Closure& reply) 26 const base::Closure& reply)
26 : internal::WorkerPoolTask(reply), 27 : internal::WorkerPoolTask(reply),
27 task_(task) {} 28 task_(task) {}
28 29
30 virtual void WillRunOnThread(base::Thread* thread) OVERRIDE {}
31
29 virtual void Run(RenderingStats* rendering_stats) OVERRIDE { 32 virtual void Run(RenderingStats* rendering_stats) OVERRIDE {
30 task_.Run(rendering_stats); 33 task_.Run(rendering_stats);
31 base::subtle::Release_Store(&completed_, 1); 34 base::subtle::Release_Store(&completed_, 1);
32 } 35 }
33 36
34 private: 37 private:
35 WorkerPool::Callback task_; 38 WorkerPool::Callback task_;
36 }; 39 };
37 40
38 const char* kWorkerThreadNamePrefix = "Compositor"; 41 const char* kWorkerThreadNamePrefix = "Compositor";
39 42
40 #if defined(OS_ANDROID) 43 #if defined(OS_ANDROID)
41 const int kNumPendingTasksPerWorker = 8; 44 const int kNumPendingTasksPerWorker = 8;
42 #else 45 #else
43 const int kNumPendingTasksPerWorker = 40; 46 const int kNumPendingTasksPerWorker = 40;
44 #endif 47 #endif
45 48
46 const int kCheckForCompletedTasksDelayMs = 6; 49 const int kCheckForCompletedTasksDelayMs = 6;
47 50
51 // Limits for the total number of cheap tasks we are allowed to perform
52 // during a single frame and the time spent running those tasks.
53 // TODO(skyostil): Determine these limits more dynamically.
54 const int kMaxCheapTaskCount = 6;
55 const int kMaxCheapTaskMs = kCheckForCompletedTasksDelayMs;
56
48 } // namespace 57 } // namespace
49 58
50 namespace internal { 59 namespace internal {
51 60
52 WorkerPoolTask::WorkerPoolTask(const base::Closure& reply) : reply_(reply) { 61 WorkerPoolTask::WorkerPoolTask(const base::Closure& reply) : reply_(reply) {
53 base::subtle::Acquire_Store(&completed_, 0); 62 base::subtle::Acquire_Store(&completed_, 0);
54 } 63 }
55 64
56 WorkerPoolTask::~WorkerPoolTask() { 65 WorkerPoolTask::~WorkerPoolTask() {
57 } 66 }
(...skipping 30 matching lines...) Expand all
88 // Complete all pending tasks. The Stop() call above guarantees that 97 // Complete all pending tasks. The Stop() call above guarantees that
89 // all tasks have finished running. 98 // all tasks have finished running.
90 while (!pending_tasks_.empty()) 99 while (!pending_tasks_.empty())
91 OnTaskCompleted(); 100 OnTaskCompleted();
92 } 101 }
93 102
94 void WorkerPool::Worker::PostTask(scoped_ptr<internal::WorkerPoolTask> task) { 103 void WorkerPool::Worker::PostTask(scoped_ptr<internal::WorkerPoolTask> task) {
95 RenderingStats* stats = 104 RenderingStats* stats =
96 record_rendering_stats_ ? rendering_stats_.get() : NULL; 105 record_rendering_stats_ ? rendering_stats_.get() : NULL;
97 106
107 task->WillRunOnThread(this);
98 worker_pool_->WillPostTask(); 108 worker_pool_->WillPostTask();
reveman 2013/02/20 04:33:41 Lets remove WorkerPool::WillPostTask() and do this
99 109
100 message_loop_proxy()->PostTask( 110 message_loop_proxy()->PostTask(
101 FROM_HERE, 111 FROM_HERE,
102 base::Bind(&Worker::RunTask, 112 base::Bind(&Worker::RunTask,
103 base::Unretained(task.get()), 113 base::Unretained(task.get()),
104 base::Unretained(worker_pool_), 114 base::Unretained(worker_pool_),
105 base::Unretained(stats))); 115 base::Unretained(stats)));
106 116
107 pending_tasks_.push_back(task.Pass()); 117 pending_tasks_.push_back(task.Pass());
108 } 118 }
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
144 } 154 }
145 } 155 }
146 156
147 WorkerPool::WorkerPool(WorkerPoolClient* client, size_t num_threads) 157 WorkerPool::WorkerPool(WorkerPoolClient* client, size_t num_threads)
148 : client_(client), 158 : client_(client),
149 origin_loop_(base::MessageLoopProxy::current()), 159 origin_loop_(base::MessageLoopProxy::current()),
150 weak_ptr_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)), 160 weak_ptr_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)),
151 workers_need_sorting_(false), 161 workers_need_sorting_(false),
152 pending_task_count_(0), 162 pending_task_count_(0),
153 shutdown_(false), 163 shutdown_(false),
154 check_for_completed_tasks_pending_(false),
155 idle_callback_( 164 idle_callback_(
156 base::Bind(&WorkerPool::OnIdle, weak_ptr_factory_.GetWeakPtr())) { 165 base::Bind(&WorkerPool::OnIdle, weak_ptr_factory_.GetWeakPtr())),
166 cheap_task_callback_(
167 base::Bind(&WorkerPool::RunCheapTasks,
168 weak_ptr_factory_.GetWeakPtr())),
169 run_cheap_tasks_pending_(false) {
157 const std::string thread_name_prefix = kWorkerThreadNamePrefix; 170 const std::string thread_name_prefix = kWorkerThreadNamePrefix;
158 while (workers_.size() < num_threads) { 171 while (workers_.size() < num_threads) {
159 int thread_number = workers_.size() + 1; 172 int thread_number = workers_.size() + 1;
160 workers_.push_back(new Worker( 173 workers_.push_back(new Worker(
161 this, 174 this,
162 thread_name_prefix + StringPrintf("Worker%d", thread_number).c_str())); 175 thread_name_prefix + StringPrintf("Worker%d", thread_number).c_str()));
163 } 176 }
164 base::subtle::Acquire_Store(&pending_task_count_, 0); 177 base::subtle::Acquire_Store(&pending_task_count_, 0);
165 } 178 }
166 179
167 WorkerPool::~WorkerPool() { 180 WorkerPool::~WorkerPool() {
168 Shutdown(); 181 Shutdown();
169 STLDeleteElements(&workers_); 182 STLDeleteElements(&workers_);
170 // Cancel all pending callbacks. 183 // Cancel all pending callbacks.
171 weak_ptr_factory_.InvalidateWeakPtrs(); 184 weak_ptr_factory_.InvalidateWeakPtrs();
172 DCHECK_EQ(base::subtle::Acquire_Load(&pending_task_count_), 0); 185 DCHECK_EQ(base::subtle::Acquire_Load(&pending_task_count_), 0);
173 } 186 }
174 187
175 void WorkerPool::Shutdown() { 188 void WorkerPool::Shutdown() {
176 DCHECK(!shutdown_); 189 DCHECK(!shutdown_);
177 shutdown_ = true; 190 shutdown_ = true;
178 191
192 if (run_cheap_tasks_pending_)
193 RunCheapTasks();
194
179 for (WorkerVector::iterator it = workers_.begin(); 195 for (WorkerVector::iterator it = workers_.begin();
180 it != workers_.end(); it++) { 196 it != workers_.end(); it++) {
181 Worker* worker = *it; 197 Worker* worker = *it;
182 worker->StopAfterCompletingAllPendingTasks(); 198 worker->StopAfterCompletingAllPendingTasks();
183 } 199 }
184 } 200 }
185 201
186 void WorkerPool::PostTaskAndReply( 202 void WorkerPool::PostTaskAndReply(
187 const Callback& task, const base::Closure& reply) { 203 const Callback& task, const base::Closure& reply) {
188 Worker* worker = GetWorkerForNextTask(); 204 PostTask(
189
190 worker->PostTask(
191 make_scoped_ptr(new WorkerPoolTaskImpl( 205 make_scoped_ptr(new WorkerPoolTaskImpl(
192 task, 206 task,
193 reply)).PassAs<internal::WorkerPoolTask>()); 207 reply)).PassAs<internal::WorkerPoolTask>(),
208 false);
194 } 209 }
195 210
196 bool WorkerPool::IsBusy() { 211 bool WorkerPool::IsBusy() {
197 Worker* worker = GetWorkerForNextTask(); 212 Worker* worker = GetWorkerForNextTask();
198 213
199 return worker->num_pending_tasks() >= kNumPendingTasksPerWorker; 214 return worker->num_pending_tasks() >= kNumPendingTasksPerWorker;
200 } 215 }
201 216
202 void WorkerPool::SetRecordRenderingStats(bool record_rendering_stats) { 217 void WorkerPool::SetRecordRenderingStats(bool record_rendering_stats) {
218 if (record_rendering_stats)
219 cheap_rendering_stats_.reset(new RenderingStats);
220 else
221 cheap_rendering_stats_.reset();
222
203 for (WorkerVector::iterator it = workers_.begin(); 223 for (WorkerVector::iterator it = workers_.begin();
204 it != workers_.end(); ++it) { 224 it != workers_.end(); ++it) {
205 Worker* worker = *it; 225 Worker* worker = *it;
206 worker->set_record_rendering_stats(record_rendering_stats); 226 worker->set_record_rendering_stats(record_rendering_stats);
207 } 227 }
208 } 228 }
209 229
210 void WorkerPool::GetRenderingStats(RenderingStats* stats) { 230 void WorkerPool::GetRenderingStats(RenderingStats* stats) {
211 stats->totalRasterizeTime = base::TimeDelta(); 231 stats->totalRasterizeTime = base::TimeDelta();
212 stats->totalRasterizeTimeForNowBinsOnPendingTree = base::TimeDelta(); 232 stats->totalRasterizeTimeForNowBinsOnPendingTree = base::TimeDelta();
213 stats->totalPixelsRasterized = 0; 233 stats->totalPixelsRasterized = 0;
214 stats->totalDeferredImageDecodeCount = 0; 234 stats->totalDeferredImageDecodeCount = 0;
215 stats->totalDeferredImageDecodeTime = base::TimeDelta(); 235 stats->totalDeferredImageDecodeTime = base::TimeDelta();
236 if (cheap_rendering_stats_) {
237 stats->totalRasterizeTime +=
238 cheap_rendering_stats_->totalRasterizeTime;
239 stats->totalPixelsRasterized +=
240 cheap_rendering_stats_->totalPixelsRasterized;
241 stats->totalDeferredImageDecodeCount +=
242 cheap_rendering_stats_->totalDeferredImageDecodeCount;
243 stats->totalDeferredImageDecodeTime +=
244 cheap_rendering_stats_->totalDeferredImageDecodeTime;
245 }
216 for (WorkerVector::iterator it = workers_.begin(); 246 for (WorkerVector::iterator it = workers_.begin();
217 it != workers_.end(); ++it) { 247 it != workers_.end(); ++it) {
218 Worker* worker = *it; 248 Worker* worker = *it;
219 CHECK(worker->rendering_stats()); 249 CHECK(worker->rendering_stats());
220 stats->totalRasterizeTime += 250 stats->totalRasterizeTime +=
221 worker->rendering_stats()->totalRasterizeTime; 251 worker->rendering_stats()->totalRasterizeTime;
222 stats->totalRasterizeTimeForNowBinsOnPendingTree += 252 stats->totalRasterizeTimeForNowBinsOnPendingTree +=
223 worker->rendering_stats()->totalRasterizeTimeForNowBinsOnPendingTree; 253 worker->rendering_stats()->totalRasterizeTimeForNowBinsOnPendingTree;
224 stats->totalPixelsRasterized += 254 stats->totalPixelsRasterized +=
225 worker->rendering_stats()->totalPixelsRasterized; 255 worker->rendering_stats()->totalPixelsRasterized;
226 stats->totalDeferredImageDecodeCount += 256 stats->totalDeferredImageDecodeCount +=
227 worker->rendering_stats()->totalDeferredImageDecodeCount; 257 worker->rendering_stats()->totalDeferredImageDecodeCount;
228 stats->totalDeferredImageDecodeTime += 258 stats->totalDeferredImageDecodeTime +=
229 worker->rendering_stats()->totalDeferredImageDecodeTime; 259 worker->rendering_stats()->totalDeferredImageDecodeTime;
230 } 260 }
231 } 261 }
232 262
233 WorkerPool::Worker* WorkerPool::GetWorkerForNextTask() { 263 WorkerPool::Worker* WorkerPool::GetWorkerForNextTask() {
234 CHECK(!shutdown_); 264 CHECK(!shutdown_);
235 SortWorkersIfNeeded(); 265 SortWorkersIfNeeded();
236 return workers_.front(); 266 return workers_.front();
237 } 267 }
238 268
239 void WorkerPool::ScheduleCheckForCompletedTasks() { 269 void WorkerPool::ScheduleCheckForCompletedTasks() {
240 if (check_for_completed_tasks_pending_) 270 if (!check_for_completed_tasks_deadline_.is_null())
241 return; 271 return;
242 272
243 check_for_completed_tasks_callback_.Reset( 273 check_for_completed_tasks_callback_.Reset(
244 base::Bind(&WorkerPool::CheckForCompletedTasks, 274 base::Bind(&WorkerPool::CheckForCompletedTasks,
245 weak_ptr_factory_.GetWeakPtr())); 275 weak_ptr_factory_.GetWeakPtr()));
276 base::TimeDelta delay =
277 base::TimeDelta::FromMilliseconds(kCheckForCompletedTasksDelayMs);
278 check_for_completed_tasks_deadline_ = base::TimeTicks::Now() + delay;
246 origin_loop_->PostDelayedTask( 279 origin_loop_->PostDelayedTask(
247 FROM_HERE, 280 FROM_HERE,
248 check_for_completed_tasks_callback_.callback(), 281 check_for_completed_tasks_callback_.callback(),
249 base::TimeDelta::FromMilliseconds(kCheckForCompletedTasksDelayMs)); 282 delay);
250 check_for_completed_tasks_pending_ = true;
251 } 283 }
252 284
253 void WorkerPool::WillPostTask() { 285 void WorkerPool::WillPostTask() {
254 base::subtle::Barrier_AtomicIncrement(&pending_task_count_, 1); 286 base::subtle::Barrier_AtomicIncrement(&pending_task_count_, 1);
255 ScheduleCheckForCompletedTasks(); 287 ScheduleCheckForCompletedTasks();
256 workers_need_sorting_ = true; 288 workers_need_sorting_ = true;
257 } 289 }
258 290
259 void WorkerPool::OnWorkCompletedOnWorkerThread() { 291 void WorkerPool::OnWorkCompletedOnWorkerThread() {
260 // Post idle handler task when pool work count reaches 0. 292 // Post idle handler task when pool work count reaches 0.
261 if (base::subtle::Barrier_AtomicIncrement(&pending_task_count_, -1) == 0) { 293 if (base::subtle::Barrier_AtomicIncrement(&pending_task_count_, -1) == 0) {
262 origin_loop_->PostTask(FROM_HERE, idle_callback_); 294 origin_loop_->PostTask(FROM_HERE, idle_callback_);
263 } 295 }
264 } 296 }
265 297
266 void WorkerPool::OnIdle() { 298 void WorkerPool::OnIdle() {
267 if (base::subtle::Acquire_Load(&pending_task_count_) == 0) { 299 if (base::subtle::Acquire_Load(&pending_task_count_) == 0 &&
300 pending_cheap_tasks_.empty()) {
268 check_for_completed_tasks_callback_.Cancel(); 301 check_for_completed_tasks_callback_.Cancel();
269 CheckForCompletedTasks(); 302 CheckForCompletedTasks();
270 } 303 }
271 } 304 }
272 305
273 void WorkerPool::CheckForCompletedTasks() { 306 void WorkerPool::CheckForCompletedTasks() {
274 check_for_completed_tasks_pending_ = false; 307 TRACE_EVENT0("cc", "WorkerPool::CheckForCompletedTasks");
308 check_for_completed_tasks_deadline_ = base::TimeTicks();
309
310 while (completed_cheap_tasks_.size()) {
311 scoped_ptr<internal::WorkerPoolTask> task =
312 completed_cheap_tasks_.take_front();
313 task->DidComplete();
314 }
275 315
276 for (WorkerVector::iterator it = workers_.begin(); 316 for (WorkerVector::iterator it = workers_.begin();
277 it != workers_.end(); it++) { 317 it != workers_.end(); it++) {
278 Worker* worker = *it; 318 Worker* worker = *it;
279 worker->CheckForCompletedTasks(); 319 worker->CheckForCompletedTasks();
280 } 320 }
281 321
282 client_->DidFinishDispatchingWorkerPoolCompletionCallbacks(); 322 client_->DidFinishDispatchingWorkerPoolCompletionCallbacks();
283 323
284 for (WorkerVector::iterator it = workers_.begin(); 324 for (WorkerVector::iterator it = workers_.begin();
(...skipping 11 matching lines...) Expand all
296 } 336 }
297 337
298 void WorkerPool::SortWorkersIfNeeded() { 338 void WorkerPool::SortWorkersIfNeeded() {
299 if (!workers_need_sorting_) 339 if (!workers_need_sorting_)
300 return; 340 return;
301 341
302 std::sort(workers_.begin(), workers_.end(), NumPendingTasksComparator()); 342 std::sort(workers_.begin(), workers_.end(), NumPendingTasksComparator());
303 workers_need_sorting_ = false; 343 workers_need_sorting_ = false;
304 } 344 }
305 345
346 void WorkerPool::PostTask(
347 scoped_ptr<internal::WorkerPoolTask> task, bool is_cheap) {
348 if (is_cheap && CanPostCheapTask()) {
349 PostCheapTask(task.Pass());
350 } else {
351 Worker* worker = GetWorkerForNextTask();
352 worker->PostTask(task.Pass());
353 }
354 }
355
356 bool WorkerPool::CanPostCheapTask() const {
357 return pending_cheap_tasks_.size() < kMaxCheapTaskCount;
358 }
359
360 void WorkerPool::PostCheapTask(scoped_ptr<internal::WorkerPoolTask> task) {
361 DCHECK(CanPostCheapTask());
362 pending_cheap_tasks_.push_back(task.Pass());
363 ScheduleRunCheapTasks();
364 ScheduleCheckForCompletedTasks();
reveman 2013/02/20 04:33:41 move ScheduleCheckForCompletedTasks() call to Post
365 }
366
367 void WorkerPool::ScheduleRunCheapTasks() {
368 if (run_cheap_tasks_pending_)
369 return;
370 origin_loop_->PostTask(FROM_HERE, cheap_task_callback_);
371 run_cheap_tasks_pending_ = true;
372 }
373
374 void WorkerPool::RunCheapTasks() {
375 TRACE_EVENT0("cc", "WorkerPool::RunCheapTasks");
376 DCHECK(run_cheap_tasks_pending_);
377
378 // Run as many cheap tasks as we can within the time limit.
379 base::TimeTicks deadline = base::TimeTicks::Now() +
380 base::TimeDelta::FromMilliseconds(kMaxCheapTaskMs);
381 while (pending_cheap_tasks_.size()) {
382 scoped_ptr<internal::WorkerPoolTask> task =
383 pending_cheap_tasks_.take_front();
384 task->Run(cheap_rendering_stats_.get());
385 completed_cheap_tasks_.push_back(task.Pass());
386
387 if (!check_for_completed_tasks_deadline_.is_null() &&
388 base::TimeTicks::Now() >= check_for_completed_tasks_deadline_) {
389 TRACE_EVENT_INSTANT0("cc", "WorkerPool::RunCheapTasks check deadline");
390 CheckForCompletedTasks();
391 }
392 if (base::TimeTicks::Now() >= deadline) {
393 TRACE_EVENT_INSTANT0("cc", "WorkerPool::RunCheapTasks out of time");
394 break;
395 }
396 }
397
398 // Defer remaining tasks to worker threads.
399 while (pending_cheap_tasks_.size()) {
400 scoped_ptr<internal::WorkerPoolTask> task =
401 pending_cheap_tasks_.take_front();
402 Worker* worker = GetWorkerForNextTask();
403 worker->PostTask(task.Pass());
reveman 2013/02/20 04:33:41 PostTask(task, false) here instead.
404 }
405 run_cheap_tasks_pending_ = false;
406 }
407
306 } // namespace cc 408 } // namespace cc
OLDNEW
« no previous file with comments | « cc/worker_pool.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698