Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(509)

Side by Side Diff: cc/raster/task_graph_work_queue.cc

Issue 1521423003: Revert of TaskGraphRunner Group support (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@refactor
Patch Set: Created 5 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « cc/raster/task_graph_work_queue.h ('k') | cc/raster/tile_task_worker_pool_perftest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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/raster/task_graph_work_queue.h" 5 #include "cc/raster/task_graph_work_queue.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <map>
9 #include <utility> 8 #include <utility>
10 9
11 #include "base/trace_event/trace_event.h" 10 #include "base/trace_event/trace_event.h"
12 11
13 namespace cc { 12 namespace cc {
14 namespace {
15
16 bool CompareTaskPriority(const TaskGraphWorkQueue::PrioritizedTask& a,
17 const TaskGraphWorkQueue::PrioritizedTask& b) {
18 // In this system, numerically lower priority is run first.
19 return a.priority > b.priority;
20 }
21
22 class CompareTaskNamespacePriority {
23 public:
24 explicit CompareTaskNamespacePriority(uint16_t category)
25 : category_(category) {}
26
27 bool operator()(const TaskGraphWorkQueue::TaskNamespace* a,
28 const TaskGraphWorkQueue::TaskNamespace* b) {
29 DCHECK(!a->ready_to_run_tasks.at(category_).empty());
30 DCHECK(!b->ready_to_run_tasks.at(category_).empty());
31
32 // Compare based on task priority of the ready_to_run_tasks heap .front()
33 // will hold the max element of the heap, except after pop_heap, when max
34 // element is moved to .back().
35 return CompareTaskPriority(a->ready_to_run_tasks.at(category_).front(),
36 b->ready_to_run_tasks.at(category_).front());
37 }
38
39 private:
40 uint16_t category_;
41 };
42 } // namespace
43 13
44 TaskGraphWorkQueue::TaskNamespace::TaskNamespace() {} 14 TaskGraphWorkQueue::TaskNamespace::TaskNamespace() {}
45 15
46 TaskGraphWorkQueue::TaskNamespace::~TaskNamespace() {} 16 TaskGraphWorkQueue::TaskNamespace::~TaskNamespace() {}
47 17
48 TaskGraphWorkQueue::TaskGraphWorkQueue() : next_namespace_id_(1) {} 18 TaskGraphWorkQueue::TaskGraphWorkQueue() : next_namespace_id_(1) {}
49 TaskGraphWorkQueue::~TaskGraphWorkQueue() {} 19 TaskGraphWorkQueue::~TaskGraphWorkQueue() {}
50 20
51 NamespaceToken TaskGraphWorkQueue::GetNamespaceToken() { 21 NamespaceToken TaskGraphWorkQueue::GetNamespaceToken() {
52 NamespaceToken token(next_namespace_id_++); 22 NamespaceToken token(next_namespace_id_++);
53 DCHECK(namespaces_.find(token) == namespaces_.end()); 23 DCHECK(namespaces_.find(token) == namespaces_.end());
54 return token; 24 return token;
55 } 25 }
56 26
57 void TaskGraphWorkQueue::ScheduleTasks(NamespaceToken token, TaskGraph* graph) { 27 void TaskGraphWorkQueue::ScheduleTasks(NamespaceToken token, TaskGraph* graph) {
58 TaskNamespace& task_namespace = namespaces_[token]; 28 TaskNamespace& task_namespace = namespaces_[token];
59 29
60 // First adjust number of dependencies to reflect completed tasks. 30 // First adjust number of dependencies to reflect completed tasks.
61 for (const scoped_refptr<Task>& task : task_namespace.completed_tasks) { 31 for (const scoped_refptr<Task>& task : task_namespace.completed_tasks) {
62 for (DependentIterator node_it(graph, task.get()); node_it; ++node_it) { 32 for (DependentIterator node_it(graph, task.get()); node_it; ++node_it) {
63 TaskGraph::Node& node = *node_it; 33 TaskGraph::Node& node = *node_it;
64 DCHECK_LT(0u, node.dependencies); 34 DCHECK_LT(0u, node.dependencies);
65 node.dependencies--; 35 node.dependencies--;
66 } 36 }
67 } 37 }
68 38
69 // Build new "ready to run" queue and remove nodes from old graph. 39 // Build new "ready to run" queue and remove nodes from old graph.
70 for (auto& ready_to_run_tasks_it : task_namespace.ready_to_run_tasks) { 40 task_namespace.ready_to_run_tasks.clear();
71 ready_to_run_tasks_it.second.clear();
72 }
73 for (const TaskGraph::Node& node : graph->nodes) { 41 for (const TaskGraph::Node& node : graph->nodes) {
74 // Remove any old nodes that are associated with this task. The result is 42 // Remove any old nodes that are associated with this task. The result is
75 // that the old graph is left with all nodes not present in this graph, 43 // that the old graph is left with all nodes not present in this graph,
76 // which we use below to determine what tasks need to be canceled. 44 // which we use below to determine what tasks need to be canceled.
77 TaskGraph::Node::Vector::iterator old_it = std::find_if( 45 TaskGraph::Node::Vector::iterator old_it = std::find_if(
78 task_namespace.graph.nodes.begin(), task_namespace.graph.nodes.end(), 46 task_namespace.graph.nodes.begin(), task_namespace.graph.nodes.end(),
79 [node](const TaskGraph::Node& other) { 47 [node](const TaskGraph::Node& other) {
80 return node.task == other.task; 48 return node.task == other.task;
81 }); 49 });
82 if (old_it != task_namespace.graph.nodes.end()) { 50 if (old_it != task_namespace.graph.nodes.end()) {
83 std::swap(*old_it, task_namespace.graph.nodes.back()); 51 std::swap(*old_it, task_namespace.graph.nodes.back());
84 task_namespace.graph.nodes.pop_back(); 52 task_namespace.graph.nodes.pop_back();
85 } 53 }
86 54
87 // Task is not ready to run if dependencies are not yet satisfied. 55 // Task is not ready to run if dependencies are not yet satisfied.
88 if (node.dependencies) 56 if (node.dependencies)
89 continue; 57 continue;
90 58
91 // Skip if already finished running task. 59 // Skip if already finished running task.
92 if (node.task->HasFinishedRunning()) 60 if (node.task->HasFinishedRunning())
93 continue; 61 continue;
94 62
95 // Skip if already running. 63 // Skip if already running.
96 if (std::find(task_namespace.running_tasks.begin(), 64 if (std::find(task_namespace.running_tasks.begin(),
97 task_namespace.running_tasks.end(), 65 task_namespace.running_tasks.end(),
98 node.task) != task_namespace.running_tasks.end()) 66 node.task) != task_namespace.running_tasks.end())
99 continue; 67 continue;
100 68
101 task_namespace.ready_to_run_tasks[node.category].push_back(PrioritizedTask( 69 task_namespace.ready_to_run_tasks.push_back(
102 node.task, &task_namespace, node.category, node.priority)); 70 PrioritizedTask(node.task, &task_namespace, node.priority));
103 } 71 }
104 72
105 // Rearrange the elements in each vector within |ready_to_run_tasks| in such a 73 // Rearrange the elements in |ready_to_run_tasks| in such a way that they
106 // way that they form a heap. 74 // form a heap.
107 for (auto& it : task_namespace.ready_to_run_tasks) { 75 std::make_heap(task_namespace.ready_to_run_tasks.begin(),
108 auto& ready_to_run_tasks = it.second; 76 task_namespace.ready_to_run_tasks.end(), CompareTaskPriority);
109 std::make_heap(ready_to_run_tasks.begin(), ready_to_run_tasks.end(),
110 CompareTaskPriority);
111 }
112 77
113 // Swap task graph. 78 // Swap task graph.
114 task_namespace.graph.Swap(graph); 79 task_namespace.graph.Swap(graph);
115 80
116 // Determine what tasks in old graph need to be canceled. 81 // Determine what tasks in old graph need to be canceled.
117 for (TaskGraph::Node::Vector::iterator it = graph->nodes.begin(); 82 for (TaskGraph::Node::Vector::iterator it = graph->nodes.begin();
118 it != graph->nodes.end(); ++it) { 83 it != graph->nodes.end(); ++it) {
119 TaskGraph::Node& node = *it; 84 TaskGraph::Node& node = *it;
120 85
121 // Skip if already finished running task. 86 // Skip if already finished running task.
122 if (node.task->HasFinishedRunning()) 87 if (node.task->HasFinishedRunning())
123 continue; 88 continue;
124 89
125 // Skip if already running. 90 // Skip if already running.
126 if (std::find(task_namespace.running_tasks.begin(), 91 if (std::find(task_namespace.running_tasks.begin(),
127 task_namespace.running_tasks.end(), 92 task_namespace.running_tasks.end(),
128 node.task) != task_namespace.running_tasks.end()) 93 node.task) != task_namespace.running_tasks.end())
129 continue; 94 continue;
130 95
131 DCHECK(std::find(task_namespace.completed_tasks.begin(), 96 DCHECK(std::find(task_namespace.completed_tasks.begin(),
132 task_namespace.completed_tasks.end(), 97 task_namespace.completed_tasks.end(),
133 node.task) == task_namespace.completed_tasks.end()); 98 node.task) == task_namespace.completed_tasks.end());
134 task_namespace.completed_tasks.push_back(node.task); 99 task_namespace.completed_tasks.push_back(node.task);
135 } 100 }
136 101
137 // Build new "ready to run" task namespaces queue. 102 // Build new "ready to run" task namespaces queue.
138 for (auto& ready_to_run_namespaces_it : ready_to_run_namespaces_) { 103 ready_to_run_namespaces_.clear();
139 ready_to_run_namespaces_it.second.clear(); 104 for (auto& it : namespaces_) {
140 } 105 if (!it.second.ready_to_run_tasks.empty())
141 for (auto& namespace_it : namespaces_) { 106 ready_to_run_namespaces_.push_back(&it.second);
142 auto& task_namespace = namespace_it.second;
143 for (auto& ready_to_run_tasks_it : task_namespace.ready_to_run_tasks) {
144 auto& ready_to_run_tasks = ready_to_run_tasks_it.second;
145 uint16_t category = ready_to_run_tasks_it.first;
146 if (!ready_to_run_tasks.empty()) {
147 ready_to_run_namespaces_[category].push_back(&task_namespace);
148 }
149 }
150 } 107 }
151 108
152 // Rearrange the task namespaces in |ready_to_run_namespaces| in such a 109 // Rearrange the task namespaces in |ready_to_run_namespaces| in such a
153 // way that they form a heap. 110 // way that they form a heap.
154 for (auto& it : ready_to_run_namespaces_) { 111 std::make_heap(ready_to_run_namespaces_.begin(),
155 uint16_t category = it.first; 112 ready_to_run_namespaces_.end(), CompareTaskNamespacePriority);
156 auto& task_namespace = it.second;
157 std::make_heap(task_namespace.begin(), task_namespace.end(),
158 CompareTaskNamespacePriority(category));
159 }
160 } 113 }
161 114
162 TaskGraphWorkQueue::PrioritizedTask TaskGraphWorkQueue::GetNextTaskToRun( 115 TaskGraphWorkQueue::PrioritizedTask TaskGraphWorkQueue::GetNextTaskToRun() {
163 uint16_t category) { 116 DCHECK(!ready_to_run_namespaces_.empty());
164 TaskNamespace::Vector& ready_to_run_namespaces =
165 ready_to_run_namespaces_[category];
166 DCHECK(!ready_to_run_namespaces.empty());
167 117
168 // Take top priority TaskNamespace from |ready_to_run_namespaces|. 118 // Take top priority TaskNamespace from |ready_to_run_namespaces_|.
169 std::pop_heap(ready_to_run_namespaces.begin(), ready_to_run_namespaces.end(), 119 std::pop_heap(ready_to_run_namespaces_.begin(),
170 CompareTaskNamespacePriority(category)); 120 ready_to_run_namespaces_.end(), CompareTaskNamespacePriority);
171 TaskNamespace* task_namespace = ready_to_run_namespaces.back(); 121 TaskNamespace* task_namespace = ready_to_run_namespaces_.back();
172 ready_to_run_namespaces.pop_back(); 122 ready_to_run_namespaces_.pop_back();
173 123 DCHECK(!task_namespace->ready_to_run_tasks.empty());
174 PrioritizedTask::Vector& ready_to_run_tasks =
175 task_namespace->ready_to_run_tasks[category];
176 DCHECK(!ready_to_run_tasks.empty());
177 124
178 // Take top priority task from |ready_to_run_tasks|. 125 // Take top priority task from |ready_to_run_tasks|.
179 std::pop_heap(ready_to_run_tasks.begin(), ready_to_run_tasks.end(), 126 std::pop_heap(task_namespace->ready_to_run_tasks.begin(),
180 CompareTaskPriority); 127 task_namespace->ready_to_run_tasks.end(), CompareTaskPriority);
181 PrioritizedTask task = ready_to_run_tasks.back(); 128 PrioritizedTask task = task_namespace->ready_to_run_tasks.back();
182 ready_to_run_tasks.pop_back(); 129 task_namespace->ready_to_run_tasks.pop_back();
183 130
184 // Add task namespace back to |ready_to_run_namespaces| if not empty after 131 // Add task namespace back to |ready_to_run_namespaces_| if not empty after
185 // taking top priority task. 132 // taking top priority task.
186 if (!ready_to_run_tasks.empty()) { 133 if (!task_namespace->ready_to_run_tasks.empty()) {
187 ready_to_run_namespaces.push_back(task_namespace); 134 ready_to_run_namespaces_.push_back(task_namespace);
188 std::push_heap(ready_to_run_namespaces.begin(), 135 std::push_heap(ready_to_run_namespaces_.begin(),
189 ready_to_run_namespaces.end(), 136 ready_to_run_namespaces_.end(),
190 CompareTaskNamespacePriority(category)); 137 CompareTaskNamespacePriority);
191 } 138 }
192 139
193 // Add task to |running_tasks|. 140 // Add task to |running_tasks|.
194 task_namespace->running_tasks.push_back(task.task); 141 task_namespace->running_tasks.push_back(task.task);
195 142
196 return task; 143 return task;
197 } 144 }
198 145
199 void TaskGraphWorkQueue::CompleteTask(const PrioritizedTask& completed_task) { 146 void TaskGraphWorkQueue::CompleteTask(const PrioritizedTask& completed_task) {
200 TaskNamespace* task_namespace = completed_task.task_namespace; 147 TaskNamespace* task_namespace = completed_task.task_namespace;
201 scoped_refptr<Task> task(completed_task.task); 148 scoped_refptr<Task> task(completed_task.task);
202 149
203 // Remove task from |running_tasks|. 150 // Remove task from |running_tasks|.
204 auto it = std::find(task_namespace->running_tasks.begin(), 151 auto it = std::find(task_namespace->running_tasks.begin(),
205 task_namespace->running_tasks.end(), task); 152 task_namespace->running_tasks.end(), task);
206 DCHECK(it != task_namespace->running_tasks.end()); 153 DCHECK(it != task_namespace->running_tasks.end());
207 std::swap(*it, task_namespace->running_tasks.back()); 154 std::swap(*it, task_namespace->running_tasks.back());
208 task_namespace->running_tasks.pop_back(); 155 task_namespace->running_tasks.pop_back();
209 156
210 // Now iterate over all dependents to decrement dependencies and check if they 157 // Now iterate over all dependents to decrement dependencies and check if they
211 // are ready to run. 158 // are ready to run.
212 bool ready_to_run_namespaces_has_heap_properties = true; 159 bool ready_to_run_namespaces_has_heap_properties = true;
213 for (DependentIterator it(&task_namespace->graph, task.get()); it; ++it) { 160 for (DependentIterator it(&task_namespace->graph, task.get()); it; ++it) {
214 TaskGraph::Node& dependent_node = *it; 161 TaskGraph::Node& dependent_node = *it;
215 162
216 DCHECK_LT(0u, dependent_node.dependencies); 163 DCHECK_LT(0u, dependent_node.dependencies);
217 dependent_node.dependencies--; 164 dependent_node.dependencies--;
218 // Task is ready if it has no dependencies. Add it to |ready_to_run_tasks_|. 165 // Task is ready if it has no dependencies. Add it to |ready_to_run_tasks_|.
219 if (!dependent_node.dependencies) { 166 if (!dependent_node.dependencies) {
220 PrioritizedTask::Vector& ready_to_run_tasks = 167 bool was_empty = task_namespace->ready_to_run_tasks.empty();
221 task_namespace->ready_to_run_tasks[dependent_node.category]; 168 task_namespace->ready_to_run_tasks.push_back(PrioritizedTask(
222 169 dependent_node.task, task_namespace, dependent_node.priority));
223 bool was_empty = ready_to_run_tasks.empty(); 170 std::push_heap(task_namespace->ready_to_run_tasks.begin(),
224 ready_to_run_tasks.push_back( 171 task_namespace->ready_to_run_tasks.end(),
225 PrioritizedTask(dependent_node.task, task_namespace,
226 dependent_node.category, dependent_node.priority));
227 std::push_heap(ready_to_run_tasks.begin(), ready_to_run_tasks.end(),
228 CompareTaskPriority); 172 CompareTaskPriority);
229
230 // Task namespace is ready if it has at least one ready to run task. Add 173 // Task namespace is ready if it has at least one ready to run task. Add
231 // it to |ready_to_run_namespaces_| if it just become ready. 174 // it to |ready_to_run_namespaces_| if it just become ready.
232 if (was_empty) { 175 if (was_empty) {
233 TaskNamespace::Vector& ready_to_run_namespaces = 176 DCHECK(std::find(ready_to_run_namespaces_.begin(),
234 ready_to_run_namespaces_[dependent_node.category]; 177 ready_to_run_namespaces_.end(),
235 178 task_namespace) == ready_to_run_namespaces_.end());
236 DCHECK(std::find(ready_to_run_namespaces.begin(), 179 ready_to_run_namespaces_.push_back(task_namespace);
237 ready_to_run_namespaces.end(),
238 task_namespace) == ready_to_run_namespaces.end());
239 ready_to_run_namespaces.push_back(task_namespace);
240 } 180 }
241 ready_to_run_namespaces_has_heap_properties = false; 181 ready_to_run_namespaces_has_heap_properties = false;
242 } 182 }
243 } 183 }
244 184
245 // Rearrange the task namespaces in |ready_to_run_namespaces_| in such a way 185 // Rearrange the task namespaces in |ready_to_run_namespaces_| in such a way
246 // that they yet again form a heap. 186 // that they yet again form a heap.
247 if (!ready_to_run_namespaces_has_heap_properties) { 187 if (!ready_to_run_namespaces_has_heap_properties) {
248 for (auto& it : ready_to_run_namespaces_) { 188 std::make_heap(ready_to_run_namespaces_.begin(),
249 uint16_t category = it.first; 189 ready_to_run_namespaces_.end(),
250 auto& ready_to_run_namespaces = it.second; 190 CompareTaskNamespacePriority);
251 std::make_heap(ready_to_run_namespaces.begin(),
252 ready_to_run_namespaces.end(),
253 CompareTaskNamespacePriority(category));
254 }
255 } 191 }
256 192
257 // Finally add task to |completed_tasks_|. 193 // Finally add task to |completed_tasks_|.
258 task_namespace->completed_tasks.push_back(task); 194 task_namespace->completed_tasks.push_back(task);
259 } 195 }
260 196
261 void TaskGraphWorkQueue::CollectCompletedTasks(NamespaceToken token, 197 void TaskGraphWorkQueue::CollectCompletedTasks(NamespaceToken token,
262 Task::Vector* completed_tasks) { 198 Task::Vector* completed_tasks) {
263 TaskNamespaceMap::iterator it = namespaces_.find(token); 199 TaskNamespaceMap::iterator it = namespaces_.find(token);
264 if (it == namespaces_.end()) 200 if (it == namespaces_.end())
265 return; 201 return;
266 202
267 TaskNamespace& task_namespace = it->second; 203 TaskNamespace& task_namespace = it->second;
268 204
269 DCHECK_EQ(0u, completed_tasks->size()); 205 DCHECK_EQ(0u, completed_tasks->size());
270 completed_tasks->swap(task_namespace.completed_tasks); 206 completed_tasks->swap(task_namespace.completed_tasks);
271 if (!HasFinishedRunningTasksInNamespace(&task_namespace)) 207 if (!HasFinishedRunningTasksInNamespace(&task_namespace))
272 return; 208 return;
273 209
274 // Remove namespace if finished running tasks. 210 // Remove namespace if finished running tasks.
275 DCHECK_EQ(0u, task_namespace.completed_tasks.size()); 211 DCHECK_EQ(0u, task_namespace.completed_tasks.size());
276 DCHECK(!HasReadyToRunTasksInNamespace(&task_namespace)); 212 DCHECK_EQ(0u, task_namespace.ready_to_run_tasks.size());
277 DCHECK_EQ(0u, task_namespace.running_tasks.size()); 213 DCHECK_EQ(0u, task_namespace.running_tasks.size());
278 namespaces_.erase(it); 214 namespaces_.erase(it);
279 } 215 }
280 216
281 bool TaskGraphWorkQueue::DependencyMismatch(const TaskGraph* graph) { 217 bool TaskGraphWorkQueue::DependencyMismatch(const TaskGraph* graph) {
282 // Value storage will be 0-initialized. 218 // Value storage will be 0-initialized.
283 base::hash_map<const Task*, size_t> dependents; 219 base::hash_map<const Task*, size_t> dependents;
284 for (const TaskGraph::Edge& edge : graph->edges) 220 for (const TaskGraph::Edge& edge : graph->edges)
285 dependents[edge.dependent]++; 221 dependents[edge.dependent]++;
286 222
287 for (const TaskGraph::Node& node : graph->nodes) { 223 for (const TaskGraph::Node& node : graph->nodes) {
288 if (dependents[node.task] != node.dependencies) 224 if (dependents[node.task] != node.dependencies)
289 return true; 225 return true;
290 } 226 }
291 227
292 return false; 228 return false;
293 } 229 }
294 230
295 } // namespace cc 231 } // namespace cc
OLDNEW
« no previous file with comments | « cc/raster/task_graph_work_queue.h ('k') | cc/raster/tile_task_worker_pool_perftest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698