OLD | NEW |
| (Empty) |
1 // Copyright 2013 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/base/worker_pool.h" | |
6 | |
7 #include "base/time.h" | |
8 #include "cc/base/completion_event.h" | |
9 #include "testing/gtest/include/gtest/gtest.h" | |
10 | |
11 namespace cc { | |
12 | |
13 namespace { | |
14 | |
15 static const int kTimeLimitMillis = 2000; | |
16 static const int kWarmupRuns = 5; | |
17 static const int kTimeCheckInterval = 10; | |
18 | |
19 class PerfTaskImpl : public internal::WorkerPoolTask { | |
20 public: | |
21 explicit PerfTaskImpl(internal::WorkerPoolTask::TaskVector* dependencies) | |
22 : internal::WorkerPoolTask(dependencies) {} | |
23 | |
24 // Overridden from internal::WorkerPoolTask: | |
25 virtual void RunOnThread(unsigned thread_index) OVERRIDE {} | |
26 virtual void DispatchCompletionCallback() OVERRIDE {} | |
27 | |
28 private: | |
29 virtual ~PerfTaskImpl() {} | |
30 }; | |
31 | |
32 class PerfControlTaskImpl : public internal::WorkerPoolTask { | |
33 public: | |
34 explicit PerfControlTaskImpl( | |
35 internal::WorkerPoolTask::TaskVector* dependencies) | |
36 : internal::WorkerPoolTask(dependencies), | |
37 did_start_(new CompletionEvent), | |
38 can_finish_(new CompletionEvent) {} | |
39 | |
40 // Overridden from internal::WorkerPoolTask: | |
41 virtual void RunOnThread(unsigned thread_index) OVERRIDE { | |
42 did_start_->Signal(); | |
43 can_finish_->Wait(); | |
44 } | |
45 virtual void DispatchCompletionCallback() OVERRIDE {} | |
46 | |
47 void WaitForTaskToStartRunning() { | |
48 did_start_->Wait(); | |
49 } | |
50 | |
51 void AllowTaskToFinish() { | |
52 can_finish_->Signal(); | |
53 } | |
54 | |
55 private: | |
56 virtual ~PerfControlTaskImpl() {} | |
57 | |
58 scoped_ptr<CompletionEvent> did_start_; | |
59 scoped_ptr<CompletionEvent> can_finish_; | |
60 }; | |
61 | |
62 class PerfWorkerPool : public WorkerPool { | |
63 public: | |
64 PerfWorkerPool() : WorkerPool(1, base::TimeDelta::FromDays(1024), "test") {} | |
65 virtual ~PerfWorkerPool() {} | |
66 | |
67 static scoped_ptr<PerfWorkerPool> Create() { | |
68 return make_scoped_ptr(new PerfWorkerPool); | |
69 } | |
70 | |
71 void ScheduleTasks(internal::WorkerPoolTask* root) { | |
72 WorkerPool::ScheduleTasks(root); | |
73 } | |
74 }; | |
75 | |
76 class WorkerPoolPerfTest : public testing::Test, | |
77 public WorkerPoolClient { | |
78 public: | |
79 WorkerPoolPerfTest() : num_runs_(0) {} | |
80 | |
81 // Overridden from testing::Test: | |
82 virtual void SetUp() OVERRIDE { | |
83 worker_pool_ = PerfWorkerPool::Create(); | |
84 worker_pool_->SetClient(this); | |
85 } | |
86 virtual void TearDown() OVERRIDE { | |
87 worker_pool_->Shutdown(); | |
88 } | |
89 | |
90 // Overridden from WorkerPoolClient: | |
91 virtual void DidFinishDispatchingWorkerPoolCompletionCallbacks() OVERRIDE {} | |
92 | |
93 void EndTest() { | |
94 elapsed_ = base::TimeTicks::HighResNow() - start_time_; | |
95 } | |
96 | |
97 void AfterTest(const std::string test_name) { | |
98 // Format matches chrome/test/perf/perf_test.h:PrintResult | |
99 printf("*RESULT %s: %.2f runs/s\n", | |
100 test_name.c_str(), | |
101 num_runs_ / elapsed_.InSecondsF()); | |
102 } | |
103 | |
104 void BuildTaskGraph(internal::WorkerPoolTask::TaskVector* dependencies, | |
105 unsigned current_depth, | |
106 unsigned max_depth, | |
107 unsigned num_children_per_node) { | |
108 internal::WorkerPoolTask::TaskVector children; | |
109 if (current_depth < max_depth) { | |
110 for (unsigned i = 0; i < num_children_per_node; ++i) { | |
111 BuildTaskGraph(&children, | |
112 current_depth + 1, | |
113 max_depth, | |
114 num_children_per_node); | |
115 } | |
116 } else if (leaf_task_) { | |
117 children.push_back(leaf_task_); | |
118 } | |
119 dependencies->push_back(make_scoped_refptr(new PerfTaskImpl(&children))); | |
120 } | |
121 | |
122 bool DidRun() { | |
123 ++num_runs_; | |
124 if (num_runs_ == kWarmupRuns) | |
125 start_time_ = base::TimeTicks::HighResNow(); | |
126 | |
127 if (!start_time_.is_null() && (num_runs_ % kTimeCheckInterval) == 0) { | |
128 base::TimeDelta elapsed = base::TimeTicks::HighResNow() - start_time_; | |
129 if (elapsed >= base::TimeDelta::FromMilliseconds(kTimeLimitMillis)) { | |
130 elapsed_ = elapsed; | |
131 return false; | |
132 } | |
133 } | |
134 | |
135 return true; | |
136 } | |
137 | |
138 void RunBuildTaskGraphTest(const std::string test_name, | |
139 unsigned max_depth, | |
140 unsigned num_children_per_node) { | |
141 start_time_ = base::TimeTicks(); | |
142 num_runs_ = 0; | |
143 do { | |
144 internal::WorkerPoolTask::TaskVector children; | |
145 BuildTaskGraph(&children, 0, max_depth, num_children_per_node); | |
146 } while (DidRun()); | |
147 | |
148 AfterTest(test_name); | |
149 } | |
150 | |
151 void RunScheduleTasksTest(const std::string test_name, | |
152 unsigned max_depth, | |
153 unsigned num_children_per_node) { | |
154 start_time_ = base::TimeTicks(); | |
155 num_runs_ = 0; | |
156 do { | |
157 internal::WorkerPoolTask::TaskVector empty; | |
158 leaf_task_ = make_scoped_refptr(new PerfControlTaskImpl(&empty)); | |
159 internal::WorkerPoolTask::TaskVector children; | |
160 BuildTaskGraph(&children, 0, max_depth, num_children_per_node); | |
161 scoped_refptr<PerfTaskImpl> root_task( | |
162 make_scoped_refptr(new PerfTaskImpl(&children))); | |
163 | |
164 worker_pool_->ScheduleTasks(root_task); | |
165 leaf_task_->WaitForTaskToStartRunning(); | |
166 worker_pool_->ScheduleTasks(NULL); | |
167 worker_pool_->CheckForCompletedTasks(); | |
168 leaf_task_->AllowTaskToFinish(); | |
169 } while (DidRun()); | |
170 | |
171 AfterTest(test_name); | |
172 } | |
173 | |
174 void RunExecuteTasksTest(const std::string test_name, | |
175 unsigned max_depth, | |
176 unsigned num_children_per_node) { | |
177 start_time_ = base::TimeTicks(); | |
178 num_runs_ = 0; | |
179 do { | |
180 internal::WorkerPoolTask::TaskVector children; | |
181 BuildTaskGraph(&children, 0, max_depth, num_children_per_node); | |
182 scoped_refptr<PerfControlTaskImpl> root_task( | |
183 make_scoped_refptr(new PerfControlTaskImpl(&children))); | |
184 | |
185 worker_pool_->ScheduleTasks(root_task); | |
186 root_task->WaitForTaskToStartRunning(); | |
187 root_task->AllowTaskToFinish(); | |
188 worker_pool_->CheckForCompletedTasks(); | |
189 } while (DidRun()); | |
190 | |
191 AfterTest(test_name); | |
192 } | |
193 | |
194 protected: | |
195 scoped_ptr<PerfWorkerPool> worker_pool_; | |
196 scoped_refptr<PerfControlTaskImpl> leaf_task_; | |
197 base::TimeTicks start_time_; | |
198 base::TimeDelta elapsed_; | |
199 int num_runs_; | |
200 }; | |
201 | |
202 TEST_F(WorkerPoolPerfTest, BuildTaskGraph) { | |
203 RunBuildTaskGraphTest("build_task_graph_1_10", 1, 10); | |
204 RunBuildTaskGraphTest("build_task_graph_1_1000", 1, 1000); | |
205 RunBuildTaskGraphTest("build_task_graph_2_10", 2, 10); | |
206 RunBuildTaskGraphTest("build_task_graph_5_5", 5, 5); | |
207 RunBuildTaskGraphTest("build_task_graph_10_2", 10, 2); | |
208 RunBuildTaskGraphTest("build_task_graph_1000_1", 1000, 1); | |
209 RunBuildTaskGraphTest("build_task_graph_10_1", 10, 1); | |
210 } | |
211 | |
212 TEST_F(WorkerPoolPerfTest, ScheduleTasks) { | |
213 RunScheduleTasksTest("schedule_tasks_1_10", 1, 10); | |
214 RunScheduleTasksTest("schedule_tasks_1_1000", 1, 1000); | |
215 RunScheduleTasksTest("schedule_tasks_2_10", 2, 10); | |
216 RunScheduleTasksTest("schedule_tasks_5_5", 5, 5); | |
217 RunScheduleTasksTest("schedule_tasks_10_2", 10, 2); | |
218 RunScheduleTasksTest("schedule_tasks_1000_1", 1000, 1); | |
219 RunScheduleTasksTest("schedule_tasks_10_1", 10, 1); | |
220 } | |
221 | |
222 TEST_F(WorkerPoolPerfTest, ExecuteTasks) { | |
223 RunExecuteTasksTest("execute_tasks_1_10", 1, 10); | |
224 RunExecuteTasksTest("execute_tasks_1_1000", 1, 1000); | |
225 RunExecuteTasksTest("execute_tasks_2_10", 2, 10); | |
226 RunExecuteTasksTest("execute_tasks_5_5", 5, 5); | |
227 RunExecuteTasksTest("execute_tasks_10_2", 10, 2); | |
228 RunExecuteTasksTest("execute_tasks_1000_1", 1000, 1); | |
229 RunExecuteTasksTest("execute_tasks_10_1", 10, 1); | |
230 } | |
231 | |
232 } // namespace | |
233 | |
234 } // namespace cc | |
OLD | NEW |