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 |