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

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

Issue 1449133002: TaskGraphRunner refactor (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: feedback 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_runner_perftest.cc ('k') | cc/raster/task_graph_work_queue.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "cc/raster/task_graph_runner.h"
6
7 #include <deque>
8 #include <vector>
9
10 #include "base/bind.h"
11 #include "base/synchronization/lock.h"
12 #include "base/threading/simple_thread.h"
13 #include "cc/base/container_util.h"
14 #include "testing/gtest/include/gtest/gtest.h"
15
16 namespace cc {
17 namespace {
18
19 const int kNamespaceCount = 3;
20
21 class TaskGraphRunnerTestBase {
22 public:
23 struct TaskInfo {
24 TaskInfo(int namespace_index,
25 unsigned id,
26 unsigned dependent_id,
27 unsigned dependent_count,
28 unsigned priority)
29 : namespace_index(namespace_index),
30 id(id),
31 dependent_id(dependent_id),
32 dependent_count(dependent_count),
33 priority(priority) {}
34
35 int namespace_index;
36 unsigned id;
37 unsigned dependent_id;
38 unsigned dependent_count;
39 unsigned priority;
40 };
41
42 TaskGraphRunnerTestBase() : task_graph_runner_(new TaskGraphRunner) {}
43
44 void ResetIds(int namespace_index) {
45 run_task_ids_[namespace_index].clear();
46 on_task_completed_ids_[namespace_index].clear();
47 }
48
49 void RunAllTasks(int namespace_index) {
50 task_graph_runner_->WaitForTasksToFinishRunning(
51 namespace_token_[namespace_index]);
52
53 Task::Vector completed_tasks;
54 task_graph_runner_->CollectCompletedTasks(namespace_token_[namespace_index],
55 &completed_tasks);
56 for (Task::Vector::const_iterator it = completed_tasks.begin();
57 it != completed_tasks.end();
58 ++it) {
59 FakeTaskImpl* task = static_cast<FakeTaskImpl*>(it->get());
60 task->CompleteOnOriginThread();
61 }
62 }
63
64 void RunTaskOnWorkerThread(int namespace_index, unsigned id) {
65 base::AutoLock lock(run_task_ids_lock_);
66 run_task_ids_[namespace_index].push_back(id);
67 }
68
69 void OnTaskCompleted(int namespace_index, unsigned id) {
70 on_task_completed_ids_[namespace_index].push_back(id);
71 }
72
73 const std::vector<unsigned>& run_task_ids(int namespace_index) {
74 return run_task_ids_[namespace_index];
75 }
76
77 const std::vector<unsigned>& on_task_completed_ids(int namespace_index) {
78 return on_task_completed_ids_[namespace_index];
79 }
80
81 void ScheduleTasks(int namespace_index, const std::vector<TaskInfo>& tasks) {
82 Task::Vector new_tasks;
83 Task::Vector new_dependents;
84 TaskGraph new_graph;
85
86 for (std::vector<TaskInfo>::const_iterator it = tasks.begin();
87 it != tasks.end();
88 ++it) {
89 scoped_refptr<FakeTaskImpl> new_task(
90 new FakeTaskImpl(this, it->namespace_index, it->id));
91 new_graph.nodes.push_back(
92 TaskGraph::Node(new_task.get(), it->priority, 0u));
93 for (unsigned i = 0; i < it->dependent_count; ++i) {
94 scoped_refptr<FakeDependentTaskImpl> new_dependent_task(
95 new FakeDependentTaskImpl(
96 this, it->namespace_index, it->dependent_id));
97 new_graph.nodes.push_back(
98 TaskGraph::Node(new_dependent_task.get(), it->priority, 1u));
99 new_graph.edges.push_back(
100 TaskGraph::Edge(new_task.get(), new_dependent_task.get()));
101
102 new_dependents.push_back(new_dependent_task.get());
103 }
104
105 new_tasks.push_back(new_task.get());
106 }
107
108 task_graph_runner_->ScheduleTasks(namespace_token_[namespace_index],
109 &new_graph);
110
111 dependents_[namespace_index].swap(new_dependents);
112 tasks_[namespace_index].swap(new_tasks);
113 }
114
115 protected:
116 class FakeTaskImpl : public Task {
117 public:
118 FakeTaskImpl(TaskGraphRunnerTestBase* test, int namespace_index, int id)
119 : test_(test), namespace_index_(namespace_index), id_(id) {}
120
121 // Overridden from Task:
122 void RunOnWorkerThread() override {
123 test_->RunTaskOnWorkerThread(namespace_index_, id_);
124 }
125
126 virtual void CompleteOnOriginThread() {
127 test_->OnTaskCompleted(namespace_index_, id_);
128 }
129
130 protected:
131 ~FakeTaskImpl() override {}
132
133 private:
134 TaskGraphRunnerTestBase* test_;
135 int namespace_index_;
136 int id_;
137
138 DISALLOW_COPY_AND_ASSIGN(FakeTaskImpl);
139 };
140
141 class FakeDependentTaskImpl : public FakeTaskImpl {
142 public:
143 FakeDependentTaskImpl(TaskGraphRunnerTestBase* test,
144 int namespace_index,
145 int id)
146 : FakeTaskImpl(test, namespace_index, id) {}
147
148 // Overridden from FakeTaskImpl:
149 void CompleteOnOriginThread() override {}
150
151 private:
152 ~FakeDependentTaskImpl() override {}
153
154 DISALLOW_COPY_AND_ASSIGN(FakeDependentTaskImpl);
155 };
156
157 scoped_ptr<TaskGraphRunner> task_graph_runner_;
158 NamespaceToken namespace_token_[kNamespaceCount];
159 Task::Vector tasks_[kNamespaceCount];
160 Task::Vector dependents_[kNamespaceCount];
161 std::vector<unsigned> run_task_ids_[kNamespaceCount];
162 base::Lock run_task_ids_lock_;
163 std::vector<unsigned> on_task_completed_ids_[kNamespaceCount];
164 };
165
166 class TaskGraphRunnerTest : public TaskGraphRunnerTestBase,
167 public testing::TestWithParam<int>,
168 public base::DelegateSimpleThread::Delegate {
169 public:
170 // Overridden from testing::Test:
171 void SetUp() override {
172 const size_t num_threads = GetParam();
173 while (workers_.size() < num_threads) {
174 scoped_ptr<base::DelegateSimpleThread> worker =
175 make_scoped_ptr(new base::DelegateSimpleThread(this, "TestWorker"));
176 worker->Start();
177 workers_.push_back(std::move(worker));
178 }
179
180 for (int i = 0; i < kNamespaceCount; ++i)
181 namespace_token_[i] = task_graph_runner_->GetNamespaceToken();
182 }
183 void TearDown() override {
184 task_graph_runner_->Shutdown();
185 while (!workers_.empty()) {
186 scoped_ptr<base::DelegateSimpleThread> worker = PopFront(&workers_);
187 worker->Join();
188 }
189 }
190
191 private:
192 // Overridden from base::DelegateSimpleThread::Delegate:
193 void Run() override { task_graph_runner_->Run(); }
194
195 std::deque<scoped_ptr<base::DelegateSimpleThread>> workers_;
196 };
197
198 TEST_P(TaskGraphRunnerTest, Basic) {
199 for (int i = 0; i < kNamespaceCount; ++i) {
200 EXPECT_EQ(0u, run_task_ids(i).size());
201 EXPECT_EQ(0u, on_task_completed_ids(i).size());
202
203 ScheduleTasks(i, std::vector<TaskInfo>(1, TaskInfo(i, 0u, 0u, 0u, 0u)));
204 }
205
206 for (int i = 0; i < kNamespaceCount; ++i) {
207 RunAllTasks(i);
208
209 EXPECT_EQ(1u, run_task_ids(i).size());
210 EXPECT_EQ(1u, on_task_completed_ids(i).size());
211 }
212
213 for (int i = 0; i < kNamespaceCount; ++i)
214 ScheduleTasks(i, std::vector<TaskInfo>(1, TaskInfo(i, 0u, 0u, 1u, 0u)));
215
216 for (int i = 0; i < kNamespaceCount; ++i) {
217 RunAllTasks(i);
218
219 EXPECT_EQ(3u, run_task_ids(i).size());
220 EXPECT_EQ(2u, on_task_completed_ids(i).size());
221 }
222
223 for (int i = 0; i < kNamespaceCount; ++i)
224 ScheduleTasks(i, std::vector<TaskInfo>(1, TaskInfo(i, 0u, 0u, 2u, 0u)));
225
226 for (int i = 0; i < kNamespaceCount; ++i) {
227 RunAllTasks(i);
228
229 EXPECT_EQ(6u, run_task_ids(i).size());
230 EXPECT_EQ(3u, on_task_completed_ids(i).size());
231 }
232 }
233
234 TEST_P(TaskGraphRunnerTest, Dependencies) {
235 for (int i = 0; i < kNamespaceCount; ++i) {
236 ScheduleTasks(i,
237 std::vector<TaskInfo>(1,
238 TaskInfo(i,
239 0u,
240 1u,
241 1u, // 1 dependent
242 0u)));
243 }
244
245 for (int i = 0; i < kNamespaceCount; ++i) {
246 RunAllTasks(i);
247
248 // Check if task ran before dependent.
249 ASSERT_EQ(2u, run_task_ids(i).size());
250 EXPECT_EQ(0u, run_task_ids(i)[0]);
251 EXPECT_EQ(1u, run_task_ids(i)[1]);
252 ASSERT_EQ(1u, on_task_completed_ids(i).size());
253 EXPECT_EQ(0u, on_task_completed_ids(i)[0]);
254 }
255
256 for (int i = 0; i < kNamespaceCount; ++i) {
257 ScheduleTasks(i,
258 std::vector<TaskInfo>(1,
259 TaskInfo(i,
260 2u,
261 3u,
262 2u, // 2 dependents
263 0u)));
264 }
265
266 for (int i = 0; i < kNamespaceCount; ++i) {
267 RunAllTasks(i);
268
269 // Task should only run once.
270 ASSERT_EQ(5u, run_task_ids(i).size());
271 EXPECT_EQ(2u, run_task_ids(i)[2]);
272 EXPECT_EQ(3u, run_task_ids(i)[3]);
273 EXPECT_EQ(3u, run_task_ids(i)[4]);
274 ASSERT_EQ(2u, on_task_completed_ids(i).size());
275 EXPECT_EQ(2u, on_task_completed_ids(i)[1]);
276 }
277 }
278
279 INSTANTIATE_TEST_CASE_P(TaskGraphRunnerTests,
280 TaskGraphRunnerTest,
281 ::testing::Range(1, 5));
282
283 class TaskGraphRunnerSingleThreadTest
284 : public TaskGraphRunnerTestBase,
285 public testing::Test,
286 public base::DelegateSimpleThread::Delegate {
287 public:
288 // Overridden from testing::Test:
289 void SetUp() override {
290 worker_.reset(new base::DelegateSimpleThread(this, "TestWorker"));
291 worker_->Start();
292
293 for (int i = 0; i < kNamespaceCount; ++i)
294 namespace_token_[i] = task_graph_runner_->GetNamespaceToken();
295 }
296 void TearDown() override {
297 task_graph_runner_->Shutdown();
298 worker_->Join();
299 }
300
301 private:
302 // Overridden from base::DelegateSimpleThread::Delegate:
303 void Run() override { task_graph_runner_->Run(); }
304
305 scoped_ptr<base::DelegateSimpleThread> worker_;
306 };
307
308 TEST_F(TaskGraphRunnerSingleThreadTest, Priority) {
309 for (int i = 0; i < kNamespaceCount; ++i) {
310 TaskInfo tasks[] = {TaskInfo(i, 0u, 2u, 1u, 1u), // Priority 1
311 TaskInfo(i, 1u, 3u, 1u, 0u) // Priority 0
312 };
313 ScheduleTasks(i, std::vector<TaskInfo>(tasks, tasks + arraysize(tasks)));
314 }
315
316 for (int i = 0; i < kNamespaceCount; ++i) {
317 RunAllTasks(i);
318
319 // Check if tasks ran in order of priority.
320 ASSERT_EQ(4u, run_task_ids(i).size());
321 EXPECT_EQ(1u, run_task_ids(i)[0]);
322 EXPECT_EQ(3u, run_task_ids(i)[1]);
323 EXPECT_EQ(0u, run_task_ids(i)[2]);
324 EXPECT_EQ(2u, run_task_ids(i)[3]);
325 ASSERT_EQ(2u, on_task_completed_ids(i).size());
326 EXPECT_EQ(1u, on_task_completed_ids(i)[0]);
327 EXPECT_EQ(0u, on_task_completed_ids(i)[1]);
328 }
329 }
330
331 } // namespace
332 } // namespace cc
OLDNEW
« no previous file with comments | « cc/raster/task_graph_runner_perftest.cc ('k') | cc/raster/task_graph_work_queue.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698