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

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: Fix picture pile reference management. Post a task for running cheap tasks. 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
« cc/tile_manager.cc ('K') | « 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();
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());
(...skipping 36 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 Worker* worker = GetWorkerForNextTask();
189 205
190 worker->PostTask( 206 worker->PostTask(
191 make_scoped_ptr(new WorkerPoolTaskImpl( 207 make_scoped_ptr(new WorkerPoolTaskImpl(
192 task, 208 task,
193 reply)).PassAs<internal::WorkerPoolTask>()); 209 reply)).PassAs<internal::WorkerPoolTask>());
194 } 210 }
195 211
196 bool WorkerPool::IsBusy() { 212 bool WorkerPool::IsBusy() {
197 Worker* worker = GetWorkerForNextTask(); 213 Worker* worker = GetWorkerForNextTask();
198 214
199 return worker->num_pending_tasks() >= kNumPendingTasksPerWorker; 215 return worker->num_pending_tasks() >= kNumPendingTasksPerWorker;
200 } 216 }
201 217
202 void WorkerPool::SetRecordRenderingStats(bool record_rendering_stats) { 218 void WorkerPool::SetRecordRenderingStats(bool record_rendering_stats) {
219 if (record_rendering_stats)
220 cheap_rendering_stats_.reset(new RenderingStats);
221 else
222 cheap_rendering_stats_.reset();
223
203 for (WorkerVector::iterator it = workers_.begin(); 224 for (WorkerVector::iterator it = workers_.begin();
204 it != workers_.end(); ++it) { 225 it != workers_.end(); ++it) {
205 Worker* worker = *it; 226 Worker* worker = *it;
206 worker->set_record_rendering_stats(record_rendering_stats); 227 worker->set_record_rendering_stats(record_rendering_stats);
207 } 228 }
208 } 229 }
209 230
210 void WorkerPool::GetRenderingStats(RenderingStats* stats) { 231 void WorkerPool::GetRenderingStats(RenderingStats* stats) {
211 stats->totalRasterizeTime = base::TimeDelta(); 232 stats->totalRasterizeTime = base::TimeDelta();
212 stats->totalRasterizeTimeForNowBinsOnPendingTree = base::TimeDelta(); 233 stats->totalRasterizeTimeForNowBinsOnPendingTree = base::TimeDelta();
213 stats->totalPixelsRasterized = 0; 234 stats->totalPixelsRasterized = 0;
214 stats->totalDeferredImageDecodeCount = 0; 235 stats->totalDeferredImageDecodeCount = 0;
215 stats->totalDeferredImageDecodeTime = base::TimeDelta(); 236 stats->totalDeferredImageDecodeTime = base::TimeDelta();
237 if (cheap_rendering_stats_) {
238 stats->totalRasterizeTime +=
239 cheap_rendering_stats_->totalRasterizeTime;
240 stats->totalPixelsRasterized +=
241 cheap_rendering_stats_->totalPixelsRasterized;
242 stats->totalDeferredImageDecodeCount +=
243 cheap_rendering_stats_->totalDeferredImageDecodeCount;
244 stats->totalDeferredImageDecodeTime +=
245 cheap_rendering_stats_->totalDeferredImageDecodeTime;
246 }
216 for (WorkerVector::iterator it = workers_.begin(); 247 for (WorkerVector::iterator it = workers_.begin();
217 it != workers_.end(); ++it) { 248 it != workers_.end(); ++it) {
218 Worker* worker = *it; 249 Worker* worker = *it;
219 CHECK(worker->rendering_stats()); 250 CHECK(worker->rendering_stats());
220 stats->totalRasterizeTime += 251 stats->totalRasterizeTime +=
221 worker->rendering_stats()->totalRasterizeTime; 252 worker->rendering_stats()->totalRasterizeTime;
222 stats->totalRasterizeTimeForNowBinsOnPendingTree += 253 stats->totalRasterizeTimeForNowBinsOnPendingTree +=
223 worker->rendering_stats()->totalRasterizeTimeForNowBinsOnPendingTree; 254 worker->rendering_stats()->totalRasterizeTimeForNowBinsOnPendingTree;
224 stats->totalPixelsRasterized += 255 stats->totalPixelsRasterized +=
225 worker->rendering_stats()->totalPixelsRasterized; 256 worker->rendering_stats()->totalPixelsRasterized;
226 stats->totalDeferredImageDecodeCount += 257 stats->totalDeferredImageDecodeCount +=
227 worker->rendering_stats()->totalDeferredImageDecodeCount; 258 worker->rendering_stats()->totalDeferredImageDecodeCount;
228 stats->totalDeferredImageDecodeTime += 259 stats->totalDeferredImageDecodeTime +=
229 worker->rendering_stats()->totalDeferredImageDecodeTime; 260 worker->rendering_stats()->totalDeferredImageDecodeTime;
230 } 261 }
231 } 262 }
232 263
233 WorkerPool::Worker* WorkerPool::GetWorkerForNextTask() { 264 WorkerPool::Worker* WorkerPool::GetWorkerForNextTask() {
234 CHECK(!shutdown_); 265 CHECK(!shutdown_);
235 SortWorkersIfNeeded(); 266 SortWorkersIfNeeded();
236 return workers_.front(); 267 return workers_.front();
237 } 268 }
238 269
239 void WorkerPool::ScheduleCheckForCompletedTasks() { 270 void WorkerPool::ScheduleCheckForCompletedTasks() {
240 if (check_for_completed_tasks_pending_) 271 if (!check_for_completed_tasks_deadline_.is_null())
241 return; 272 return;
242 273
243 check_for_completed_tasks_callback_.Reset( 274 check_for_completed_tasks_callback_.Reset(
244 base::Bind(&WorkerPool::CheckForCompletedTasks, 275 base::Bind(&WorkerPool::CheckForCompletedTasks,
245 weak_ptr_factory_.GetWeakPtr())); 276 weak_ptr_factory_.GetWeakPtr()));
277 base::TimeDelta delay =
278 base::TimeDelta::FromMilliseconds(kCheckForCompletedTasksDelayMs);
279 check_for_completed_tasks_deadline_ = base::TimeTicks::Now() + delay;
246 origin_loop_->PostDelayedTask( 280 origin_loop_->PostDelayedTask(
247 FROM_HERE, 281 FROM_HERE,
248 check_for_completed_tasks_callback_.callback(), 282 check_for_completed_tasks_callback_.callback(),
249 base::TimeDelta::FromMilliseconds(kCheckForCompletedTasksDelayMs)); 283 delay);
250 check_for_completed_tasks_pending_ = true;
251 } 284 }
252 285
253 void WorkerPool::WillPostTask() { 286 void WorkerPool::WillPostTask() {
254 base::subtle::Barrier_AtomicIncrement(&pending_task_count_, 1); 287 base::subtle::Barrier_AtomicIncrement(&pending_task_count_, 1);
255 ScheduleCheckForCompletedTasks(); 288 ScheduleCheckForCompletedTasks();
256 workers_need_sorting_ = true; 289 workers_need_sorting_ = true;
257 } 290 }
258 291
259 void WorkerPool::OnWorkCompletedOnWorkerThread() { 292 void WorkerPool::OnWorkCompletedOnWorkerThread() {
260 // Post idle handler task when pool work count reaches 0. 293 // Post idle handler task when pool work count reaches 0.
261 if (base::subtle::Barrier_AtomicIncrement(&pending_task_count_, -1) == 0) { 294 if (base::subtle::Barrier_AtomicIncrement(&pending_task_count_, -1) == 0) {
262 origin_loop_->PostTask(FROM_HERE, idle_callback_); 295 origin_loop_->PostTask(FROM_HERE, idle_callback_);
263 } 296 }
264 } 297 }
265 298
266 void WorkerPool::OnIdle() { 299 void WorkerPool::OnIdle() {
267 if (base::subtle::Acquire_Load(&pending_task_count_) == 0) { 300 if (base::subtle::Acquire_Load(&pending_task_count_) == 0 &&
301 pending_cheap_tasks_.empty()) {
268 check_for_completed_tasks_callback_.Cancel(); 302 check_for_completed_tasks_callback_.Cancel();
269 CheckForCompletedTasks(); 303 CheckForCompletedTasks();
270 } 304 }
271 } 305 }
272 306
273 void WorkerPool::CheckForCompletedTasks() { 307 void WorkerPool::CheckForCompletedTasks() {
274 check_for_completed_tasks_pending_ = false; 308 TRACE_EVENT0("cc", "WorkerPool::CheckForCompletedTasks");
309 check_for_completed_tasks_deadline_ = base::TimeTicks();
310
311 while (completed_cheap_tasks_.size()) {
312 scoped_ptr<internal::WorkerPoolTask> task =
313 completed_cheap_tasks_.take_front();
314 task->DidComplete();
315 }
275 316
276 for (WorkerVector::iterator it = workers_.begin(); 317 for (WorkerVector::iterator it = workers_.begin();
277 it != workers_.end(); it++) { 318 it != workers_.end(); it++) {
278 Worker* worker = *it; 319 Worker* worker = *it;
279 worker->CheckForCompletedTasks(); 320 worker->CheckForCompletedTasks();
280 } 321 }
281 322
282 client_->DidFinishDispatchingWorkerPoolCompletionCallbacks(); 323 client_->DidFinishDispatchingWorkerPoolCompletionCallbacks();
283 324
284 for (WorkerVector::iterator it = workers_.begin(); 325 for (WorkerVector::iterator it = workers_.begin();
(...skipping 11 matching lines...) Expand all
296 } 337 }
297 338
298 void WorkerPool::SortWorkersIfNeeded() { 339 void WorkerPool::SortWorkersIfNeeded() {
299 if (!workers_need_sorting_) 340 if (!workers_need_sorting_)
300 return; 341 return;
301 342
302 std::sort(workers_.begin(), workers_.end(), NumPendingTasksComparator()); 343 std::sort(workers_.begin(), workers_.end(), NumPendingTasksComparator());
303 workers_need_sorting_ = false; 344 workers_need_sorting_ = false;
304 } 345 }
305 346
347 bool WorkerPool::CanPostCheapTask() const {
348 return pending_cheap_tasks_.size() < kMaxCheapTaskCount;
349 }
350
351 void WorkerPool::PostCheapTask(scoped_ptr<internal::WorkerPoolTask> task) {
352 DCHECK(CanPostCheapTask());
353 pending_cheap_tasks_.push_back(task.Pass());
354 ScheduleRunCheapTasks();
355 ScheduleCheckForCompletedTasks();
356 }
357
358 void WorkerPool::ScheduleRunCheapTasks() {
359 if (run_cheap_tasks_pending_)
360 return;
361 origin_loop_->PostTask(FROM_HERE, cheap_task_callback_);
362 run_cheap_tasks_pending_ = true;
363 }
364
365 void WorkerPool::RunCheapTasks() {
366 TRACE_EVENT0("cc", "WorkerPool::RunCheapTasks");
367 DCHECK(run_cheap_tasks_pending_);
368
369 // Run as many cheap tasks as we can within the time limit.
370 base::TimeTicks deadline = base::TimeTicks::Now() +
371 base::TimeDelta::FromMilliseconds(kMaxCheapTaskMs);
372 while (pending_cheap_tasks_.size()) {
373 scoped_ptr<internal::WorkerPoolTask> task =
374 pending_cheap_tasks_.take_front();
375 task->Run(cheap_rendering_stats_.get());
376 completed_cheap_tasks_.push_back(task.Pass());
377
378 if (!check_for_completed_tasks_deadline_.is_null() &&
379 base::TimeTicks::Now() >= check_for_completed_tasks_deadline_) {
380 TRACE_EVENT_INSTANT0("cc", "WorkerPool::RunCheapTasks check deadline");
381 CheckForCompletedTasks();
382 }
383 if (base::TimeTicks::Now() >= deadline) {
384 TRACE_EVENT_INSTANT0("cc", "WorkerPool::RunCheapTasks out of time");
385 break;
386 }
387 }
388
389 // Defer remaining tasks to worker threads.
390 while (pending_cheap_tasks_.size()) {
391 scoped_ptr<internal::WorkerPoolTask> task =
392 pending_cheap_tasks_.take_front();
393 Worker* worker = GetWorkerForNextTask();
394 worker->PostTask(task.Pass());
395 }
396 run_cheap_tasks_pending_ = false;
397 }
398
306 } // namespace cc 399 } // namespace cc
OLDNEW
« cc/tile_manager.cc ('K') | « cc/worker_pool.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698