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

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: Refactoring PostTask. 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
98 worker_pool_->WillPostTask();
99
100 message_loop_proxy()->PostTask( 107 message_loop_proxy()->PostTask(
101 FROM_HERE, 108 FROM_HERE,
102 base::Bind(&Worker::RunTask, 109 base::Bind(&Worker::RunTask,
103 base::Unretained(task.get()), 110 base::Unretained(task.get()),
104 base::Unretained(worker_pool_), 111 base::Unretained(worker_pool_),
105 base::Unretained(stats))); 112 base::Unretained(stats)));
106 113
107 pending_tasks_.push_back(task.Pass()); 114 pending_tasks_.push_back(task.Pass());
108 } 115 }
109 116
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
144 } 151 }
145 } 152 }
146 153
147 WorkerPool::WorkerPool(WorkerPoolClient* client, size_t num_threads) 154 WorkerPool::WorkerPool(WorkerPoolClient* client, size_t num_threads)
148 : client_(client), 155 : client_(client),
149 origin_loop_(base::MessageLoopProxy::current()), 156 origin_loop_(base::MessageLoopProxy::current()),
150 weak_ptr_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)), 157 weak_ptr_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)),
151 workers_need_sorting_(false), 158 workers_need_sorting_(false),
152 pending_task_count_(0), 159 pending_task_count_(0),
153 shutdown_(false), 160 shutdown_(false),
154 check_for_completed_tasks_pending_(false),
155 idle_callback_( 161 idle_callback_(
156 base::Bind(&WorkerPool::OnIdle, weak_ptr_factory_.GetWeakPtr())) { 162 base::Bind(&WorkerPool::OnIdle, weak_ptr_factory_.GetWeakPtr())),
163 cheap_task_callback_(
164 base::Bind(&WorkerPool::RunCheapTasks,
165 weak_ptr_factory_.GetWeakPtr())),
166 run_cheap_tasks_pending_(false) {
157 const std::string thread_name_prefix = kWorkerThreadNamePrefix; 167 const std::string thread_name_prefix = kWorkerThreadNamePrefix;
158 while (workers_.size() < num_threads) { 168 while (workers_.size() < num_threads) {
159 int thread_number = workers_.size() + 1; 169 int thread_number = workers_.size() + 1;
160 workers_.push_back(new Worker( 170 workers_.push_back(new Worker(
161 this, 171 this,
162 thread_name_prefix + StringPrintf("Worker%d", thread_number).c_str())); 172 thread_name_prefix + StringPrintf("Worker%d", thread_number).c_str()));
163 } 173 }
164 base::subtle::Acquire_Store(&pending_task_count_, 0); 174 base::subtle::Acquire_Store(&pending_task_count_, 0);
165 } 175 }
166 176
167 WorkerPool::~WorkerPool() { 177 WorkerPool::~WorkerPool() {
168 Shutdown(); 178 Shutdown();
169 STLDeleteElements(&workers_); 179 STLDeleteElements(&workers_);
170 // Cancel all pending callbacks. 180 // Cancel all pending callbacks.
171 weak_ptr_factory_.InvalidateWeakPtrs(); 181 weak_ptr_factory_.InvalidateWeakPtrs();
172 DCHECK_EQ(base::subtle::Acquire_Load(&pending_task_count_), 0); 182 DCHECK_EQ(base::subtle::Acquire_Load(&pending_task_count_), 0);
173 } 183 }
174 184
175 void WorkerPool::Shutdown() { 185 void WorkerPool::Shutdown() {
176 DCHECK(!shutdown_); 186 DCHECK(!shutdown_);
177 shutdown_ = true; 187 shutdown_ = true;
178 188
189 if (run_cheap_tasks_pending_)
190 RunCheapTasks();
191
179 for (WorkerVector::iterator it = workers_.begin(); 192 for (WorkerVector::iterator it = workers_.begin();
180 it != workers_.end(); it++) { 193 it != workers_.end(); it++) {
181 Worker* worker = *it; 194 Worker* worker = *it;
182 worker->StopAfterCompletingAllPendingTasks(); 195 worker->StopAfterCompletingAllPendingTasks();
183 } 196 }
184 } 197 }
185 198
186 void WorkerPool::PostTaskAndReply( 199 void WorkerPool::PostTaskAndReply(
187 const Callback& task, const base::Closure& reply) { 200 const Callback& task, const base::Closure& reply) {
188 Worker* worker = GetWorkerForNextTask(); 201 PostTask(
189
190 worker->PostTask(
191 make_scoped_ptr(new WorkerPoolTaskImpl( 202 make_scoped_ptr(new WorkerPoolTaskImpl(
192 task, 203 task,
193 reply)).PassAs<internal::WorkerPoolTask>()); 204 reply)).PassAs<internal::WorkerPoolTask>(),
205 false);
194 } 206 }
195 207
196 bool WorkerPool::IsBusy() { 208 bool WorkerPool::IsBusy() {
197 Worker* worker = GetWorkerForNextTask(); 209 Worker* worker = GetWorkerForNextTask();
198 210
199 return worker->num_pending_tasks() >= kNumPendingTasksPerWorker; 211 return worker->num_pending_tasks() >= kNumPendingTasksPerWorker;
200 } 212 }
201 213
202 void WorkerPool::SetRecordRenderingStats(bool record_rendering_stats) { 214 void WorkerPool::SetRecordRenderingStats(bool record_rendering_stats) {
215 if (record_rendering_stats)
216 cheap_rendering_stats_.reset(new RenderingStats);
217 else
218 cheap_rendering_stats_.reset();
219
203 for (WorkerVector::iterator it = workers_.begin(); 220 for (WorkerVector::iterator it = workers_.begin();
204 it != workers_.end(); ++it) { 221 it != workers_.end(); ++it) {
205 Worker* worker = *it; 222 Worker* worker = *it;
206 worker->set_record_rendering_stats(record_rendering_stats); 223 worker->set_record_rendering_stats(record_rendering_stats);
207 } 224 }
208 } 225 }
209 226
210 void WorkerPool::GetRenderingStats(RenderingStats* stats) { 227 void WorkerPool::GetRenderingStats(RenderingStats* stats) {
211 stats->totalRasterizeTime = base::TimeDelta(); 228 stats->totalRasterizeTime = base::TimeDelta();
212 stats->totalRasterizeTimeForNowBinsOnPendingTree = base::TimeDelta(); 229 stats->totalRasterizeTimeForNowBinsOnPendingTree = base::TimeDelta();
213 stats->totalPixelsRasterized = 0; 230 stats->totalPixelsRasterized = 0;
214 stats->totalDeferredImageDecodeCount = 0; 231 stats->totalDeferredImageDecodeCount = 0;
215 stats->totalDeferredImageDecodeTime = base::TimeDelta(); 232 stats->totalDeferredImageDecodeTime = base::TimeDelta();
233 if (cheap_rendering_stats_) {
234 stats->totalRasterizeTime +=
235 cheap_rendering_stats_->totalRasterizeTime;
236 stats->totalPixelsRasterized +=
237 cheap_rendering_stats_->totalPixelsRasterized;
238 stats->totalDeferredImageDecodeCount +=
239 cheap_rendering_stats_->totalDeferredImageDecodeCount;
240 stats->totalDeferredImageDecodeTime +=
241 cheap_rendering_stats_->totalDeferredImageDecodeTime;
242 }
216 for (WorkerVector::iterator it = workers_.begin(); 243 for (WorkerVector::iterator it = workers_.begin();
217 it != workers_.end(); ++it) { 244 it != workers_.end(); ++it) {
218 Worker* worker = *it; 245 Worker* worker = *it;
219 CHECK(worker->rendering_stats()); 246 CHECK(worker->rendering_stats());
220 stats->totalRasterizeTime += 247 stats->totalRasterizeTime +=
221 worker->rendering_stats()->totalRasterizeTime; 248 worker->rendering_stats()->totalRasterizeTime;
222 stats->totalRasterizeTimeForNowBinsOnPendingTree += 249 stats->totalRasterizeTimeForNowBinsOnPendingTree +=
223 worker->rendering_stats()->totalRasterizeTimeForNowBinsOnPendingTree; 250 worker->rendering_stats()->totalRasterizeTimeForNowBinsOnPendingTree;
224 stats->totalPixelsRasterized += 251 stats->totalPixelsRasterized +=
225 worker->rendering_stats()->totalPixelsRasterized; 252 worker->rendering_stats()->totalPixelsRasterized;
226 stats->totalDeferredImageDecodeCount += 253 stats->totalDeferredImageDecodeCount +=
227 worker->rendering_stats()->totalDeferredImageDecodeCount; 254 worker->rendering_stats()->totalDeferredImageDecodeCount;
228 stats->totalDeferredImageDecodeTime += 255 stats->totalDeferredImageDecodeTime +=
229 worker->rendering_stats()->totalDeferredImageDecodeTime; 256 worker->rendering_stats()->totalDeferredImageDecodeTime;
230 } 257 }
231 } 258 }
232 259
233 WorkerPool::Worker* WorkerPool::GetWorkerForNextTask() { 260 WorkerPool::Worker* WorkerPool::GetWorkerForNextTask() {
234 CHECK(!shutdown_); 261 CHECK(!shutdown_);
235 SortWorkersIfNeeded(); 262 SortWorkersIfNeeded();
236 return workers_.front(); 263 return workers_.front();
237 } 264 }
238 265
239 void WorkerPool::ScheduleCheckForCompletedTasks() { 266 void WorkerPool::ScheduleCheckForCompletedTasks() {
240 if (check_for_completed_tasks_pending_) 267 if (!check_for_completed_tasks_deadline_.is_null())
241 return; 268 return;
242 269
243 check_for_completed_tasks_callback_.Reset( 270 check_for_completed_tasks_callback_.Reset(
244 base::Bind(&WorkerPool::CheckForCompletedTasks, 271 base::Bind(&WorkerPool::CheckForCompletedTasks,
245 weak_ptr_factory_.GetWeakPtr())); 272 weak_ptr_factory_.GetWeakPtr()));
273 base::TimeDelta delay =
274 base::TimeDelta::FromMilliseconds(kCheckForCompletedTasksDelayMs);
275 check_for_completed_tasks_deadline_ = base::TimeTicks::Now() + delay;
246 origin_loop_->PostDelayedTask( 276 origin_loop_->PostDelayedTask(
247 FROM_HERE, 277 FROM_HERE,
248 check_for_completed_tasks_callback_.callback(), 278 check_for_completed_tasks_callback_.callback(),
249 base::TimeDelta::FromMilliseconds(kCheckForCompletedTasksDelayMs)); 279 delay);
250 check_for_completed_tasks_pending_ = true;
251 }
252
253 void WorkerPool::WillPostTask() {
254 base::subtle::Barrier_AtomicIncrement(&pending_task_count_, 1);
255 ScheduleCheckForCompletedTasks();
256 workers_need_sorting_ = true;
257 } 280 }
258 281
259 void WorkerPool::OnWorkCompletedOnWorkerThread() { 282 void WorkerPool::OnWorkCompletedOnWorkerThread() {
260 // Post idle handler task when pool work count reaches 0. 283 // Post idle handler task when pool work count reaches 0.
261 if (base::subtle::Barrier_AtomicIncrement(&pending_task_count_, -1) == 0) { 284 if (base::subtle::Barrier_AtomicIncrement(&pending_task_count_, -1) == 0) {
262 origin_loop_->PostTask(FROM_HERE, idle_callback_); 285 origin_loop_->PostTask(FROM_HERE, idle_callback_);
263 } 286 }
264 } 287 }
265 288
266 void WorkerPool::OnIdle() { 289 void WorkerPool::OnIdle() {
267 if (base::subtle::Acquire_Load(&pending_task_count_) == 0) { 290 if (base::subtle::Acquire_Load(&pending_task_count_) == 0 &&
291 pending_cheap_tasks_.empty()) {
268 check_for_completed_tasks_callback_.Cancel(); 292 check_for_completed_tasks_callback_.Cancel();
269 CheckForCompletedTasks(); 293 CheckForCompletedTasks();
270 } 294 }
271 } 295 }
272 296
273 void WorkerPool::CheckForCompletedTasks() { 297 void WorkerPool::CheckForCompletedTasks() {
274 check_for_completed_tasks_pending_ = false; 298 TRACE_EVENT0("cc", "WorkerPool::CheckForCompletedTasks");
299 check_for_completed_tasks_deadline_ = base::TimeTicks();
300
301 while (completed_cheap_tasks_.size()) {
302 scoped_ptr<internal::WorkerPoolTask> task =
303 completed_cheap_tasks_.take_front();
304 task->DidComplete();
305 }
275 306
276 for (WorkerVector::iterator it = workers_.begin(); 307 for (WorkerVector::iterator it = workers_.begin();
277 it != workers_.end(); it++) { 308 it != workers_.end(); it++) {
278 Worker* worker = *it; 309 Worker* worker = *it;
279 worker->CheckForCompletedTasks(); 310 worker->CheckForCompletedTasks();
280 } 311 }
281 312
282 client_->DidFinishDispatchingWorkerPoolCompletionCallbacks(); 313 client_->DidFinishDispatchingWorkerPoolCompletionCallbacks();
283 314
284 for (WorkerVector::iterator it = workers_.begin(); 315 for (WorkerVector::iterator it = workers_.begin();
(...skipping 11 matching lines...) Expand all
296 } 327 }
297 328
298 void WorkerPool::SortWorkersIfNeeded() { 329 void WorkerPool::SortWorkersIfNeeded() {
299 if (!workers_need_sorting_) 330 if (!workers_need_sorting_)
300 return; 331 return;
301 332
302 std::sort(workers_.begin(), workers_.end(), NumPendingTasksComparator()); 333 std::sort(workers_.begin(), workers_.end(), NumPendingTasksComparator());
303 workers_need_sorting_ = false; 334 workers_need_sorting_ = false;
304 } 335 }
305 336
337 void WorkerPool::PostTask(
338 scoped_ptr<internal::WorkerPoolTask> task, bool is_cheap) {
339 if (is_cheap && CanPostCheapTask()) {
340 pending_cheap_tasks_.push_back(task.Pass());
341 ScheduleRunCheapTasks();
342 } else {
343 base::subtle::Barrier_AtomicIncrement(&pending_task_count_, 1);
344 workers_need_sorting_ = true;
345
346 Worker* worker = GetWorkerForNextTask();
347 task->WillRunOnThread(worker);
348 worker->PostTask(task.Pass());
349 }
350 ScheduleCheckForCompletedTasks();
351 }
352
353 bool WorkerPool::CanPostCheapTask() const {
354 return pending_cheap_tasks_.size() < kMaxCheapTaskCount;
355 }
356
357 void WorkerPool::ScheduleRunCheapTasks() {
358 if (run_cheap_tasks_pending_)
359 return;
360 origin_loop_->PostTask(FROM_HERE, cheap_task_callback_);
361 run_cheap_tasks_pending_ = true;
362 }
363
364 void WorkerPool::RunCheapTasks() {
365 TRACE_EVENT0("cc", "WorkerPool::RunCheapTasks");
366 DCHECK(run_cheap_tasks_pending_);
367
368 // Run as many cheap tasks as we can within the time limit.
369 base::TimeTicks deadline = base::TimeTicks::Now() +
370 base::TimeDelta::FromMilliseconds(kMaxCheapTaskMs);
371 while (pending_cheap_tasks_.size()) {
372 scoped_ptr<internal::WorkerPoolTask> task =
373 pending_cheap_tasks_.take_front();
374 task->Run(cheap_rendering_stats_.get());
375 completed_cheap_tasks_.push_back(task.Pass());
376
377 if (!check_for_completed_tasks_deadline_.is_null() &&
378 base::TimeTicks::Now() >= check_for_completed_tasks_deadline_) {
379 TRACE_EVENT_INSTANT0("cc", "WorkerPool::RunCheapTasks check deadline");
380 CheckForCompletedTasks();
381 }
382 if (base::TimeTicks::Now() >= deadline) {
383 TRACE_EVENT_INSTANT0("cc", "WorkerPool::RunCheapTasks out of time");
384 break;
385 }
386 }
387
388 // Defer remaining tasks to worker threads.
389 while (pending_cheap_tasks_.size()) {
390 scoped_ptr<internal::WorkerPoolTask> task =
391 pending_cheap_tasks_.take_front();
392 PostTask(task.Pass(), false);
393 }
394 run_cheap_tasks_pending_ = false;
395 }
396
306 } // namespace cc 397 } // 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