| OLD | NEW |
| 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/stl_util.h" | 10 #include "base/stl_util.h" |
| 11 #include "base/stringprintf.h" | 11 #include "base/stringprintf.h" |
| 12 | 12 |
| 13 #if defined(OS_ANDROID) | 13 #if defined(OS_ANDROID) |
| 14 // TODO(epenner): Move thread priorities to base. (crbug.com/170549) | 14 // TODO(epenner): Move thread priorities to base. (crbug.com/170549) |
| 15 #include <sys/resource.h> | 15 #include <sys/resource.h> |
| 16 #endif | 16 #endif |
| 17 | 17 |
| 18 namespace cc { | 18 namespace cc { |
| 19 | 19 |
| 20 namespace { | 20 namespace { |
| 21 | 21 |
| 22 class WorkerPoolTaskImpl : public internal::WorkerPoolTask { | 22 class WorkerPoolTaskImpl : public internal::WorkerPoolTask { |
| 23 public: | 23 public: |
| 24 WorkerPoolTaskImpl(const WorkerPool::Callback& task, | 24 WorkerPoolTaskImpl(const WorkerPool::Callback& task, |
| 25 const base::Closure& reply) | 25 const base::Closure& reply) |
| 26 : internal::WorkerPoolTask(reply), | 26 : internal::WorkerPoolTask(reply), |
| 27 task_(task) {} | 27 task_(task) {} |
| 28 | 28 |
| 29 virtual void Run() OVERRIDE { | 29 virtual void Run(RenderingStats* rendering_stats) OVERRIDE { |
| 30 task_.Run(&rendering_stats_); | 30 task_.Run(rendering_stats); |
| 31 } | 31 } |
| 32 | 32 |
| 33 private: | 33 private: |
| 34 WorkerPool::Callback task_; | 34 WorkerPool::Callback task_; |
| 35 }; | 35 }; |
| 36 | 36 |
| 37 const char* kWorkerThreadNamePrefix = "Compositor"; | 37 const char* kWorkerThreadNamePrefix = "Compositor"; |
| 38 | 38 |
| 39 // Allow two pending tasks per worker. This keeps resource usage | 39 // Allow two pending tasks per worker. This keeps resource usage |
| 40 // low while making sure workers aren't unnecessarily idle. | 40 // low while making sure workers aren't unnecessarily idle. |
| 41 const int kNumPendingTasksPerWorker = 2; | 41 const int kNumPendingTasksPerWorker = 2; |
| 42 | 42 |
| 43 } // namespace | 43 } // namespace |
| 44 | 44 |
| 45 namespace internal { | 45 namespace internal { |
| 46 | 46 |
| 47 WorkerPoolTask::WorkerPoolTask(const base::Closure& reply) | 47 WorkerPoolTask::WorkerPoolTask(const base::Closure& reply) |
| 48 : reply_(reply) { | 48 : reply_(reply) { |
| 49 } | 49 } |
| 50 | 50 |
| 51 WorkerPoolTask::~WorkerPoolTask() { | 51 WorkerPoolTask::~WorkerPoolTask() { |
| 52 } | 52 } |
| 53 | 53 |
| 54 void WorkerPoolTask::Completed() { | 54 void WorkerPoolTask::Completed() { |
| 55 reply_.Run(); | 55 reply_.Run(); |
| 56 } | 56 } |
| 57 | 57 |
| 58 } // namespace internal | 58 } // namespace internal |
| 59 | 59 |
| 60 WorkerPool::Worker::Worker(WorkerPool* worker_pool, const std::string name) | 60 WorkerPool::Worker::Worker( |
| 61 WorkerPool* worker_pool, |
| 62 const std::string name, |
| 63 scoped_ptr<RenderingStats> rendering_stats) |
| 61 : base::Thread(name.c_str()), | 64 : base::Thread(name.c_str()), |
| 62 worker_pool_(worker_pool), | 65 worker_pool_(worker_pool), |
| 63 weak_ptr_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) { | 66 weak_ptr_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)), |
| 67 rendering_stats_(rendering_stats.Pass()) { |
| 64 Start(); | 68 Start(); |
| 65 DCHECK(IsRunning()); | 69 DCHECK(IsRunning()); |
| 66 } | 70 } |
| 67 | 71 |
| 68 WorkerPool::Worker::~Worker() { | 72 WorkerPool::Worker::~Worker() { |
| 69 DCHECK(!IsRunning()); | 73 DCHECK(!IsRunning()); |
| 70 DCHECK_EQ(pending_tasks_.size(), 0); | 74 DCHECK_EQ(pending_tasks_.size(), 0); |
| 71 } | 75 } |
| 72 | 76 |
| 73 void WorkerPool::Worker::StopAfterCompletingAllPendingTasks() { | 77 void WorkerPool::Worker::StopAfterCompletingAllPendingTasks() { |
| 74 // Signals the thread to exit and returns once all pending tasks have run. | 78 // Signals the thread to exit and returns once all pending tasks have run. |
| 75 Stop(); | 79 Stop(); |
| 76 | 80 |
| 77 // Complete all pending tasks. The Stop() call above guarantees that | 81 // Complete all pending tasks. The Stop() call above guarantees that |
| 78 // all tasks have finished running. | 82 // all tasks have finished running. |
| 79 while (!pending_tasks_.empty()) | 83 while (!pending_tasks_.empty()) |
| 80 OnTaskCompleted(); | 84 OnTaskCompleted(); |
| 81 | 85 |
| 82 // Cancel all pending replies. | 86 // Cancel all pending replies. |
| 83 weak_ptr_factory_.InvalidateWeakPtrs(); | 87 weak_ptr_factory_.InvalidateWeakPtrs(); |
| 84 } | 88 } |
| 85 | 89 |
| 86 void WorkerPool::Worker::PostTask(scoped_ptr<internal::WorkerPoolTask> task) { | 90 void WorkerPool::Worker::PostTask(scoped_ptr<internal::WorkerPoolTask> task) { |
| 87 DCHECK_LT(num_pending_tasks(), kNumPendingTasksPerWorker); | 91 DCHECK_LT(num_pending_tasks(), kNumPendingTasksPerWorker); |
| 88 | 92 |
| 89 message_loop_proxy()->PostTaskAndReply( | 93 message_loop_proxy()->PostTaskAndReply( |
| 90 FROM_HERE, | 94 FROM_HERE, |
| 91 base::Bind(&Worker::RunTask, base::Unretained(task.get())), | 95 base::Bind(&Worker::RunTask, |
| 96 base::Unretained(task.get()), |
| 97 base::Unretained(rendering_stats_.get())), |
| 92 base::Bind(&Worker::OnTaskCompleted, weak_ptr_factory_.GetWeakPtr())); | 98 base::Bind(&Worker::OnTaskCompleted, weak_ptr_factory_.GetWeakPtr())); |
| 93 | 99 |
| 94 pending_tasks_.push_back(task.Pass()); | 100 pending_tasks_.push_back(task.Pass()); |
| 95 | 101 |
| 96 worker_pool_->DidNumPendingTasksChange(); | 102 worker_pool_->DidNumPendingTasksChange(); |
| 97 } | 103 } |
| 98 | 104 |
| 99 void WorkerPool::Worker::Init() { | 105 void WorkerPool::Worker::Init() { |
| 100 #if defined(OS_ANDROID) | 106 #if defined(OS_ANDROID) |
| 101 // TODO(epenner): Move thread priorities to base. (crbug.com/170549) | 107 // TODO(epenner): Move thread priorities to base. (crbug.com/170549) |
| 102 int nice_value = 10; // Idle priority. | 108 int nice_value = 10; // Idle priority. |
| 103 setpriority(PRIO_PROCESS, base::PlatformThread::CurrentId(), nice_value); | 109 setpriority(PRIO_PROCESS, base::PlatformThread::CurrentId(), nice_value); |
| 104 #endif | 110 #endif |
| 105 } | 111 } |
| 106 | 112 |
| 107 // static | 113 // static |
| 108 void WorkerPool::Worker::RunTask(internal::WorkerPoolTask* task) { | 114 void WorkerPool::Worker::RunTask( |
| 109 task->Run(); | 115 internal::WorkerPoolTask* task, RenderingStats* rendering_stats) { |
| 116 task->Run(rendering_stats); |
| 110 } | 117 } |
| 111 | 118 |
| 112 void WorkerPool::Worker::OnTaskCompleted() { | 119 void WorkerPool::Worker::OnTaskCompleted() { |
| 113 CHECK(!pending_tasks_.empty()); | 120 CHECK(!pending_tasks_.empty()); |
| 114 | 121 |
| 115 scoped_ptr<internal::WorkerPoolTask> task = pending_tasks_.take_front(); | 122 scoped_ptr<internal::WorkerPoolTask> task = pending_tasks_.take_front(); |
| 116 | |
| 117 task->Completed(); | 123 task->Completed(); |
| 118 | 124 |
| 119 rendering_stats_.totalRasterizeTime += | |
| 120 task->rendering_stats().totalRasterizeTime; | |
| 121 rendering_stats_.totalPixelsRasterized += | |
| 122 task->rendering_stats().totalPixelsRasterized; | |
| 123 rendering_stats_.totalDeferredImageDecodeTime += | |
| 124 task->rendering_stats().totalDeferredImageDecodeTime; | |
| 125 rendering_stats_.totalDeferredImageDecodeCount += | |
| 126 task->rendering_stats().totalDeferredImageDecodeCount; | |
| 127 | |
| 128 worker_pool_->DidNumPendingTasksChange(); | 125 worker_pool_->DidNumPendingTasksChange(); |
| 129 } | 126 } |
| 130 | 127 |
| 131 WorkerPool::WorkerPool(size_t num_threads) | 128 WorkerPool::WorkerPool(size_t num_threads, bool record_rendering_stats) |
| 132 : workers_need_sorting_(false), | 129 : workers_need_sorting_(false), |
| 133 shutdown_(false) { | 130 shutdown_(false) { |
| 134 const std::string thread_name_prefix = kWorkerThreadNamePrefix; | 131 const std::string thread_name_prefix = kWorkerThreadNamePrefix; |
| 135 while (workers_.size() < num_threads) { | 132 while (workers_.size() < num_threads) { |
| 136 int thread_number = workers_.size() + 1; | 133 int thread_number = workers_.size() + 1; |
| 137 workers_.push_back( | 134 scoped_ptr<RenderingStats> rendering_stats = record_rendering_stats ? |
| 138 new Worker(this, | 135 make_scoped_ptr(new RenderingStats) : scoped_ptr<RenderingStats>(); |
| 139 thread_name_prefix + | 136 workers_.push_back(new Worker( |
| 140 StringPrintf("Worker%d", thread_number).c_str())); | 137 this, |
| 138 thread_name_prefix + StringPrintf("Worker%d", thread_number).c_str(), |
| 139 rendering_stats.Pass())); |
| 141 } | 140 } |
| 142 } | 141 } |
| 143 | 142 |
| 144 WorkerPool::~WorkerPool() { | 143 WorkerPool::~WorkerPool() { |
| 145 Shutdown(); | 144 Shutdown(); |
| 146 STLDeleteElements(&workers_); | 145 STLDeleteElements(&workers_); |
| 147 } | 146 } |
| 148 | 147 |
| 149 void WorkerPool::Shutdown() { | 148 void WorkerPool::Shutdown() { |
| 150 DCHECK(!shutdown_); | 149 DCHECK(!shutdown_); |
| (...skipping 23 matching lines...) Expand all Loading... |
| 174 } | 173 } |
| 175 | 174 |
| 176 void WorkerPool::GetRenderingStats(RenderingStats* stats) { | 175 void WorkerPool::GetRenderingStats(RenderingStats* stats) { |
| 177 stats->totalRasterizeTime = base::TimeDelta(); | 176 stats->totalRasterizeTime = base::TimeDelta(); |
| 178 stats->totalPixelsRasterized = 0; | 177 stats->totalPixelsRasterized = 0; |
| 179 stats->totalDeferredImageDecodeCount = 0; | 178 stats->totalDeferredImageDecodeCount = 0; |
| 180 stats->totalDeferredImageDecodeTime = base::TimeDelta(); | 179 stats->totalDeferredImageDecodeTime = base::TimeDelta(); |
| 181 for (WorkerVector::iterator it = workers_.begin(); | 180 for (WorkerVector::iterator it = workers_.begin(); |
| 182 it != workers_.end(); ++it) { | 181 it != workers_.end(); ++it) { |
| 183 Worker* worker = *it; | 182 Worker* worker = *it; |
| 183 CHECK(worker->rendering_stats()); |
| 184 stats->totalRasterizeTime += | 184 stats->totalRasterizeTime += |
| 185 worker->rendering_stats().totalRasterizeTime; | 185 worker->rendering_stats()->totalRasterizeTime; |
| 186 stats->totalPixelsRasterized += | 186 stats->totalPixelsRasterized += |
| 187 worker->rendering_stats().totalPixelsRasterized; | 187 worker->rendering_stats()->totalPixelsRasterized; |
| 188 stats->totalDeferredImageDecodeCount += | 188 stats->totalDeferredImageDecodeCount += |
| 189 worker->rendering_stats().totalDeferredImageDecodeCount; | 189 worker->rendering_stats()->totalDeferredImageDecodeCount; |
| 190 stats->totalDeferredImageDecodeTime += | 190 stats->totalDeferredImageDecodeTime += |
| 191 worker->rendering_stats().totalDeferredImageDecodeTime; | 191 worker->rendering_stats()->totalDeferredImageDecodeTime; |
| 192 } | 192 } |
| 193 } | 193 } |
| 194 | 194 |
| 195 WorkerPool::Worker* WorkerPool::GetWorkerForNextTask() { | 195 WorkerPool::Worker* WorkerPool::GetWorkerForNextTask() { |
| 196 CHECK(!shutdown_); | 196 CHECK(!shutdown_); |
| 197 SortWorkersIfNeeded(); | 197 SortWorkersIfNeeded(); |
| 198 return workers_.front(); | 198 return workers_.front(); |
| 199 } | 199 } |
| 200 | 200 |
| 201 void WorkerPool::DidNumPendingTasksChange() { | 201 void WorkerPool::DidNumPendingTasksChange() { |
| 202 workers_need_sorting_ = true; | 202 workers_need_sorting_ = true; |
| 203 } | 203 } |
| 204 | 204 |
| 205 void WorkerPool::SortWorkersIfNeeded() { | 205 void WorkerPool::SortWorkersIfNeeded() { |
| 206 if (!workers_need_sorting_) | 206 if (!workers_need_sorting_) |
| 207 return; | 207 return; |
| 208 | 208 |
| 209 std::sort(workers_.begin(), workers_.end(), NumPendingTasksComparator()); | 209 std::sort(workers_.begin(), workers_.end(), NumPendingTasksComparator()); |
| 210 workers_need_sorting_ = false; | 210 workers_need_sorting_ = false; |
| 211 } | 211 } |
| 212 | 212 |
| 213 } // namespace cc | 213 } // namespace cc |
| OLD | NEW |