| Index: cc/worker_pool.cc
|
| diff --git a/cc/worker_pool.cc b/cc/worker_pool.cc
|
| index cf5f8cd653b29974e747eda39182c182a3d97006..ba48b49bcb638e1392714dbdaaa187f3956fe06b 100644
|
| --- a/cc/worker_pool.cc
|
| +++ b/cc/worker_pool.cc
|
| @@ -7,6 +7,7 @@
|
| #include <algorithm>
|
|
|
| #include "base/bind.h"
|
| +#include "base/debug/trace_event.h"
|
| #include "base/stl_util.h"
|
| #include "base/stringprintf.h"
|
|
|
| @@ -26,6 +27,8 @@ class WorkerPoolTaskImpl : public internal::WorkerPoolTask {
|
| : internal::WorkerPoolTask(reply),
|
| task_(task) {}
|
|
|
| + virtual void WillRunOnThread(base::Thread* thread) OVERRIDE {}
|
| +
|
| virtual void Run(RenderingStats* rendering_stats) OVERRIDE {
|
| task_.Run(rendering_stats);
|
| base::subtle::Release_Store(&completed_, 1);
|
| @@ -45,6 +48,12 @@ const int kNumPendingTasksPerWorker = 40;
|
|
|
| const int kCheckForCompletedTasksDelayMs = 6;
|
|
|
| +// Limits for the total number of cheap tasks we are allowed to perform
|
| +// during a single frame and the time spent running those tasks.
|
| +// TODO(skyostil): Determine these limits more dynamically.
|
| +const int kMaxCheapTaskCount = 6;
|
| +const int kMaxCheapTaskMs = kCheckForCompletedTasksDelayMs;
|
| +
|
| } // namespace
|
|
|
| namespace internal {
|
| @@ -95,6 +104,7 @@ void WorkerPool::Worker::PostTask(scoped_ptr<internal::WorkerPoolTask> task) {
|
| RenderingStats* stats =
|
| record_rendering_stats_ ? rendering_stats_.get() : NULL;
|
|
|
| + task->WillRunOnThread(this);
|
| worker_pool_->WillPostTask();
|
|
|
| message_loop_proxy()->PostTask(
|
| @@ -151,9 +161,12 @@ WorkerPool::WorkerPool(WorkerPoolClient* client, size_t num_threads)
|
| workers_need_sorting_(false),
|
| pending_task_count_(0),
|
| shutdown_(false),
|
| - check_for_completed_tasks_pending_(false),
|
| idle_callback_(
|
| - base::Bind(&WorkerPool::OnIdle, weak_ptr_factory_.GetWeakPtr())) {
|
| + base::Bind(&WorkerPool::OnIdle, weak_ptr_factory_.GetWeakPtr())),
|
| + cheap_task_callback_(
|
| + base::Bind(&WorkerPool::RunCheapTasks,
|
| + weak_ptr_factory_.GetWeakPtr())),
|
| + run_cheap_tasks_pending_(false) {
|
| const std::string thread_name_prefix = kWorkerThreadNamePrefix;
|
| while (workers_.size() < num_threads) {
|
| int thread_number = workers_.size() + 1;
|
| @@ -176,6 +189,9 @@ void WorkerPool::Shutdown() {
|
| DCHECK(!shutdown_);
|
| shutdown_ = true;
|
|
|
| + if (run_cheap_tasks_pending_)
|
| + RunCheapTasks();
|
| +
|
| for (WorkerVector::iterator it = workers_.begin();
|
| it != workers_.end(); it++) {
|
| Worker* worker = *it;
|
| @@ -200,6 +216,11 @@ bool WorkerPool::IsBusy() {
|
| }
|
|
|
| void WorkerPool::SetRecordRenderingStats(bool record_rendering_stats) {
|
| + if (record_rendering_stats)
|
| + cheap_rendering_stats_.reset(new RenderingStats);
|
| + else
|
| + cheap_rendering_stats_.reset();
|
| +
|
| for (WorkerVector::iterator it = workers_.begin();
|
| it != workers_.end(); ++it) {
|
| Worker* worker = *it;
|
| @@ -213,6 +234,16 @@ void WorkerPool::GetRenderingStats(RenderingStats* stats) {
|
| stats->totalPixelsRasterized = 0;
|
| stats->totalDeferredImageDecodeCount = 0;
|
| stats->totalDeferredImageDecodeTime = base::TimeDelta();
|
| + if (cheap_rendering_stats_) {
|
| + stats->totalRasterizeTime +=
|
| + cheap_rendering_stats_->totalRasterizeTime;
|
| + stats->totalPixelsRasterized +=
|
| + cheap_rendering_stats_->totalPixelsRasterized;
|
| + stats->totalDeferredImageDecodeCount +=
|
| + cheap_rendering_stats_->totalDeferredImageDecodeCount;
|
| + stats->totalDeferredImageDecodeTime +=
|
| + cheap_rendering_stats_->totalDeferredImageDecodeTime;
|
| + }
|
| for (WorkerVector::iterator it = workers_.begin();
|
| it != workers_.end(); ++it) {
|
| Worker* worker = *it;
|
| @@ -237,17 +268,19 @@ WorkerPool::Worker* WorkerPool::GetWorkerForNextTask() {
|
| }
|
|
|
| void WorkerPool::ScheduleCheckForCompletedTasks() {
|
| - if (check_for_completed_tasks_pending_)
|
| + if (!check_for_completed_tasks_deadline_.is_null())
|
| return;
|
|
|
| check_for_completed_tasks_callback_.Reset(
|
| base::Bind(&WorkerPool::CheckForCompletedTasks,
|
| weak_ptr_factory_.GetWeakPtr()));
|
| + base::TimeDelta delay =
|
| + base::TimeDelta::FromMilliseconds(kCheckForCompletedTasksDelayMs);
|
| + check_for_completed_tasks_deadline_ = base::TimeTicks::Now() + delay;
|
| origin_loop_->PostDelayedTask(
|
| FROM_HERE,
|
| check_for_completed_tasks_callback_.callback(),
|
| - base::TimeDelta::FromMilliseconds(kCheckForCompletedTasksDelayMs));
|
| - check_for_completed_tasks_pending_ = true;
|
| + delay);
|
| }
|
|
|
| void WorkerPool::WillPostTask() {
|
| @@ -264,14 +297,22 @@ void WorkerPool::OnWorkCompletedOnWorkerThread() {
|
| }
|
|
|
| void WorkerPool::OnIdle() {
|
| - if (base::subtle::Acquire_Load(&pending_task_count_) == 0) {
|
| + if (base::subtle::Acquire_Load(&pending_task_count_) == 0 &&
|
| + pending_cheap_tasks_.empty()) {
|
| check_for_completed_tasks_callback_.Cancel();
|
| CheckForCompletedTasks();
|
| }
|
| }
|
|
|
| void WorkerPool::CheckForCompletedTasks() {
|
| - check_for_completed_tasks_pending_ = false;
|
| + TRACE_EVENT0("cc", "WorkerPool::CheckForCompletedTasks");
|
| + check_for_completed_tasks_deadline_ = base::TimeTicks();
|
| +
|
| + while (completed_cheap_tasks_.size()) {
|
| + scoped_ptr<internal::WorkerPoolTask> task =
|
| + completed_cheap_tasks_.take_front();
|
| + task->DidComplete();
|
| + }
|
|
|
| for (WorkerVector::iterator it = workers_.begin();
|
| it != workers_.end(); it++) {
|
| @@ -303,4 +344,56 @@ void WorkerPool::SortWorkersIfNeeded() {
|
| workers_need_sorting_ = false;
|
| }
|
|
|
| +bool WorkerPool::CanPostCheapTask() const {
|
| + return pending_cheap_tasks_.size() < kMaxCheapTaskCount;
|
| +}
|
| +
|
| +void WorkerPool::PostCheapTask(scoped_ptr<internal::WorkerPoolTask> task) {
|
| + DCHECK(CanPostCheapTask());
|
| + pending_cheap_tasks_.push_back(task.Pass());
|
| + ScheduleRunCheapTasks();
|
| + ScheduleCheckForCompletedTasks();
|
| +}
|
| +
|
| +void WorkerPool::ScheduleRunCheapTasks() {
|
| + if (run_cheap_tasks_pending_)
|
| + return;
|
| + origin_loop_->PostTask(FROM_HERE, cheap_task_callback_);
|
| + run_cheap_tasks_pending_ = true;
|
| +}
|
| +
|
| +void WorkerPool::RunCheapTasks() {
|
| + TRACE_EVENT0("cc", "WorkerPool::RunCheapTasks");
|
| + DCHECK(run_cheap_tasks_pending_);
|
| +
|
| + // Run as many cheap tasks as we can within the time limit.
|
| + base::TimeTicks deadline = base::TimeTicks::Now() +
|
| + base::TimeDelta::FromMilliseconds(kMaxCheapTaskMs);
|
| + while (pending_cheap_tasks_.size()) {
|
| + scoped_ptr<internal::WorkerPoolTask> task =
|
| + pending_cheap_tasks_.take_front();
|
| + task->Run(cheap_rendering_stats_.get());
|
| + completed_cheap_tasks_.push_back(task.Pass());
|
| +
|
| + if (!check_for_completed_tasks_deadline_.is_null() &&
|
| + base::TimeTicks::Now() >= check_for_completed_tasks_deadline_) {
|
| + TRACE_EVENT_INSTANT0("cc", "WorkerPool::RunCheapTasks check deadline");
|
| + CheckForCompletedTasks();
|
| + }
|
| + if (base::TimeTicks::Now() >= deadline) {
|
| + TRACE_EVENT_INSTANT0("cc", "WorkerPool::RunCheapTasks out of time");
|
| + break;
|
| + }
|
| + }
|
| +
|
| + // Defer remaining tasks to worker threads.
|
| + while (pending_cheap_tasks_.size()) {
|
| + scoped_ptr<internal::WorkerPoolTask> task =
|
| + pending_cheap_tasks_.take_front();
|
| + Worker* worker = GetWorkerForNextTask();
|
| + worker->PostTask(task.Pass());
|
| + }
|
| + run_cheap_tasks_pending_ = false;
|
| +}
|
| +
|
| } // namespace cc
|
|
|