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

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: Post a task to run 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/raster_worker_pool.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
29 virtual void Run(RenderingStats* rendering_stats) OVERRIDE { 30 virtual void Run(RenderingStats* rendering_stats) OVERRIDE {
30 task_.Run(rendering_stats); 31 task_.Run(rendering_stats);
31 base::subtle::Release_Store(&completed_, 1); 32 base::subtle::Release_Store(&completed_, 1);
32 } 33 }
33 34
35 virtual void DeferToThread(base::Thread* thread) OVERRIDE {}
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 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
146 155
147 WorkerPool::WorkerPool(WorkerPoolClient* client, size_t num_threads) 156 WorkerPool::WorkerPool(WorkerPoolClient* client, size_t num_threads)
148 : client_(client), 157 : client_(client),
149 origin_loop_(base::MessageLoopProxy::current()), 158 origin_loop_(base::MessageLoopProxy::current()),
150 weak_ptr_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)), 159 weak_ptr_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)),
151 workers_need_sorting_(false), 160 workers_need_sorting_(false),
152 pending_task_count_(0), 161 pending_task_count_(0),
153 shutdown_(false), 162 shutdown_(false),
154 check_for_completed_tasks_pending_(false), 163 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->totalPixelsRasterized = 0; 233 stats->totalPixelsRasterized = 0;
213 stats->totalDeferredImageDecodeCount = 0; 234 stats->totalDeferredImageDecodeCount = 0;
214 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 }
215 for (WorkerVector::iterator it = workers_.begin(); 246 for (WorkerVector::iterator it = workers_.begin();
216 it != workers_.end(); ++it) { 247 it != workers_.end(); ++it) {
217 Worker* worker = *it; 248 Worker* worker = *it;
218 CHECK(worker->rendering_stats()); 249 CHECK(worker->rendering_stats());
219 stats->totalRasterizeTime += 250 stats->totalRasterizeTime +=
220 worker->rendering_stats()->totalRasterizeTime; 251 worker->rendering_stats()->totalRasterizeTime;
221 stats->totalPixelsRasterized += 252 stats->totalPixelsRasterized +=
222 worker->rendering_stats()->totalPixelsRasterized; 253 worker->rendering_stats()->totalPixelsRasterized;
223 stats->totalDeferredImageDecodeCount += 254 stats->totalDeferredImageDecodeCount +=
224 worker->rendering_stats()->totalDeferredImageDecodeCount; 255 worker->rendering_stats()->totalDeferredImageDecodeCount;
(...skipping 28 matching lines...) Expand all
253 workers_need_sorting_ = true; 284 workers_need_sorting_ = true;
254 } 285 }
255 286
256 void WorkerPool::OnWorkCompletedOnWorkerThread() { 287 void WorkerPool::OnWorkCompletedOnWorkerThread() {
257 // Post idle handler task when pool work count reaches 0. 288 // Post idle handler task when pool work count reaches 0.
258 if (base::subtle::Barrier_AtomicIncrement(&pending_task_count_, -1) == 0) { 289 if (base::subtle::Barrier_AtomicIncrement(&pending_task_count_, -1) == 0) {
259 origin_loop_->PostTask(FROM_HERE, idle_callback_); 290 origin_loop_->PostTask(FROM_HERE, idle_callback_);
260 } 291 }
261 } 292 }
262 293
263 void WorkerPool::OnIdle() { 294 void WorkerPool::OnIdle() {
reveman 2013/02/14 21:10:49 do we need to make sure this is not called when we
Sami 2013/02/15 16:41:22 Good point. I made it a no-op if there are pending
295 TRACE_EVENT0("cc", "WorkerPool::OnIdle");
264 if (base::subtle::Acquire_Load(&pending_task_count_) == 0) { 296 if (base::subtle::Acquire_Load(&pending_task_count_) == 0) {
265 check_for_completed_tasks_callback_.Cancel(); 297 check_for_completed_tasks_callback_.Cancel();
266 CheckForCompletedTasks(); 298 CheckForCompletedTasks();
267 } 299 }
268 } 300 }
269 301
270 void WorkerPool::CheckForCompletedTasks() { 302 void WorkerPool::CheckForCompletedTasks() {
303 TRACE_EVENT0("cc", "WorkerPool::CheckForCompletedTasks");
271 check_for_completed_tasks_pending_ = false; 304 check_for_completed_tasks_pending_ = false;
272 305
273 for (WorkerVector::iterator it = workers_.begin(); 306 for (WorkerVector::iterator it = workers_.begin();
274 it != workers_.end(); it++) { 307 it != workers_.end(); it++) {
275 Worker* worker = *it; 308 Worker* worker = *it;
276 worker->CheckForCompletedTasks(); 309 worker->CheckForCompletedTasks();
277 } 310 }
278 311
279 client_->DidFinishDispatchingWorkerPoolCompletionCallbacks(); 312 client_->DidFinishDispatchingWorkerPoolCompletionCallbacks();
280 313
(...skipping 12 matching lines...) Expand all
293 } 326 }
294 327
295 void WorkerPool::SortWorkersIfNeeded() { 328 void WorkerPool::SortWorkersIfNeeded() {
296 if (!workers_need_sorting_) 329 if (!workers_need_sorting_)
297 return; 330 return;
298 331
299 std::sort(workers_.begin(), workers_.end(), NumPendingTasksComparator()); 332 std::sort(workers_.begin(), workers_.end(), NumPendingTasksComparator());
300 workers_need_sorting_ = false; 333 workers_need_sorting_ = false;
301 } 334 }
302 335
336 bool WorkerPool::CanPostCheapTask() const {
337 return pending_cheap_tasks_.size() < kMaxCheapTaskCount;
338 }
339
340 void WorkerPool::PostCheapTask(scoped_ptr<internal::WorkerPoolTask> task) {
341 DCHECK(CanPostCheapTask());
342 pending_cheap_tasks_.push_back(task.Pass());
343 if (!run_cheap_tasks_pending_) {
344 origin_loop_->PostTask(FROM_HERE, cheap_task_callback_);
reveman 2013/02/14 21:10:49 Please add a ScheduleRunCheapTasks(). And you'll n
Sami 2013/02/15 16:41:22 Done. See below for why I didn't add the ScheduleC
345 run_cheap_tasks_pending_ = true;
346 }
347 }
348
349 void WorkerPool::RunCheapTasks() {
350 // Run as many cheap tasks as we can within the time limit.
351 TRACE_EVENT0("cc", "WorkerPool::RunCheapTasks");
352 base::TimeTicks deadline = base::TimeTicks::Now() +
353 base::TimeDelta::FromMilliseconds(kMaxCheapTaskMs);
reveman 2013/02/14 21:10:49 Should the deadline for cheap tasks not be somethi
Sami 2013/02/15 16:41:22 I'm not sure that's ideal. One of the sites this o
354 while (pending_cheap_tasks_.size()) {
355 scoped_ptr<internal::WorkerPoolTask> task =
356 pending_cheap_tasks_.take_front();
357 task->Run(cheap_rendering_stats_.get());
358 task->DidComplete();
reveman 2013/02/14 21:10:49 Can we have this DidComplete call be done by Check
Sami 2013/02/15 16:41:22 Good idea, I've moved the DidComplete() check to C
359 if (base::TimeTicks::Now() >= deadline) {
360 TRACE_EVENT_INSTANT0("cc", "WorkerPool::RunCheapTasks out of time");
361 break;
362 }
363 }
364
365 // Defer remaining tasks to worker threads.
366 while (pending_cheap_tasks_.size()) {
367 scoped_ptr<internal::WorkerPoolTask> task =
368 pending_cheap_tasks_.take_front();
369 Worker* worker = GetWorkerForNextTask();
370 task->DeferToThread(worker);
reveman 2013/02/14 21:10:49 move DeferToThread into PostTask if possible.
Sami 2013/02/15 16:41:22 Done.
371 worker->PostTask(task.Pass());
372 }
373 run_cheap_tasks_pending_ = false;
374 }
375
303 } // namespace cc 376 } // namespace cc
OLDNEW
« cc/raster_worker_pool.cc ('K') | « cc/worker_pool.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698