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

Unified Diff: cc/raster/task_graph_work_queue.cc

Issue 1489233003: TaskGraphRunner Group support (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@refactor
Patch Set: rebase 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 side-by-side diff with in-line comments
Download patch
Index: cc/raster/task_graph_work_queue.cc
diff --git a/cc/raster/task_graph_work_queue.cc b/cc/raster/task_graph_work_queue.cc
index 655a005b024804117fc9052a16ca20dd523868ca..dec9a4490c2eb6a429d07b3efa20b31514fc4db6 100644
--- a/cc/raster/task_graph_work_queue.cc
+++ b/cc/raster/task_graph_work_queue.cc
@@ -10,6 +10,52 @@
#include "base/trace_event/trace_event.h"
namespace cc {
+namespace {
+
+template <typename T>
+void ClearAllVectors(T* array_of_vectors) {
reveman 2015/12/04 02:30:53 nit: remove vector specific references as T can be
ericrk 2015/12/04 19:14:31 no longer needed when using map - but good point.
+ for (auto& vector : *array_of_vectors) {
+ vector.clear();
+ }
+}
+
+// Helper which checks if all sub arrays of a group are empty.
+template <typename T>
+bool AllVectorsEmpty(const T& array_of_vectors) {
reveman 2015/12/04 02:30:54 ditto. maybe std::for_each and std::find_if with
ericrk 2015/12/04 19:14:31 Acknowledged.
+ for (const auto& vector : array_of_vectors) {
+ if (!vector.empty())
+ return false;
+ }
+ return true;
+}
+
+bool CompareTaskPriority(const TaskGraphWorkQueue::PrioritizedTask& a,
+ const TaskGraphWorkQueue::PrioritizedTask& b) {
+ // In this system, numerically lower priority is run first.
+ return a.priority > b.priority;
+}
+
+class CompareTaskNamespacePriority {
reveman 2015/12/04 02:30:54 nit: this code predates c++11 support in chromium.
ericrk 2015/12/04 19:14:30 Using a lambda directly is a lot more verbose at t
reveman 2015/12/04 20:55:50 I think this would be OK with auto for arguments b
+ public:
+ explicit CompareTaskNamespacePriority(uint16_t group) : group_(group) {}
+
+ bool operator()(const TaskGraphWorkQueue::TaskNamespace* a,
+ const TaskGraphWorkQueue::TaskNamespace* b) {
+ DCHECK(group_ < TaskGraphWorkQueue::kMaxTaskGroups);
+ DCHECK(!a->ready_to_run_tasks[group_].empty());
+ DCHECK(!b->ready_to_run_tasks[group_].empty());
+
+ // Compare based on task priority of the ready_to_run_tasks heap .front()
+ // will hold the max element of the heap, except after pop_heap, when max
+ // element is moved to .back().
+ return CompareTaskPriority(a->ready_to_run_tasks[group_].front(),
+ b->ready_to_run_tasks[group_].front());
+ }
+
+ private:
+ uint16_t group_;
+};
+} // namespace
TaskGraphWorkQueue::TaskNamespace::TaskNamespace() {}
@@ -25,6 +71,8 @@ NamespaceToken TaskGraphWorkQueue::GetNamespaceToken() {
}
void TaskGraphWorkQueue::ScheduleTasks(NamespaceToken token, TaskGraph* graph) {
+ DCHECK(ValidateGroups(graph));
+
TaskNamespace& task_namespace = namespaces_[token];
// First adjust number of dependencies to reflect completed tasks.
@@ -37,7 +85,7 @@ void TaskGraphWorkQueue::ScheduleTasks(NamespaceToken token, TaskGraph* graph) {
}
// Build new "ready to run" queue and remove nodes from old graph.
- task_namespace.ready_to_run_tasks.clear();
+ ClearAllVectors(&task_namespace.ready_to_run_tasks);
for (const TaskGraph::Node& node : graph->nodes) {
// Remove any old nodes that are associated with this task. The result is
// that the old graph is left with all nodes not present in this graph,
@@ -66,14 +114,15 @@ void TaskGraphWorkQueue::ScheduleTasks(NamespaceToken token, TaskGraph* graph) {
node.task) != task_namespace.running_tasks.end())
continue;
- task_namespace.ready_to_run_tasks.push_back(
- PrioritizedTask(node.task, &task_namespace, node.priority));
+ task_namespace.ready_to_run_tasks[node.group].push_back(
+ PrioritizedTask(node.task, &task_namespace, node.group, node.priority));
}
- // Rearrange the elements in |ready_to_run_tasks| in such a way that they
- // form a heap.
- std::make_heap(task_namespace.ready_to_run_tasks.begin(),
- task_namespace.ready_to_run_tasks.end(), CompareTaskPriority);
+ // Rearrange the elements in each vector within |ready_to_run_tasks| in such a
+ // way that they form a heap.
+ for (auto& vector : task_namespace.ready_to_run_tasks) {
reveman 2015/12/04 02:30:54 nit: s/vector/ready_to_run_tasks/ not a fan of nam
ericrk 2015/12/04 19:14:30 Done.
+ std::make_heap(vector.begin(), vector.end(), CompareTaskPriority);
+ }
// Swap task graph.
task_namespace.graph.Swap(graph);
@@ -100,41 +149,52 @@ void TaskGraphWorkQueue::ScheduleTasks(NamespaceToken token, TaskGraph* graph) {
}
// Build new "ready to run" task namespaces queue.
- ready_to_run_namespaces_.clear();
+ ClearAllVectors(&ready_to_run_namespaces_);
for (auto& it : namespaces_) {
reveman 2015/12/04 02:30:53 would be nice if this could be something like: fo
ericrk 2015/12/04 19:14:31 Couldn't do that before (when using an array), as
- if (!it.second.ready_to_run_tasks.empty())
- ready_to_run_namespaces_.push_back(&it.second);
+ for (uint16_t group = 0; group < kMaxTaskGroups; ++group) {
+ if (!it.second.ready_to_run_tasks[group].empty())
+ ready_to_run_namespaces_[group].push_back(&it.second);
+ }
}
// Rearrange the task namespaces in |ready_to_run_namespaces| in such a
// way that they form a heap.
- std::make_heap(ready_to_run_namespaces_.begin(),
- ready_to_run_namespaces_.end(), CompareTaskNamespacePriority);
+ for (uint16_t group = 0; group < kMaxTaskGroups; ++group) {
+ std::make_heap(ready_to_run_namespaces_[group].begin(),
+ ready_to_run_namespaces_[group].end(),
+ CompareTaskNamespacePriority(group));
+ }
}
-TaskGraphWorkQueue::PrioritizedTask TaskGraphWorkQueue::GetNextTaskToRun() {
- DCHECK(!ready_to_run_namespaces_.empty());
-
- // Take top priority TaskNamespace from |ready_to_run_namespaces_|.
- std::pop_heap(ready_to_run_namespaces_.begin(),
- ready_to_run_namespaces_.end(), CompareTaskNamespacePriority);
- TaskNamespace* task_namespace = ready_to_run_namespaces_.back();
- ready_to_run_namespaces_.pop_back();
- DCHECK(!task_namespace->ready_to_run_tasks.empty());
-
- // Take top priority task from |ready_to_run_tasks|.
- std::pop_heap(task_namespace->ready_to_run_tasks.begin(),
- task_namespace->ready_to_run_tasks.end(), CompareTaskPriority);
- PrioritizedTask task = task_namespace->ready_to_run_tasks.back();
- task_namespace->ready_to_run_tasks.pop_back();
-
- // Add task namespace back to |ready_to_run_namespaces_| if not empty after
+TaskGraphWorkQueue::PrioritizedTask
+TaskGraphWorkQueue::GetNextTaskToRunForGroup(uint16_t group) {
+ DCHECK(group < kMaxTaskGroups);
+
+ TaskNamespace::Vector& namespaces_for_group = ready_to_run_namespaces_[group];
reveman 2015/12/04 02:30:54 nit: s/namespaces_for_group/ready_to_run_namespace
ericrk 2015/12/04 19:14:31 Done.
+ DCHECK(!namespaces_for_group.empty());
+
+ // Take top priority TaskNamespace from |namespaces_for_group|.
+ std::pop_heap(namespaces_for_group.begin(), namespaces_for_group.end(),
+ CompareTaskNamespacePriority(group));
+ TaskNamespace* task_namespace = namespaces_for_group.back();
+ namespaces_for_group.pop_back();
+
+ PrioritizedTask::Vector& tasks_for_group =
reveman 2015/12/04 02:30:54 nit: s/tasks_for_group/ready_to_run_tasks_for_grou
ericrk 2015/12/04 19:14:30 Done.
+ task_namespace->ready_to_run_tasks[group];
+ DCHECK(!tasks_for_group.empty());
+
+ // Take top priority task from |tasks_for_group|.
+ std::pop_heap(tasks_for_group.begin(), tasks_for_group.end(),
+ CompareTaskPriority);
+ PrioritizedTask task = tasks_for_group.back();
+ tasks_for_group.pop_back();
+
+ // Add task namespace back to |namespaces_for_group| if not empty after
// taking top priority task.
- if (!task_namespace->ready_to_run_tasks.empty()) {
- ready_to_run_namespaces_.push_back(task_namespace);
- std::push_heap(ready_to_run_namespaces_.begin(),
- ready_to_run_namespaces_.end(),
- CompareTaskNamespacePriority);
+ if (!tasks_for_group.empty()) {
+ namespaces_for_group.push_back(task_namespace);
+ std::push_heap(namespaces_for_group.begin(), namespaces_for_group.end(),
+ CompareTaskNamespacePriority(group));
}
// Add task to |running_tasks|.
@@ -143,6 +203,18 @@ TaskGraphWorkQueue::PrioritizedTask TaskGraphWorkQueue::GetNextTaskToRun() {
return task;
}
+TaskGraphWorkQueue::PrioritizedTask TaskGraphWorkQueue::GetNextTaskToRun() {
+ for (uint16_t group = 0; group < kMaxTaskGroups; ++group) {
+ if (!ready_to_run_namespaces_[group].empty()) {
+ return GetNextTaskToRunForGroup(group);
+ }
+ }
+
+ // This function must only be called when there is at least one task to run.
+ NOTREACHED();
+ return GetNextTaskToRunForGroup(0);
+}
+
void TaskGraphWorkQueue::CompleteTask(const PrioritizedTask& completed_task) {
TaskNamespace* task_namespace = completed_task.task_namespace;
scoped_refptr<Task> task(completed_task.task);
@@ -164,19 +236,26 @@ void TaskGraphWorkQueue::CompleteTask(const PrioritizedTask& completed_task) {
dependent_node.dependencies--;
// Task is ready if it has no dependencies. Add it to |ready_to_run_tasks_|.
if (!dependent_node.dependencies) {
- bool was_empty = task_namespace->ready_to_run_tasks.empty();
- task_namespace->ready_to_run_tasks.push_back(PrioritizedTask(
- dependent_node.task, task_namespace, dependent_node.priority));
- std::push_heap(task_namespace->ready_to_run_tasks.begin(),
- task_namespace->ready_to_run_tasks.end(),
+ PrioritizedTask::Vector& tasks_for_group =
reveman 2015/12/04 02:30:53 nit: same as above, ready_to_run_tasks_for_group o
ericrk 2015/12/04 19:14:31 Done.
+ task_namespace->ready_to_run_tasks[dependent_node.group];
+
+ bool was_empty = tasks_for_group.empty();
+ tasks_for_group.push_back(
+ PrioritizedTask(dependent_node.task, task_namespace,
+ dependent_node.group, dependent_node.priority));
+ std::push_heap(tasks_for_group.begin(), tasks_for_group.end(),
CompareTaskPriority);
+
// Task namespace is ready if it has at least one ready to run task. Add
// it to |ready_to_run_namespaces_| if it just become ready.
if (was_empty) {
- DCHECK(std::find(ready_to_run_namespaces_.begin(),
- ready_to_run_namespaces_.end(),
- task_namespace) == ready_to_run_namespaces_.end());
- ready_to_run_namespaces_.push_back(task_namespace);
+ TaskNamespace::Vector& namespaces_for_group =
reveman 2015/12/04 02:30:53 ditto
ericrk 2015/12/04 19:14:31 Done.
+ ready_to_run_namespaces_[dependent_node.group];
+
+ DCHECK(std::find(namespaces_for_group.begin(),
+ namespaces_for_group.end(),
+ task_namespace) == namespaces_for_group.end());
+ namespaces_for_group.push_back(task_namespace);
}
ready_to_run_namespaces_has_heap_properties = false;
}
@@ -185,9 +264,11 @@ void TaskGraphWorkQueue::CompleteTask(const PrioritizedTask& completed_task) {
// Rearrange the task namespaces in |ready_to_run_namespaces_| in such a way
// that they yet again form a heap.
if (!ready_to_run_namespaces_has_heap_properties) {
- std::make_heap(ready_to_run_namespaces_.begin(),
- ready_to_run_namespaces_.end(),
- CompareTaskNamespacePriority);
+ for (uint16_t group = 0; group < kMaxTaskGroups; ++group) {
+ std::make_heap(ready_to_run_namespaces_[group].begin(),
+ ready_to_run_namespaces_[group].end(),
+ CompareTaskNamespacePriority(group));
+ }
}
// Finally add task to |completed_tasks_|.
@@ -209,11 +290,21 @@ void TaskGraphWorkQueue::CollectCompletedTasks(NamespaceToken token,
// Remove namespace if finished running tasks.
DCHECK_EQ(0u, task_namespace.completed_tasks.size());
- DCHECK_EQ(0u, task_namespace.ready_to_run_tasks.size());
+ DCHECK(AllVectorsEmpty(task_namespace.ready_to_run_tasks));
DCHECK_EQ(0u, task_namespace.running_tasks.size());
namespaces_.erase(it);
}
+bool TaskGraphWorkQueue::HasReadyToRunTasks() const {
+ return !AllVectorsEmpty(ready_to_run_namespaces_);
+}
+
+bool TaskGraphWorkQueue::HasFinishedRunningTasksInNamespace(
+ const TaskNamespace* task_namespace) {
+ return task_namespace->running_tasks.empty() &&
+ AllVectorsEmpty(task_namespace->ready_to_run_tasks);
+}
+
bool TaskGraphWorkQueue::DependencyMismatch(const TaskGraph* graph) {
// Value storage will be 0-initialized.
base::hash_map<const Task*, size_t> dependents;
@@ -228,4 +319,12 @@ bool TaskGraphWorkQueue::DependencyMismatch(const TaskGraph* graph) {
return false;
}
+bool TaskGraphWorkQueue::ValidateGroups(const TaskGraph* graph) {
+ for (const TaskGraph::Node& node : graph->nodes) {
+ if (node.group >= kMaxTaskGroups)
+ return false;
+ }
+ return true;
+}
+
} // namespace cc

Powered by Google App Engine
This is Rietveld 408576698