| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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/resources/task_graph_runner.h" | 5 #include "cc/resources/task_graph_runner.h" |
| 6 | 6 |
| 7 #include <vector> | 7 #include <vector> |
| 8 | 8 |
| 9 #include "base/time/time.h" | 9 #include "base/time/time.h" |
| 10 #include "cc/base/completion_event.h" | 10 #include "cc/base/completion_event.h" |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 62 int num_top_level_tasks, | 62 int num_top_level_tasks, |
| 63 int num_tasks, | 63 int num_tasks, |
| 64 int num_leaf_tasks) { | 64 int num_leaf_tasks) { |
| 65 PerfTaskImpl::Vector top_level_tasks; | 65 PerfTaskImpl::Vector top_level_tasks; |
| 66 PerfTaskImpl::Vector tasks; | 66 PerfTaskImpl::Vector tasks; |
| 67 PerfTaskImpl::Vector leaf_tasks; | 67 PerfTaskImpl::Vector leaf_tasks; |
| 68 CreateTasks(num_top_level_tasks, &top_level_tasks); | 68 CreateTasks(num_top_level_tasks, &top_level_tasks); |
| 69 CreateTasks(num_tasks, &tasks); | 69 CreateTasks(num_tasks, &tasks); |
| 70 CreateTasks(num_leaf_tasks, &leaf_tasks); | 70 CreateTasks(num_leaf_tasks, &leaf_tasks); |
| 71 | 71 |
| 72 // Avoid unnecessary heap allocations by reusing the same graph. |
| 73 internal::TaskGraph graph; |
| 74 |
| 72 timer_.Reset(); | 75 timer_.Reset(); |
| 73 do { | 76 do { |
| 74 internal::GraphNode::Map graph; | 77 graph.Reset(); |
| 75 BuildTaskGraph(top_level_tasks, tasks, leaf_tasks, &graph); | 78 BuildTaskGraph(top_level_tasks, tasks, leaf_tasks, &graph); |
| 76 timer_.NextLap(); | 79 timer_.NextLap(); |
| 77 } while (!timer_.HasTimeLimitExpired()); | 80 } while (!timer_.HasTimeLimitExpired()); |
| 78 | 81 |
| 79 perf_test::PrintResult("build_task_graph", | 82 perf_test::PrintResult("build_task_graph", |
| 80 "", | 83 "", |
| 81 test_name, | 84 test_name, |
| 82 timer_.LapsPerSecond(), | 85 timer_.LapsPerSecond(), |
| 83 "runs/s", | 86 "runs/s", |
| 84 true); | 87 true); |
| 85 } | 88 } |
| 86 | 89 |
| 87 void RunScheduleTasksTest(const std::string& test_name, | 90 void RunScheduleTasksTest(const std::string& test_name, |
| 88 int num_top_level_tasks, | 91 int num_top_level_tasks, |
| 89 int num_tasks, | 92 int num_tasks, |
| 90 int num_leaf_tasks) { | 93 int num_leaf_tasks) { |
| 91 PerfTaskImpl::Vector top_level_tasks; | 94 PerfTaskImpl::Vector top_level_tasks; |
| 92 PerfTaskImpl::Vector tasks; | 95 PerfTaskImpl::Vector tasks; |
| 93 PerfTaskImpl::Vector leaf_tasks; | 96 PerfTaskImpl::Vector leaf_tasks; |
| 94 CreateTasks(num_top_level_tasks, &top_level_tasks); | 97 CreateTasks(num_top_level_tasks, &top_level_tasks); |
| 95 CreateTasks(num_tasks, &tasks); | 98 CreateTasks(num_tasks, &tasks); |
| 96 CreateTasks(num_leaf_tasks, &leaf_tasks); | 99 CreateTasks(num_leaf_tasks, &leaf_tasks); |
| 97 | 100 |
| 101 // Avoid unnecessary heap allocations by reusing the same graph and |
| 102 // completed tasks vector. |
| 103 internal::TaskGraph graph; |
| 104 internal::Task::Vector completed_tasks; |
| 105 |
| 98 timer_.Reset(); | 106 timer_.Reset(); |
| 99 do { | 107 do { |
| 100 internal::GraphNode::Map graph; | 108 graph.Reset(); |
| 101 BuildTaskGraph(top_level_tasks, tasks, leaf_tasks, &graph); | 109 BuildTaskGraph(top_level_tasks, tasks, leaf_tasks, &graph); |
| 102 task_graph_runner_->SetTaskGraph(namespace_token_, &graph); | 110 task_graph_runner_->SetTaskGraph(namespace_token_, &graph); |
| 103 // Shouldn't be any tasks to collect as we reschedule the same set | 111 // Shouldn't be any tasks to collect as we reschedule the same set |
| 104 // of tasks. | 112 // of tasks. |
| 105 DCHECK_EQ(0u, CollectCompletedTasks()); | 113 DCHECK_EQ(0u, CollectCompletedTasks(&completed_tasks)); |
| 106 timer_.NextLap(); | 114 timer_.NextLap(); |
| 107 } while (!timer_.HasTimeLimitExpired()); | 115 } while (!timer_.HasTimeLimitExpired()); |
| 108 | 116 |
| 109 internal::GraphNode::Map empty; | 117 internal::TaskGraph empty; |
| 110 task_graph_runner_->SetTaskGraph(namespace_token_, &empty); | 118 task_graph_runner_->SetTaskGraph(namespace_token_, &empty); |
| 111 CollectCompletedTasks(); | 119 CollectCompletedTasks(&completed_tasks); |
| 112 | 120 |
| 113 perf_test::PrintResult("schedule_tasks", | 121 perf_test::PrintResult("schedule_tasks", |
| 114 "", | 122 "", |
| 115 test_name, | 123 test_name, |
| 116 timer_.LapsPerSecond(), | 124 timer_.LapsPerSecond(), |
| 117 "runs/s", | 125 "runs/s", |
| 118 true); | 126 true); |
| 119 } | 127 } |
| 120 | 128 |
| 121 void RunScheduleAlternateTasksTest(const std::string& test_name, | 129 void RunScheduleAlternateTasksTest(const std::string& test_name, |
| 122 int num_top_level_tasks, | 130 int num_top_level_tasks, |
| 123 int num_tasks, | 131 int num_tasks, |
| 124 int num_leaf_tasks) { | 132 int num_leaf_tasks) { |
| 125 const int kNumVersions = 2; | 133 const int kNumVersions = 2; |
| 126 PerfTaskImpl::Vector top_level_tasks[kNumVersions]; | 134 PerfTaskImpl::Vector top_level_tasks[kNumVersions]; |
| 127 PerfTaskImpl::Vector tasks[kNumVersions]; | 135 PerfTaskImpl::Vector tasks[kNumVersions]; |
| 128 PerfTaskImpl::Vector leaf_tasks[kNumVersions]; | 136 PerfTaskImpl::Vector leaf_tasks[kNumVersions]; |
| 129 for (int i = 0; i < kNumVersions; ++i) { | 137 for (int i = 0; i < kNumVersions; ++i) { |
| 130 CreateTasks(num_top_level_tasks, &top_level_tasks[i]); | 138 CreateTasks(num_top_level_tasks, &top_level_tasks[i]); |
| 131 CreateTasks(num_tasks, &tasks[i]); | 139 CreateTasks(num_tasks, &tasks[i]); |
| 132 CreateTasks(num_leaf_tasks, &leaf_tasks[i]); | 140 CreateTasks(num_leaf_tasks, &leaf_tasks[i]); |
| 133 } | 141 } |
| 134 | 142 |
| 143 // Avoid unnecessary heap allocations by reusing the same graph and |
| 144 // completed tasks vector. |
| 145 internal::TaskGraph graph; |
| 146 internal::Task::Vector completed_tasks; |
| 147 |
| 135 int count = 0; | 148 int count = 0; |
| 136 timer_.Reset(); | 149 timer_.Reset(); |
| 137 do { | 150 do { |
| 138 internal::GraphNode::Map graph; | 151 graph.Reset(); |
| 139 BuildTaskGraph(top_level_tasks[count % kNumVersions], | 152 BuildTaskGraph(top_level_tasks[count % kNumVersions], |
| 140 tasks[count % kNumVersions], | 153 tasks[count % kNumVersions], |
| 141 leaf_tasks[count % kNumVersions], | 154 leaf_tasks[count % kNumVersions], |
| 142 &graph); | 155 &graph); |
| 143 task_graph_runner_->SetTaskGraph(namespace_token_, &graph); | 156 task_graph_runner_->SetTaskGraph(namespace_token_, &graph); |
| 144 CollectCompletedTasks(); | 157 CollectCompletedTasks(&completed_tasks); |
| 158 completed_tasks.clear(); |
| 145 ++count; | 159 ++count; |
| 146 timer_.NextLap(); | 160 timer_.NextLap(); |
| 147 } while (!timer_.HasTimeLimitExpired()); | 161 } while (!timer_.HasTimeLimitExpired()); |
| 148 | 162 |
| 149 internal::GraphNode::Map empty; | 163 internal::TaskGraph empty; |
| 150 task_graph_runner_->SetTaskGraph(namespace_token_, &empty); | 164 task_graph_runner_->SetTaskGraph(namespace_token_, &empty); |
| 151 CollectCompletedTasks(); | 165 CollectCompletedTasks(&completed_tasks); |
| 152 | 166 |
| 153 perf_test::PrintResult("schedule_alternate_tasks", | 167 perf_test::PrintResult("schedule_alternate_tasks", |
| 154 "", | 168 "", |
| 155 test_name, | 169 test_name, |
| 156 timer_.LapsPerSecond(), | 170 timer_.LapsPerSecond(), |
| 157 "runs/s", | 171 "runs/s", |
| 158 true); | 172 true); |
| 159 } | 173 } |
| 160 | 174 |
| 161 void RunScheduleAndExecuteTasksTest(const std::string& test_name, | 175 void RunScheduleAndExecuteTasksTest(const std::string& test_name, |
| 162 int num_top_level_tasks, | 176 int num_top_level_tasks, |
| 163 int num_tasks, | 177 int num_tasks, |
| 164 int num_leaf_tasks) { | 178 int num_leaf_tasks) { |
| 165 PerfTaskImpl::Vector top_level_tasks; | 179 PerfTaskImpl::Vector top_level_tasks; |
| 166 PerfTaskImpl::Vector tasks; | 180 PerfTaskImpl::Vector tasks; |
| 167 PerfTaskImpl::Vector leaf_tasks; | 181 PerfTaskImpl::Vector leaf_tasks; |
| 168 CreateTasks(num_top_level_tasks, &top_level_tasks); | 182 CreateTasks(num_top_level_tasks, &top_level_tasks); |
| 169 CreateTasks(num_tasks, &tasks); | 183 CreateTasks(num_tasks, &tasks); |
| 170 CreateTasks(num_leaf_tasks, &leaf_tasks); | 184 CreateTasks(num_leaf_tasks, &leaf_tasks); |
| 171 | 185 |
| 186 // Avoid unnecessary heap allocations by reusing the same graph and |
| 187 // completed tasks vector. |
| 188 internal::TaskGraph graph; |
| 189 internal::Task::Vector completed_tasks; |
| 190 |
| 172 timer_.Reset(); | 191 timer_.Reset(); |
| 173 do { | 192 do { |
| 174 internal::GraphNode::Map graph; | 193 graph.Reset(); |
| 175 BuildTaskGraph(top_level_tasks, tasks, leaf_tasks, &graph); | 194 BuildTaskGraph(top_level_tasks, tasks, leaf_tasks, &graph); |
| 176 task_graph_runner_->SetTaskGraph(namespace_token_, &graph); | 195 task_graph_runner_->SetTaskGraph(namespace_token_, &graph); |
| 177 while (task_graph_runner_->RunTaskForTesting()) | 196 while (task_graph_runner_->RunTaskForTesting()) |
| 178 continue; | 197 continue; |
| 179 CollectCompletedTasks(); | 198 CollectCompletedTasks(&completed_tasks); |
| 199 completed_tasks.clear(); |
| 180 ResetTasks(&top_level_tasks); | 200 ResetTasks(&top_level_tasks); |
| 181 ResetTasks(&tasks); | 201 ResetTasks(&tasks); |
| 182 ResetTasks(&leaf_tasks); | 202 ResetTasks(&leaf_tasks); |
| 183 timer_.NextLap(); | 203 timer_.NextLap(); |
| 184 } while (!timer_.HasTimeLimitExpired()); | 204 } while (!timer_.HasTimeLimitExpired()); |
| 185 | 205 |
| 186 perf_test::PrintResult( | 206 perf_test::PrintResult( |
| 187 "execute_tasks", "", test_name, timer_.LapsPerSecond(), "runs/s", true); | 207 "execute_tasks", "", test_name, timer_.LapsPerSecond(), "runs/s", true); |
| 188 } | 208 } |
| 189 | 209 |
| 190 private: | 210 private: |
| 191 void CreateTasks(int num_tasks, PerfTaskImpl::Vector* tasks) { | 211 void CreateTasks(int num_tasks, PerfTaskImpl::Vector* tasks) { |
| 192 for (int i = 0; i < num_tasks; ++i) | 212 for (int i = 0; i < num_tasks; ++i) |
| 193 tasks->push_back(make_scoped_refptr(new PerfTaskImpl)); | 213 tasks->push_back(make_scoped_refptr(new PerfTaskImpl)); |
| 194 } | 214 } |
| 195 | 215 |
| 196 void ResetTasks(PerfTaskImpl::Vector* tasks) { | 216 void ResetTasks(PerfTaskImpl::Vector* tasks) { |
| 197 for (PerfTaskImpl::Vector::iterator it = tasks->begin(); it != tasks->end(); | 217 for (PerfTaskImpl::Vector::iterator it = tasks->begin(); it != tasks->end(); |
| 198 ++it) { | 218 ++it) { |
| 199 PerfTaskImpl* task = it->get(); | 219 PerfTaskImpl* task = it->get(); |
| 200 task->Reset(); | 220 task->Reset(); |
| 201 } | 221 } |
| 202 } | 222 } |
| 203 | 223 |
| 204 void BuildTaskGraph(const PerfTaskImpl::Vector& top_level_tasks, | 224 void BuildTaskGraph(const PerfTaskImpl::Vector& top_level_tasks, |
| 205 const PerfTaskImpl::Vector& tasks, | 225 const PerfTaskImpl::Vector& tasks, |
| 206 const PerfTaskImpl::Vector& leaf_tasks, | 226 const PerfTaskImpl::Vector& leaf_tasks, |
| 207 internal::GraphNode::Map* graph) { | 227 internal::TaskGraph* graph) { |
| 208 typedef std::vector<internal::GraphNode*> NodeVector; | 228 DCHECK(graph->nodes.empty()); |
| 229 DCHECK(graph->edges.empty()); |
| 209 | 230 |
| 210 NodeVector top_level_nodes; | |
| 211 top_level_nodes.reserve(top_level_tasks.size()); | |
| 212 for (PerfTaskImpl::Vector::const_iterator it = top_level_tasks.begin(); | |
| 213 it != top_level_tasks.end(); | |
| 214 ++it) { | |
| 215 internal::Task* top_level_task = it->get(); | |
| 216 scoped_ptr<internal::GraphNode> top_level_node( | |
| 217 new internal::GraphNode(top_level_task, 0u)); | |
| 218 | |
| 219 top_level_nodes.push_back(top_level_node.get()); | |
| 220 graph->set(top_level_task, top_level_node.Pass()); | |
| 221 } | |
| 222 | |
| 223 NodeVector leaf_nodes; | |
| 224 leaf_nodes.reserve(leaf_tasks.size()); | |
| 225 for (PerfTaskImpl::Vector::const_iterator it = leaf_tasks.begin(); | 231 for (PerfTaskImpl::Vector::const_iterator it = leaf_tasks.begin(); |
| 226 it != leaf_tasks.end(); | 232 it != leaf_tasks.end(); |
| 227 ++it) { | 233 ++it) { |
| 228 internal::Task* leaf_task = it->get(); | 234 graph->nodes.push_back(internal::TaskGraph::Node(it->get(), 0u, 0u)); |
| 229 scoped_ptr<internal::GraphNode> leaf_node( | |
| 230 new internal::GraphNode(leaf_task, 0u)); | |
| 231 | |
| 232 leaf_nodes.push_back(leaf_node.get()); | |
| 233 graph->set(leaf_task, leaf_node.Pass()); | |
| 234 } | 235 } |
| 235 | 236 |
| 236 for (PerfTaskImpl::Vector::const_iterator it = tasks.begin(); | 237 for (PerfTaskImpl::Vector::const_iterator it = tasks.begin(); |
| 237 it != tasks.end(); | 238 it != tasks.end(); |
| 238 ++it) { | 239 ++it) { |
| 239 internal::Task* task = it->get(); | 240 graph->nodes.push_back( |
| 240 scoped_ptr<internal::GraphNode> node(new internal::GraphNode(task, 0u)); | 241 internal::TaskGraph::Node(it->get(), 0u, leaf_tasks.size())); |
| 241 | 242 |
| 242 for (NodeVector::iterator node_it = top_level_nodes.begin(); | 243 for (PerfTaskImpl::Vector::const_iterator leaf_it = leaf_tasks.begin(); |
| 243 node_it != top_level_nodes.end(); | 244 leaf_it != leaf_tasks.end(); |
| 244 ++node_it) { | 245 ++leaf_it) { |
| 245 internal::GraphNode* top_level_node = *node_it; | 246 graph->edges.push_back( |
| 246 node->add_dependent(top_level_node); | 247 internal::TaskGraph::Edge(leaf_it->get(), it->get())); |
| 247 top_level_node->add_dependency(); | |
| 248 } | 248 } |
| 249 | 249 |
| 250 for (NodeVector::iterator node_it = leaf_nodes.begin(); | 250 for (PerfTaskImpl::Vector::const_iterator top_level_it = |
| 251 node_it != leaf_nodes.end(); | 251 top_level_tasks.begin(); |
| 252 ++node_it) { | 252 top_level_it != top_level_tasks.end(); |
| 253 internal::GraphNode* leaf_node = *node_it; | 253 ++top_level_it) { |
| 254 leaf_node->add_dependent(node.get()); | 254 graph->edges.push_back( |
| 255 node->add_dependency(); | 255 internal::TaskGraph::Edge(it->get(), top_level_it->get())); |
| 256 } | 256 } |
| 257 } |
| 257 | 258 |
| 258 graph->set(task, node.Pass()); | 259 for (PerfTaskImpl::Vector::const_iterator it = top_level_tasks.begin(); |
| 260 it != top_level_tasks.end(); |
| 261 ++it) { |
| 262 graph->nodes.push_back( |
| 263 internal::TaskGraph::Node(it->get(), 0u, tasks.size())); |
| 259 } | 264 } |
| 260 } | 265 } |
| 261 | 266 |
| 262 size_t CollectCompletedTasks() { | 267 size_t CollectCompletedTasks(internal::Task::Vector* completed_tasks) { |
| 263 internal::Task::Vector completed_tasks; | 268 DCHECK(completed_tasks->empty()); |
| 264 task_graph_runner_->CollectCompletedTasks(namespace_token_, | 269 task_graph_runner_->CollectCompletedTasks(namespace_token_, |
| 265 &completed_tasks); | 270 completed_tasks); |
| 266 return completed_tasks.size(); | 271 return completed_tasks->size(); |
| 267 } | 272 } |
| 268 | 273 |
| 269 scoped_ptr<internal::TaskGraphRunner> task_graph_runner_; | 274 scoped_ptr<internal::TaskGraphRunner> task_graph_runner_; |
| 270 internal::NamespaceToken namespace_token_; | 275 internal::NamespaceToken namespace_token_; |
| 271 LapTimer timer_; | 276 LapTimer timer_; |
| 272 }; | 277 }; |
| 273 | 278 |
| 274 TEST_F(TaskGraphRunnerPerfTest, BuildTaskGraph) { | 279 TEST_F(TaskGraphRunnerPerfTest, BuildTaskGraph) { |
| 275 RunBuildTaskGraphTest("0_1_0", 0, 1, 0); | 280 RunBuildTaskGraphTest("0_1_0", 0, 1, 0); |
| 276 RunBuildTaskGraphTest("0_32_0", 0, 32, 0); | 281 RunBuildTaskGraphTest("0_32_0", 0, 32, 0); |
| (...skipping 25 matching lines...) Expand all Loading... |
| 302 RunScheduleAndExecuteTasksTest("0_1_0", 0, 1, 0); | 307 RunScheduleAndExecuteTasksTest("0_1_0", 0, 1, 0); |
| 303 RunScheduleAndExecuteTasksTest("0_32_0", 0, 32, 0); | 308 RunScheduleAndExecuteTasksTest("0_32_0", 0, 32, 0); |
| 304 RunScheduleAndExecuteTasksTest("2_1_0", 2, 1, 0); | 309 RunScheduleAndExecuteTasksTest("2_1_0", 2, 1, 0); |
| 305 RunScheduleAndExecuteTasksTest("2_32_0", 2, 32, 0); | 310 RunScheduleAndExecuteTasksTest("2_32_0", 2, 32, 0); |
| 306 RunScheduleAndExecuteTasksTest("2_1_1", 2, 1, 1); | 311 RunScheduleAndExecuteTasksTest("2_1_1", 2, 1, 1); |
| 307 RunScheduleAndExecuteTasksTest("2_32_1", 2, 32, 1); | 312 RunScheduleAndExecuteTasksTest("2_32_1", 2, 32, 1); |
| 308 } | 313 } |
| 309 | 314 |
| 310 } // namespace | 315 } // namespace |
| 311 } // namespace cc | 316 } // namespace cc |
| OLD | NEW |