Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / cc / resources / task_graph_runner_perftest.cc
index 5e952a3..71933f5 100644 (file)
@@ -4,6 +4,8 @@
 
 #include "cc/resources/task_graph_runner.h"
 
+#include <vector>
+
 #include "base/time/time.h"
 #include "cc/base/completion_event.h"
 #include "cc/test/lap_timer.h"
@@ -19,40 +21,21 @@ static const int kTimeCheckInterval = 10;
 
 class PerfTaskImpl : public internal::Task {
  public:
+  typedef std::vector<scoped_refptr<PerfTaskImpl> > Vector;
+
   PerfTaskImpl() {}
 
   // Overridden from internal::Task:
   virtual void RunOnWorkerThread(unsigned thread_index) OVERRIDE {}
 
+  void Reset() { did_run_ = false; }
+
  private:
   virtual ~PerfTaskImpl() {}
 
   DISALLOW_COPY_AND_ASSIGN(PerfTaskImpl);
 };
 
-class PerfControlTaskImpl : public internal::Task {
- public:
-  PerfControlTaskImpl() {}
-
-  // Overridden from internal::Task:
-  virtual void RunOnWorkerThread(unsigned thread_index) OVERRIDE {
-    did_start_.Signal();
-    can_finish_.Wait();
-  }
-
-  void WaitForTaskToStartRunning() { did_start_.Wait(); }
-
-  void AllowTaskToFinish() { can_finish_.Signal(); }
-
- private:
-  virtual ~PerfControlTaskImpl() {}
-
-  CompletionEvent did_start_;
-  CompletionEvent can_finish_;
-
-  DISALLOW_COPY_AND_ASSIGN(PerfControlTaskImpl);
-};
-
 class TaskGraphRunnerPerfTest : public testing::Test {
  public:
   TaskGraphRunnerPerfTest()
@@ -63,7 +46,8 @@ class TaskGraphRunnerPerfTest : public testing::Test {
   // Overridden from testing::Test:
   virtual void SetUp() OVERRIDE {
     task_graph_runner_ =
-        make_scoped_ptr(new internal::TaskGraphRunner(1, "PerfTest"));
+        make_scoped_ptr(new internal::TaskGraphRunner(0,  // 0 worker threads
+                                                      "PerfTest"));
     namespace_token_ = task_graph_runner_->GetNamespaceToken();
   }
   virtual void TearDown() OVERRIDE { task_graph_runner_.reset(); }
@@ -74,23 +58,66 @@ class TaskGraphRunnerPerfTest : public testing::Test {
         "*RESULT %s: %.2f runs/s\n", test_name.c_str(), timer_.LapsPerSecond());
   }
 
+  void RunBuildTaskGraphTest(const std::string& test_name,
+                             int num_top_level_tasks,
+                             int num_tasks,
+                             int num_leaf_tasks) {
+    PerfTaskImpl::Vector top_level_tasks;
+    PerfTaskImpl::Vector tasks;
+    PerfTaskImpl::Vector leaf_tasks;
+    CreateTasks(num_top_level_tasks, &top_level_tasks);
+    CreateTasks(num_tasks, &tasks);
+    CreateTasks(num_leaf_tasks, &leaf_tasks);
+
+    // Avoid unnecessary heap allocations by reusing the same graph.
+    internal::TaskGraph graph;
+
+    timer_.Reset();
+    do {
+      graph.Reset();
+      BuildTaskGraph(top_level_tasks, tasks, leaf_tasks, &graph);
+      timer_.NextLap();
+    } while (!timer_.HasTimeLimitExpired());
+
+    perf_test::PrintResult("build_task_graph",
+                           "",
+                           test_name,
+                           timer_.LapsPerSecond(),
+                           "runs/s",
+                           true);
+  }
+
   void RunScheduleTasksTest(const std::string& test_name,
-                            unsigned max_depth,
-                            unsigned num_children_per_node) {
+                            int num_top_level_tasks,
+                            int num_tasks,
+                            int num_leaf_tasks) {
+    PerfTaskImpl::Vector top_level_tasks;
+    PerfTaskImpl::Vector tasks;
+    PerfTaskImpl::Vector leaf_tasks;
+    CreateTasks(num_top_level_tasks, &top_level_tasks);
+    CreateTasks(num_tasks, &tasks);
+    CreateTasks(num_leaf_tasks, &leaf_tasks);
+
+    // Avoid unnecessary heap allocations by reusing the same graph and
+    // completed tasks vector.
+    internal::TaskGraph graph;
+    internal::Task::Vector completed_tasks;
+
     timer_.Reset();
     do {
-      scoped_refptr<PerfControlTaskImpl> leaf_task(new PerfControlTaskImpl);
-      ScheduleTasks(NULL, leaf_task.get(), max_depth, num_children_per_node);
-      leaf_task->WaitForTaskToStartRunning();
-      ScheduleTasks(NULL, NULL, 0, 0);
-      leaf_task->AllowTaskToFinish();
-      task_graph_runner_->WaitForTasksToFinishRunning(namespace_token_);
-      internal::Task::Vector completed_tasks;
-      task_graph_runner_->CollectCompletedTasks(namespace_token_,
-                                                &completed_tasks);
+      graph.Reset();
+      BuildTaskGraph(top_level_tasks, tasks, leaf_tasks, &graph);
+      task_graph_runner_->SetTaskGraph(namespace_token_, &graph);
+      // Shouldn't be any tasks to collect as we reschedule the same set
+      // of tasks.
+      DCHECK_EQ(0u, CollectCompletedTasks(&completed_tasks));
       timer_.NextLap();
     } while (!timer_.HasTimeLimitExpired());
 
+    internal::TaskGraph empty;
+    task_graph_runner_->SetTaskGraph(namespace_token_, &empty);
+    CollectCompletedTasks(&completed_tasks);
+
     perf_test::PrintResult("schedule_tasks",
                            "",
                            test_name,
@@ -99,16 +126,80 @@ class TaskGraphRunnerPerfTest : public testing::Test {
                            true);
   }
 
-  void RunExecuteTasksTest(const std::string& test_name,
-                           unsigned max_depth,
-                           unsigned num_children_per_node) {
+  void RunScheduleAlternateTasksTest(const std::string& test_name,
+                                     int num_top_level_tasks,
+                                     int num_tasks,
+                                     int num_leaf_tasks) {
+    const size_t kNumVersions = 2;
+    PerfTaskImpl::Vector top_level_tasks[kNumVersions];
+    PerfTaskImpl::Vector tasks[kNumVersions];
+    PerfTaskImpl::Vector leaf_tasks[kNumVersions];
+    for (size_t i = 0; i < kNumVersions; ++i) {
+      CreateTasks(num_top_level_tasks, &top_level_tasks[i]);
+      CreateTasks(num_tasks, &tasks[i]);
+      CreateTasks(num_leaf_tasks, &leaf_tasks[i]);
+    }
+
+    // Avoid unnecessary heap allocations by reusing the same graph and
+    // completed tasks vector.
+    internal::TaskGraph graph;
+    internal::Task::Vector completed_tasks;
+
+    size_t count = 0;
     timer_.Reset();
     do {
-      ScheduleTasks(NULL, NULL, max_depth, num_children_per_node);
-      task_graph_runner_->WaitForTasksToFinishRunning(namespace_token_);
-      internal::Task::Vector completed_tasks;
-      task_graph_runner_->CollectCompletedTasks(namespace_token_,
-                                                &completed_tasks);
+      graph.Reset();
+      BuildTaskGraph(top_level_tasks[count % kNumVersions],
+                     tasks[count % kNumVersions],
+                     leaf_tasks[count % kNumVersions],
+                     &graph);
+      task_graph_runner_->SetTaskGraph(namespace_token_, &graph);
+      CollectCompletedTasks(&completed_tasks);
+      completed_tasks.clear();
+      ++count;
+      timer_.NextLap();
+    } while (!timer_.HasTimeLimitExpired());
+
+    internal::TaskGraph empty;
+    task_graph_runner_->SetTaskGraph(namespace_token_, &empty);
+    CollectCompletedTasks(&completed_tasks);
+
+    perf_test::PrintResult("schedule_alternate_tasks",
+                           "",
+                           test_name,
+                           timer_.LapsPerSecond(),
+                           "runs/s",
+                           true);
+  }
+
+  void RunScheduleAndExecuteTasksTest(const std::string& test_name,
+                                      int num_top_level_tasks,
+                                      int num_tasks,
+                                      int num_leaf_tasks) {
+    PerfTaskImpl::Vector top_level_tasks;
+    PerfTaskImpl::Vector tasks;
+    PerfTaskImpl::Vector leaf_tasks;
+    CreateTasks(num_top_level_tasks, &top_level_tasks);
+    CreateTasks(num_tasks, &tasks);
+    CreateTasks(num_leaf_tasks, &leaf_tasks);
+
+    // Avoid unnecessary heap allocations by reusing the same graph and
+    // completed tasks vector.
+    internal::TaskGraph graph;
+    internal::Task::Vector completed_tasks;
+
+    timer_.Reset();
+    do {
+      graph.Reset();
+      BuildTaskGraph(top_level_tasks, tasks, leaf_tasks, &graph);
+      task_graph_runner_->SetTaskGraph(namespace_token_, &graph);
+      while (task_graph_runner_->RunTaskForTesting())
+        continue;
+      CollectCompletedTasks(&completed_tasks);
+      completed_tasks.clear();
+      ResetTasks(&top_level_tasks);
+      ResetTasks(&tasks);
+      ResetTasks(&leaf_tasks);
       timer_.NextLap();
     } while (!timer_.HasTimeLimitExpired());
 
@@ -117,100 +208,108 @@ class TaskGraphRunnerPerfTest : public testing::Test {
   }
 
  private:
-  void ScheduleTasks(internal::Task* root_task,
-                     internal::Task* leaf_task,
-                     unsigned max_depth,
-                     unsigned num_children_per_node) {
-    internal::Task::Vector tasks;
-    internal::GraphNode::Map graph;
-
-    scoped_ptr<internal::GraphNode> root_node;
-    if (root_task)
-      root_node = make_scoped_ptr(new internal::GraphNode(root_task, 0u));
-
-    scoped_ptr<internal::GraphNode> leaf_node;
-    if (leaf_task)
-      leaf_node = make_scoped_ptr(new internal::GraphNode(leaf_task, 0u));
-
-    if (max_depth) {
-      BuildTaskGraph(&tasks,
-                     &graph,
-                     root_node.get(),
-                     leaf_node.get(),
-                     0,
-                     max_depth,
-                     num_children_per_node);
-    }
-
-    if (leaf_node)
-      graph.set(leaf_task, leaf_node.Pass());
+  void CreateTasks(int num_tasks, PerfTaskImpl::Vector* tasks) {
+    for (int i = 0; i < num_tasks; ++i)
+      tasks->push_back(make_scoped_refptr(new PerfTaskImpl));
+  }
 
-    if (root_node)
-      graph.set(root_task, root_node.Pass());
+  void ResetTasks(PerfTaskImpl::Vector* tasks) {
+    for (PerfTaskImpl::Vector::iterator it = tasks->begin(); it != tasks->end();
+         ++it) {
+      PerfTaskImpl* task = it->get();
+      task->Reset();
+    }
+  }
 
-    task_graph_runner_->SetTaskGraph(namespace_token_, &graph);
+  void BuildTaskGraph(const PerfTaskImpl::Vector& top_level_tasks,
+                      const PerfTaskImpl::Vector& tasks,
+                      const PerfTaskImpl::Vector& leaf_tasks,
+                      internal::TaskGraph* graph) {
+    DCHECK(graph->nodes.empty());
+    DCHECK(graph->edges.empty());
+
+    for (PerfTaskImpl::Vector::const_iterator it = leaf_tasks.begin();
+         it != leaf_tasks.end();
+         ++it) {
+      graph->nodes.push_back(internal::TaskGraph::Node(it->get(), 0u, 0u));
+    }
 
-    tasks_.swap(tasks);
-  }
+    for (PerfTaskImpl::Vector::const_iterator it = tasks.begin();
+         it != tasks.end();
+         ++it) {
+      graph->nodes.push_back(
+          internal::TaskGraph::Node(it->get(), 0u, leaf_tasks.size()));
+
+      for (PerfTaskImpl::Vector::const_iterator leaf_it = leaf_tasks.begin();
+           leaf_it != leaf_tasks.end();
+           ++leaf_it) {
+        graph->edges.push_back(
+            internal::TaskGraph::Edge(leaf_it->get(), it->get()));
+      }
 
-  void BuildTaskGraph(internal::Task::Vector* tasks,
-                      internal::GraphNode::Map* graph,
-                      internal::GraphNode* dependent_node,
-                      internal::GraphNode* leaf_node,
-                      unsigned current_depth,
-                      unsigned max_depth,
-                      unsigned num_children_per_node) {
-    scoped_refptr<PerfTaskImpl> task(new PerfTaskImpl);
-    scoped_ptr<internal::GraphNode> node(
-        new internal::GraphNode(task.get(), 0u));
-
-    if (current_depth < max_depth) {
-      for (unsigned i = 0; i < num_children_per_node; ++i) {
-        BuildTaskGraph(tasks,
-                       graph,
-                       node.get(),
-                       leaf_node,
-                       current_depth + 1,
-                       max_depth,
-                       num_children_per_node);
+      for (PerfTaskImpl::Vector::const_iterator top_level_it =
+               top_level_tasks.begin();
+           top_level_it != top_level_tasks.end();
+           ++top_level_it) {
+        graph->edges.push_back(
+            internal::TaskGraph::Edge(it->get(), top_level_it->get()));
       }
-    } else if (leaf_node) {
-      leaf_node->add_dependent(node.get());
-      node->add_dependency();
     }
 
-    if (dependent_node) {
-      node->add_dependent(dependent_node);
-      dependent_node->add_dependency();
+    for (PerfTaskImpl::Vector::const_iterator it = top_level_tasks.begin();
+         it != top_level_tasks.end();
+         ++it) {
+      graph->nodes.push_back(
+          internal::TaskGraph::Node(it->get(), 0u, tasks.size()));
     }
-    graph->set(task.get(), node.Pass());
-    tasks->push_back(task.get());
+  }
+
+  size_t CollectCompletedTasks(internal::Task::Vector* completed_tasks) {
+    DCHECK(completed_tasks->empty());
+    task_graph_runner_->CollectCompletedTasks(namespace_token_,
+                                              completed_tasks);
+    return completed_tasks->size();
   }
 
   scoped_ptr<internal::TaskGraphRunner> task_graph_runner_;
   internal::NamespaceToken namespace_token_;
-  internal::Task::Vector tasks_;
   LapTimer timer_;
 };
 
+TEST_F(TaskGraphRunnerPerfTest, BuildTaskGraph) {
+  RunBuildTaskGraphTest("0_1_0", 0, 1, 0);
+  RunBuildTaskGraphTest("0_32_0", 0, 32, 0);
+  RunBuildTaskGraphTest("2_1_0", 2, 1, 0);
+  RunBuildTaskGraphTest("2_32_0", 2, 32, 0);
+  RunBuildTaskGraphTest("2_1_1", 2, 1, 1);
+  RunBuildTaskGraphTest("2_32_1", 2, 32, 1);
+}
+
 TEST_F(TaskGraphRunnerPerfTest, ScheduleTasks) {
-  RunScheduleTasksTest("1_10", 1, 10);
-  RunScheduleTasksTest("1_1000", 1, 1000);
-  RunScheduleTasksTest("2_10", 2, 10);
-  RunScheduleTasksTest("5_5", 5, 5);
-  RunScheduleTasksTest("10_2", 10, 2);
-  RunScheduleTasksTest("1000_1", 1000, 1);
-  RunScheduleTasksTest("10_1", 10, 1);
+  RunScheduleTasksTest("0_1_0", 0, 1, 0);
+  RunScheduleTasksTest("0_32_0", 0, 32, 0);
+  RunScheduleTasksTest("2_1_0", 2, 1, 0);
+  RunScheduleTasksTest("2_32_0", 2, 32, 0);
+  RunScheduleTasksTest("2_1_1", 2, 1, 1);
+  RunScheduleTasksTest("2_32_1", 2, 32, 1);
+}
+
+TEST_F(TaskGraphRunnerPerfTest, ScheduleAlternateTasks) {
+  RunScheduleAlternateTasksTest("0_1_0", 0, 1, 0);
+  RunScheduleAlternateTasksTest("0_32_0", 0, 32, 0);
+  RunScheduleAlternateTasksTest("2_1_0", 2, 1, 0);
+  RunScheduleAlternateTasksTest("2_32_0", 2, 32, 0);
+  RunScheduleAlternateTasksTest("2_1_1", 2, 1, 1);
+  RunScheduleAlternateTasksTest("2_32_1", 2, 32, 1);
 }
 
-TEST_F(TaskGraphRunnerPerfTest, ExecuteTasks) {
-  RunExecuteTasksTest("1_10", 1, 10);
-  RunExecuteTasksTest("1_1000", 1, 1000);
-  RunExecuteTasksTest("2_10", 2, 10);
-  RunExecuteTasksTest("5_5", 5, 5);
-  RunExecuteTasksTest("10_2", 10, 2);
-  RunExecuteTasksTest("1000_1", 1000, 1);
-  RunExecuteTasksTest("10_1", 10, 1);
+TEST_F(TaskGraphRunnerPerfTest, ScheduleAndExecuteTasks) {
+  RunScheduleAndExecuteTasksTest("0_1_0", 0, 1, 0);
+  RunScheduleAndExecuteTasksTest("0_32_0", 0, 32, 0);
+  RunScheduleAndExecuteTasksTest("2_1_0", 2, 1, 0);
+  RunScheduleAndExecuteTasksTest("2_32_0", 2, 32, 0);
+  RunScheduleAndExecuteTasksTest("2_1_1", 2, 1, 1);
+  RunScheduleAndExecuteTasksTest("2_32_1", 2, 32, 1);
 }
 
 }  // namespace