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 3 // found in the LICENSE file. 4 5 #include "cc/resources/raster_worker_pool.h" 6 7 #include "base/time/time.h" 8 #include "testing/gtest/include/gtest/gtest.h" 9 10 namespace cc { 11 12 namespace { 13 14 static const int kTimeLimitMillis = 2000; 15 static const int kWarmupRuns = 5; 16 static const int kTimeCheckInterval = 10; 17 18 class PerfWorkerPoolTaskImpl : public internal::WorkerPoolTask { 19 public: 20 // Overridden from internal::WorkerPoolTask: 21 virtual void RunOnWorkerThread(unsigned thread_index) OVERRIDE {} 22 virtual void CompleteOnOriginThread() OVERRIDE {} 23 24 private: 25 virtual ~PerfWorkerPoolTaskImpl() {} 26 }; 27 28 class PerfRasterWorkerPool : public RasterWorkerPool { 29 public: 30 PerfRasterWorkerPool() : RasterWorkerPool(NULL, 1) {} 31 virtual ~PerfRasterWorkerPool() {} 32 33 static scoped_ptr<PerfRasterWorkerPool> Create() { 34 return make_scoped_ptr(new PerfRasterWorkerPool); 35 } 36 37 // Overridden from RasterWorkerPool: 38 virtual void ScheduleTasks(RasterTask::Queue* queue) OVERRIDE { 39 NOTREACHED(); 40 } 41 virtual void OnRasterTasksFinished() OVERRIDE { 42 NOTREACHED(); 43 } 44 virtual void OnRasterTasksRequiredForActivationFinished() OVERRIDE { 45 NOTREACHED(); 46 } 47 48 void SetRasterTasks(RasterTask::Queue* queue) { 49 RasterWorkerPool::SetRasterTasks(queue); 50 51 TaskMap perf_tasks; 52 for (RasterTaskVector::const_iterator it = raster_tasks().begin(); 53 it != raster_tasks().end(); ++it) { 54 internal::RasterWorkerPoolTask* task = it->get(); 55 56 scoped_refptr<internal::WorkerPoolTask> new_perf_task( 57 new PerfWorkerPoolTaskImpl); 58 perf_tasks[task] = new_perf_task; 59 } 60 61 perf_tasks_.swap(perf_tasks); 62 } 63 64 void BuildTaskGraph() { 65 unsigned priority = 0; 66 TaskGraph graph; 67 68 scoped_refptr<internal::WorkerPoolTask> 69 raster_required_for_activation_finished_task( 70 CreateRasterRequiredForActivationFinishedTask()); 71 internal::GraphNode* raster_required_for_activation_finished_node = 72 CreateGraphNodeForTask( 73 raster_required_for_activation_finished_task.get(), 74 priority++, 75 &graph); 76 77 scoped_refptr<internal::WorkerPoolTask> raster_finished_task( 78 CreateRasterFinishedTask()); 79 internal::GraphNode* raster_finished_node = 80 CreateGraphNodeForTask(raster_finished_task.get(), 81 priority++, 82 &graph); 83 84 for (RasterTaskVector::const_iterator it = raster_tasks().begin(); 85 it != raster_tasks().end(); ++it) { 86 internal::RasterWorkerPoolTask* task = it->get(); 87 88 TaskMap::iterator perf_it = perf_tasks_.find(task); 89 DCHECK(perf_it != perf_tasks_.end()); 90 if (perf_it != perf_tasks_.end()) { 91 internal::WorkerPoolTask* perf_task = perf_it->second.get(); 92 93 internal::GraphNode* perf_node = 94 CreateGraphNodeForRasterTask(perf_task, 95 task->dependencies(), 96 priority++, 97 &graph); 98 99 if (IsRasterTaskRequiredForActivation(task)) { 100 raster_required_for_activation_finished_node->add_dependency(); 101 perf_node->add_dependent( 102 raster_required_for_activation_finished_node); 103 } 104 105 raster_finished_node->add_dependency(); 106 perf_node->add_dependent(raster_finished_node); 107 } 108 } 109 } 110 111 private: 112 TaskMap perf_tasks_; 113 114 DISALLOW_COPY_AND_ASSIGN(PerfRasterWorkerPool); 115 }; 116 117 class RasterWorkerPoolPerfTest : public testing::Test { 118 public: 119 RasterWorkerPoolPerfTest() : num_runs_(0) {} 120 121 // Overridden from testing::Test: 122 virtual void SetUp() OVERRIDE { 123 raster_worker_pool_ = PerfRasterWorkerPool::Create(); 124 } 125 virtual void TearDown() OVERRIDE { 126 raster_worker_pool_->Shutdown(); 127 } 128 129 void EndTest() { 130 elapsed_ = base::TimeTicks::HighResNow() - start_time_; 131 } 132 133 void AfterTest(const std::string test_name) { 134 // Format matches chrome/test/perf/perf_test.h:PrintResult 135 printf("*RESULT %s: %.2f runs/s\n", 136 test_name.c_str(), 137 num_runs_ / elapsed_.InSecondsF()); 138 } 139 140 bool DidRun() { 141 ++num_runs_; 142 if (num_runs_ == kWarmupRuns) 143 start_time_ = base::TimeTicks::HighResNow(); 144 145 if (!start_time_.is_null() && (num_runs_ % kTimeCheckInterval) == 0) { 146 base::TimeDelta elapsed = base::TimeTicks::HighResNow() - start_time_; 147 if (elapsed >= base::TimeDelta::FromMilliseconds(kTimeLimitMillis)) { 148 elapsed_ = elapsed; 149 return false; 150 } 151 } 152 153 return true; 154 } 155 156 void CreateTasks(RasterWorkerPool::RasterTask::Queue* tasks, 157 unsigned num_raster_tasks, 158 unsigned num_image_decode_tasks) { 159 typedef std::vector<RasterWorkerPool::Task> TaskVector; 160 TaskVector image_decode_tasks; 161 162 for (unsigned i = 0; i < num_image_decode_tasks; ++i) { 163 image_decode_tasks.push_back( 164 RasterWorkerPool::CreateImageDecodeTask( 165 NULL, 166 0, 167 NULL, 168 base::Bind( 169 &RasterWorkerPoolPerfTest::OnImageDecodeTaskCompleted))); 170 } 171 172 for (unsigned i = 0; i < num_raster_tasks; ++i) { 173 RasterWorkerPool::Task::Set decode_tasks; 174 for (TaskVector::iterator it = image_decode_tasks.begin(); 175 it != image_decode_tasks.end(); ++it) 176 decode_tasks.Insert(*it); 177 178 tasks->Append( 179 RasterWorkerPool::CreateRasterTask( 180 NULL, 181 NULL, 182 gfx::Rect(), 183 1.0, 184 HIGH_QUALITY_RASTER_MODE, 185 false, 186 TileResolution(), 187 1, 188 NULL, 189 1, 190 NULL, 191 base::Bind(&RasterWorkerPoolPerfTest::OnRasterTaskCompleted), 192 &decode_tasks), 193 false); 194 } 195 } 196 197 void RunBuildTaskGraphTest(const std::string test_name, 198 unsigned num_raster_tasks, 199 unsigned num_image_decode_tasks) { 200 start_time_ = base::TimeTicks(); 201 num_runs_ = 0; 202 RasterWorkerPool::RasterTask::Queue tasks; 203 CreateTasks(&tasks, num_raster_tasks, num_image_decode_tasks); 204 raster_worker_pool_->SetRasterTasks(&tasks); 205 do { 206 raster_worker_pool_->BuildTaskGraph(); 207 } while (DidRun()); 208 209 AfterTest(test_name); 210 } 211 212 protected: 213 static void OnRasterTaskCompleted(const PicturePileImpl::Analysis& analysis, 214 bool was_canceled) {} 215 static void OnImageDecodeTaskCompleted(bool was_canceled) {} 216 217 scoped_ptr<PerfRasterWorkerPool> raster_worker_pool_; 218 base::TimeTicks start_time_; 219 base::TimeDelta elapsed_; 220 int num_runs_; 221 }; 222 223 TEST_F(RasterWorkerPoolPerfTest, BuildTaskGraph) { 224 RunBuildTaskGraphTest("build_task_graph_10_0", 10, 0); 225 RunBuildTaskGraphTest("build_task_graph_100_0", 100, 0); 226 RunBuildTaskGraphTest("build_task_graph_1000_0", 1000, 0); 227 RunBuildTaskGraphTest("build_task_graph_10_1", 10, 1); 228 RunBuildTaskGraphTest("build_task_graph_100_1", 100, 1); 229 RunBuildTaskGraphTest("build_task_graph_1000_1", 1000, 1); 230 RunBuildTaskGraphTest("build_task_graph_10_4", 10, 4); 231 RunBuildTaskGraphTest("build_task_graph_100_4", 100, 4); 232 RunBuildTaskGraphTest("build_task_graph_1000_4", 1000, 4); 233 RunBuildTaskGraphTest("build_task_graph_10_16", 10, 16); 234 RunBuildTaskGraphTest("build_task_graph_100_16", 100, 16); 235 RunBuildTaskGraphTest("build_task_graph_1000_16", 1000, 16); 236 } 237 238 } // namespace 239 240 } // namespace cc 241