Home | History | Annotate | Download | only in resources
      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