| 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 "content/renderer/scheduler/renderer_scheduler_impl.h" | 5 #include "content/renderer/scheduler/renderer_scheduler_impl.h" |
| 6 | 6 |
| 7 #include "base/callback.h" | 7 #include "base/callback.h" |
| 8 #include "cc/output/begin_frame_args.h" | 8 #include "cc/output/begin_frame_args.h" |
| 9 #include "cc/test/ordered_simple_task_runner.h" | 9 #include "cc/test/ordered_simple_task_runner.h" |
| 10 #include "content/renderer/scheduler/nestable_task_runner_for_test.h" | 10 #include "content/child/scheduler/nestable_task_runner_for_test.h" |
| 11 #include "content/renderer/scheduler/renderer_scheduler_message_loop_delegate.h" | 11 #include "content/child/scheduler/scheduler_message_loop_delegate.h" |
| 12 #include "testing/gmock/include/gmock/gmock.h" | 12 #include "testing/gmock/include/gmock/gmock.h" |
| 13 #include "testing/gtest/include/gtest/gtest.h" | 13 #include "testing/gtest/include/gtest/gtest.h" |
| 14 | 14 |
| 15 namespace content { | 15 namespace content { |
| 16 | 16 |
| 17 namespace { | 17 namespace { |
| 18 class FakeInputEvent : public blink::WebInputEvent { | 18 class FakeInputEvent : public blink::WebInputEvent { |
| 19 public: | 19 public: |
| 20 explicit FakeInputEvent(blink::WebInputEvent::Type event_type) | 20 explicit FakeInputEvent(blink::WebInputEvent::Type event_type) |
| 21 : WebInputEvent(sizeof(FakeInputEvent)) { | 21 : WebInputEvent(sizeof(FakeInputEvent)) { |
| (...skipping 11 matching lines...) Expand all Loading... |
| 33 std::string value) { | 33 std::string value) { |
| 34 vector->push_back(value); | 34 vector->push_back(value); |
| 35 } | 35 } |
| 36 | 36 |
| 37 void AppendToVectorIdleTestTask(std::vector<std::string>* vector, | 37 void AppendToVectorIdleTestTask(std::vector<std::string>* vector, |
| 38 std::string value, | 38 std::string value, |
| 39 base::TimeTicks deadline) { | 39 base::TimeTicks deadline) { |
| 40 AppendToVectorTestTask(vector, value); | 40 AppendToVectorTestTask(vector, value); |
| 41 } | 41 } |
| 42 | 42 |
| 43 void NullTask() { |
| 44 } |
| 45 |
| 46 void AppendToVectorReentrantTask( |
| 47 scoped_refptr<base::SingleThreadTaskRunner> task_runner, |
| 48 std::vector<int>* vector, |
| 49 int* reentrant_count, |
| 50 int max_reentrant_count) { |
| 51 vector->push_back((*reentrant_count)++); |
| 52 if (*reentrant_count < max_reentrant_count) { |
| 53 task_runner->PostTask( |
| 54 FROM_HERE, base::Bind(AppendToVectorReentrantTask, task_runner, vector, |
| 55 reentrant_count, max_reentrant_count)); |
| 56 } |
| 57 } |
| 58 |
| 59 void IdleTestTask(int* run_count, |
| 60 base::TimeTicks* deadline_out, |
| 61 base::TimeTicks deadline) { |
| 62 (*run_count)++; |
| 63 *deadline_out = deadline; |
| 64 } |
| 65 |
| 66 int max_idle_task_reposts = 2; |
| 67 |
| 68 void RepostingIdleTestTask( |
| 69 scoped_refptr<SingleThreadIdleTaskRunner> idle_task_runner, |
| 70 int* run_count, |
| 71 base::TimeTicks deadline) { |
| 72 if ((*run_count + 1) < max_idle_task_reposts) { |
| 73 idle_task_runner->PostIdleTask( |
| 74 FROM_HERE, |
| 75 base::Bind(&RepostingIdleTestTask, idle_task_runner, run_count)); |
| 76 } |
| 77 (*run_count)++; |
| 78 } |
| 79 |
| 80 void UpdateClockToDeadlineIdleTestTask( |
| 81 scoped_refptr<cc::TestNowSource> clock, |
| 82 scoped_refptr<base::SingleThreadTaskRunner> task_runner, |
| 83 int* run_count, |
| 84 base::TimeTicks deadline) { |
| 85 clock->SetNow(deadline); |
| 86 // Due to the way in which OrderedSimpleTestRunner orders tasks and the fact |
| 87 // that we updated the time within a task, the delayed pending task to call |
| 88 // EndIdlePeriod will not happen until after a TaskQueueManager DoWork, so |
| 89 // post a normal task here to ensure it runs before the next idle task. |
| 90 task_runner->PostTask(FROM_HERE, base::Bind(NullTask)); |
| 91 (*run_count)++; |
| 92 } |
| 93 |
| 94 void PostingYieldingTestTask( |
| 95 RendererSchedulerImpl* scheduler, |
| 96 scoped_refptr<base::SingleThreadTaskRunner> task_runner, |
| 97 bool simulate_input, |
| 98 bool* should_yield_before, |
| 99 bool* should_yield_after) { |
| 100 *should_yield_before = scheduler->ShouldYieldForHighPriorityWork(); |
| 101 task_runner->PostTask(FROM_HERE, base::Bind(NullTask)); |
| 102 if (simulate_input) { |
| 103 scheduler->DidReceiveInputEventOnCompositorThread( |
| 104 FakeInputEvent(blink::WebInputEvent::GestureFlingStart)); |
| 105 } |
| 106 *should_yield_after = scheduler->ShouldYieldForHighPriorityWork(); |
| 107 } |
| 108 |
| 109 void AnticipationTestTask(RendererSchedulerImpl* scheduler, |
| 110 bool simulate_input, |
| 111 bool* is_anticipated_before, |
| 112 bool* is_anticipated_after) { |
| 113 *is_anticipated_before = scheduler->IsHighPriorityWorkAnticipated(); |
| 114 if (simulate_input) { |
| 115 scheduler->DidReceiveInputEventOnCompositorThread( |
| 116 FakeInputEvent(blink::WebInputEvent::GestureFlingStart)); |
| 117 } |
| 118 *is_anticipated_after = scheduler->IsHighPriorityWorkAnticipated(); |
| 119 } |
| 43 }; // namespace | 120 }; // namespace |
| 44 | 121 |
| 45 class RendererSchedulerImplTest : public testing::Test { | 122 class RendererSchedulerImplTest : public testing::Test { |
| 46 public: | 123 public: |
| 47 using Policy = RendererSchedulerImpl::Policy; | 124 using Policy = RendererSchedulerImpl::Policy; |
| 48 | 125 |
| 49 RendererSchedulerImplTest() | 126 RendererSchedulerImplTest() |
| 50 : clock_(cc::TestNowSource::Create(5000)), | 127 : clock_(cc::TestNowSource::Create(5000)), |
| 51 mock_task_runner_(new cc::OrderedSimpleTaskRunner(clock_, false)), | 128 mock_task_runner_(new cc::OrderedSimpleTaskRunner(clock_, false)), |
| 52 nestable_task_runner_( | 129 nestable_task_runner_( |
| 53 NestableTaskRunnerForTest::Create(mock_task_runner_)), | 130 NestableTaskRunnerForTest::Create(mock_task_runner_)), |
| 54 scheduler_(new RendererSchedulerImpl(nestable_task_runner_)), | 131 scheduler_(new RendererSchedulerImpl(nestable_task_runner_)), |
| 55 default_task_runner_(scheduler_->DefaultTaskRunner()), | 132 default_task_runner_(scheduler_->DefaultTaskRunner()), |
| 56 compositor_task_runner_(scheduler_->CompositorTaskRunner()), | 133 compositor_task_runner_(scheduler_->CompositorTaskRunner()), |
| 57 loading_task_runner_(scheduler_->LoadingTaskRunner()), | 134 loading_task_runner_(scheduler_->LoadingTaskRunner()), |
| 58 idle_task_runner_(scheduler_->IdleTaskRunner()) { | 135 idle_task_runner_(scheduler_->IdleTaskRunner()) { |
| 59 scheduler_->SetTimeSourceForTesting(clock_); | 136 scheduler_->SetTimeSourceForTesting(clock_); |
| 60 } | 137 } |
| 61 | 138 |
| 62 RendererSchedulerImplTest(base::MessageLoop* message_loop) | 139 RendererSchedulerImplTest(base::MessageLoop* message_loop) |
| 63 : clock_(cc::TestNowSource::Create(5000)), | 140 : clock_(cc::TestNowSource::Create(5000)), |
| 64 message_loop_(message_loop), | 141 message_loop_(message_loop), |
| 65 nestable_task_runner_( | 142 nestable_task_runner_( |
| 66 RendererSchedulerMessageLoopDelegate::Create(message_loop)), | 143 SchedulerMessageLoopDelegate::Create(message_loop)), |
| 67 scheduler_(new RendererSchedulerImpl(nestable_task_runner_)), | 144 scheduler_(new RendererSchedulerImpl(nestable_task_runner_)), |
| 68 default_task_runner_(scheduler_->DefaultTaskRunner()), | 145 default_task_runner_(scheduler_->DefaultTaskRunner()), |
| 69 compositor_task_runner_(scheduler_->CompositorTaskRunner()), | 146 compositor_task_runner_(scheduler_->CompositorTaskRunner()), |
| 70 loading_task_runner_(scheduler_->LoadingTaskRunner()), | 147 loading_task_runner_(scheduler_->LoadingTaskRunner()), |
| 71 idle_task_runner_(scheduler_->IdleTaskRunner()) { | 148 idle_task_runner_(scheduler_->IdleTaskRunner()) { |
| 72 scheduler_->SetTimeSourceForTesting(clock_); | 149 scheduler_->SetTimeSourceForTesting(clock_); |
| 73 } | 150 } |
| 74 ~RendererSchedulerImplTest() override {} | 151 ~RendererSchedulerImplTest() override {} |
| 75 | 152 |
| 76 void TearDown() override { | 153 void TearDown() override { |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 153 } | 230 } |
| 154 | 231 |
| 155 protected: | 232 protected: |
| 156 static base::TimeDelta priority_escalation_after_input_duration() { | 233 static base::TimeDelta priority_escalation_after_input_duration() { |
| 157 return base::TimeDelta::FromMilliseconds( | 234 return base::TimeDelta::FromMilliseconds( |
| 158 RendererSchedulerImpl::kPriorityEscalationAfterInputMillis); | 235 RendererSchedulerImpl::kPriorityEscalationAfterInputMillis); |
| 159 } | 236 } |
| 160 | 237 |
| 161 static base::TimeDelta maximum_idle_period_duration() { | 238 static base::TimeDelta maximum_idle_period_duration() { |
| 162 return base::TimeDelta::FromMilliseconds( | 239 return base::TimeDelta::FromMilliseconds( |
| 163 RendererSchedulerImpl::kMaximumIdlePeriodMillis); | 240 SchedulerHelper::kMaximumIdlePeriodMillis); |
| 164 } | 241 } |
| 165 | 242 |
| 166 base::TimeTicks CurrentIdleTaskDeadline() { | 243 base::TimeTicks CurrentIdleTaskDeadline() { |
| 167 base::TimeTicks deadline; | 244 base::TimeTicks deadline; |
| 168 scheduler_->CurrentIdleTaskDeadlineCallback(&deadline); | 245 scheduler_->CurrentIdleTaskDeadlineCallbackForTesting(&deadline); |
| 169 return deadline; | 246 return deadline; |
| 170 } | 247 } |
| 171 | 248 |
| 172 scoped_refptr<cc::TestNowSource> clock_; | 249 scoped_refptr<cc::TestNowSource> clock_; |
| 173 // Only one of mock_task_runner_ or message_loop_ will be set. | 250 // Only one of mock_task_runner_ or message_loop_ will be set. |
| 174 scoped_refptr<cc::OrderedSimpleTaskRunner> mock_task_runner_; | 251 scoped_refptr<cc::OrderedSimpleTaskRunner> mock_task_runner_; |
| 175 scoped_ptr<base::MessageLoop> message_loop_; | 252 scoped_ptr<base::MessageLoop> message_loop_; |
| 176 | 253 |
| 177 scoped_refptr<NestableSingleThreadTaskRunner> nestable_task_runner_; | 254 scoped_refptr<NestableSingleThreadTaskRunner> nestable_task_runner_; |
| 178 scoped_ptr<RendererSchedulerImpl> scheduler_; | 255 scoped_ptr<RendererSchedulerImpl> scheduler_; |
| 179 scoped_refptr<base::SingleThreadTaskRunner> default_task_runner_; | 256 scoped_refptr<base::SingleThreadTaskRunner> default_task_runner_; |
| 180 scoped_refptr<base::SingleThreadTaskRunner> compositor_task_runner_; | 257 scoped_refptr<base::SingleThreadTaskRunner> compositor_task_runner_; |
| 181 scoped_refptr<base::SingleThreadTaskRunner> loading_task_runner_; | 258 scoped_refptr<base::SingleThreadTaskRunner> loading_task_runner_; |
| 182 scoped_refptr<SingleThreadIdleTaskRunner> idle_task_runner_; | 259 scoped_refptr<SingleThreadIdleTaskRunner> idle_task_runner_; |
| 183 | 260 |
| 184 DISALLOW_COPY_AND_ASSIGN(RendererSchedulerImplTest); | 261 DISALLOW_COPY_AND_ASSIGN(RendererSchedulerImplTest); |
| 185 }; | 262 }; |
| 186 | 263 |
| 187 void NullTask() { | |
| 188 } | |
| 189 | |
| 190 void AppendToVectorReentrantTask( | |
| 191 scoped_refptr<base::SingleThreadTaskRunner> task_runner, | |
| 192 std::vector<int>* vector, | |
| 193 int* reentrant_count, | |
| 194 int max_reentrant_count) { | |
| 195 vector->push_back((*reentrant_count)++); | |
| 196 if (*reentrant_count < max_reentrant_count) { | |
| 197 task_runner->PostTask( | |
| 198 FROM_HERE, base::Bind(AppendToVectorReentrantTask, task_runner, vector, | |
| 199 reentrant_count, max_reentrant_count)); | |
| 200 } | |
| 201 } | |
| 202 | |
| 203 void IdleTestTask(int* run_count, | |
| 204 base::TimeTicks* deadline_out, | |
| 205 base::TimeTicks deadline) { | |
| 206 (*run_count)++; | |
| 207 *deadline_out = deadline; | |
| 208 } | |
| 209 | |
| 210 void RepostingIdleTestTask( | |
| 211 scoped_refptr<SingleThreadIdleTaskRunner> idle_task_runner, | |
| 212 int* run_count, | |
| 213 base::TimeTicks deadline) { | |
| 214 if (*run_count == 0) { | |
| 215 idle_task_runner->PostIdleTask( | |
| 216 FROM_HERE, | |
| 217 base::Bind(&RepostingIdleTestTask, idle_task_runner, run_count)); | |
| 218 } | |
| 219 (*run_count)++; | |
| 220 } | |
| 221 | |
| 222 void UpdateClockToDeadlineIdleTestTask( | |
| 223 scoped_refptr<cc::TestNowSource> clock, | |
| 224 scoped_refptr<base::SingleThreadTaskRunner> task_runner, | |
| 225 int* run_count, | |
| 226 base::TimeTicks deadline) { | |
| 227 clock->SetNow(deadline); | |
| 228 // Due to the way in which OrderedSimpleTestRunner orders tasks and the fact | |
| 229 // that we updated the time within a task, the delayed pending task to call | |
| 230 // EndIdlePeriod will not happen until after a TaskQueueManager DoWork, so | |
| 231 // post a normal task here to ensure it runs before the next idle task. | |
| 232 task_runner->PostTask(FROM_HERE, base::Bind(NullTask)); | |
| 233 (*run_count)++; | |
| 234 } | |
| 235 | |
| 236 void PostingYieldingTestTask( | |
| 237 RendererSchedulerImpl* scheduler, | |
| 238 scoped_refptr<base::SingleThreadTaskRunner> task_runner, | |
| 239 bool simulate_input, | |
| 240 bool* should_yield_before, | |
| 241 bool* should_yield_after) { | |
| 242 *should_yield_before = scheduler->ShouldYieldForHighPriorityWork(); | |
| 243 task_runner->PostTask(FROM_HERE, base::Bind(NullTask)); | |
| 244 if (simulate_input) { | |
| 245 scheduler->DidReceiveInputEventOnCompositorThread( | |
| 246 FakeInputEvent(blink::WebInputEvent::GestureFlingStart)); | |
| 247 } | |
| 248 *should_yield_after = scheduler->ShouldYieldForHighPriorityWork(); | |
| 249 } | |
| 250 | |
| 251 void AnticipationTestTask(RendererSchedulerImpl* scheduler, | |
| 252 bool simulate_input, | |
| 253 bool* is_anticipated_before, | |
| 254 bool* is_anticipated_after) { | |
| 255 *is_anticipated_before = scheduler->IsHighPriorityWorkAnticipated(); | |
| 256 if (simulate_input) { | |
| 257 scheduler->DidReceiveInputEventOnCompositorThread( | |
| 258 FakeInputEvent(blink::WebInputEvent::GestureFlingStart)); | |
| 259 } | |
| 260 *is_anticipated_after = scheduler->IsHighPriorityWorkAnticipated(); | |
| 261 } | |
| 262 | |
| 263 TEST_F(RendererSchedulerImplTest, TestPostDefaultTask) { | 264 TEST_F(RendererSchedulerImplTest, TestPostDefaultTask) { |
| 264 std::vector<std::string> run_order; | 265 std::vector<std::string> run_order; |
| 265 PostTestTasks(&run_order, "D1 D2 D3 D4"); | 266 PostTestTasks(&run_order, "D1 D2 D3 D4"); |
| 266 | 267 |
| 267 RunUntilIdle(); | 268 RunUntilIdle(); |
| 268 EXPECT_THAT(run_order, | 269 EXPECT_THAT(run_order, |
| 269 testing::ElementsAre(std::string("D1"), std::string("D2"), | 270 testing::ElementsAre(std::string("D1"), std::string("D2"), |
| 270 std::string("D3"), std::string("D4"))); | 271 std::string("D3"), std::string("D4"))); |
| 271 } | 272 } |
| 272 | 273 |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 319 clock_->AdvanceNow(base::TimeDelta::FromMilliseconds(800)); | 320 clock_->AdvanceNow(base::TimeDelta::FromMilliseconds(800)); |
| 320 scheduler_->DidCommitFrameToCompositor(); | 321 scheduler_->DidCommitFrameToCompositor(); |
| 321 RunUntilIdle(); | 322 RunUntilIdle(); |
| 322 EXPECT_EQ(1, run_count); | 323 EXPECT_EQ(1, run_count); |
| 323 EXPECT_EQ(expected_deadline, deadline_in_task); | 324 EXPECT_EQ(expected_deadline, deadline_in_task); |
| 324 } | 325 } |
| 325 | 326 |
| 326 TEST_F(RendererSchedulerImplTest, TestRepostingIdleTask) { | 327 TEST_F(RendererSchedulerImplTest, TestRepostingIdleTask) { |
| 327 int run_count = 0; | 328 int run_count = 0; |
| 328 | 329 |
| 330 max_idle_task_reposts = 2; |
| 329 idle_task_runner_->PostIdleTask( | 331 idle_task_runner_->PostIdleTask( |
| 330 FROM_HERE, | 332 FROM_HERE, |
| 331 base::Bind(&RepostingIdleTestTask, idle_task_runner_, &run_count)); | 333 base::Bind(&RepostingIdleTestTask, idle_task_runner_, &run_count)); |
| 332 EnableIdleTasks(); | 334 EnableIdleTasks(); |
| 333 RunUntilIdle(); | 335 RunUntilIdle(); |
| 334 EXPECT_EQ(1, run_count); | 336 EXPECT_EQ(1, run_count); |
| 335 | 337 |
| 336 // Reposted tasks shouldn't run until next idle period. | 338 // Reposted tasks shouldn't run until next idle period. |
| 337 RunUntilIdle(); | 339 RunUntilIdle(); |
| 338 EXPECT_EQ(1, run_count); | 340 EXPECT_EQ(1, run_count); |
| (...skipping 816 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1155 | 1157 |
| 1156 // After the delayed task has been run we should trigger an idle period. | 1158 // After the delayed task has been run we should trigger an idle period. |
| 1157 clock_->AdvanceNow(maximum_idle_period_duration()); | 1159 clock_->AdvanceNow(maximum_idle_period_duration()); |
| 1158 RunUntilIdle(); | 1160 RunUntilIdle(); |
| 1159 EXPECT_EQ(1, run_count); | 1161 EXPECT_EQ(1, run_count); |
| 1160 } | 1162 } |
| 1161 | 1163 |
| 1162 TEST_F(RendererSchedulerImplTest, TestLongIdlePeriodRepeating) { | 1164 TEST_F(RendererSchedulerImplTest, TestLongIdlePeriodRepeating) { |
| 1163 int run_count = 0; | 1165 int run_count = 0; |
| 1164 | 1166 |
| 1167 max_idle_task_reposts = 3; |
| 1165 idle_task_runner_->PostIdleTask( | 1168 idle_task_runner_->PostIdleTask( |
| 1166 FROM_HERE, | 1169 FROM_HERE, |
| 1167 base::Bind(&RepostingIdleTestTask, idle_task_runner_, &run_count)); | 1170 base::Bind(&RepostingIdleTestTask, idle_task_runner_, &run_count)); |
| 1168 | 1171 |
| 1169 scheduler_->BeginFrameNotExpectedSoon(); | 1172 scheduler_->BeginFrameNotExpectedSoon(); |
| 1170 RunUntilIdle(); | 1173 RunUntilIdle(); |
| 1171 EXPECT_EQ(1, run_count); // Should only run once per idle period. | 1174 EXPECT_EQ(1, run_count); // Should only run once per idle period. |
| 1172 | 1175 |
| 1173 // Advance time to start of next long idle period and check task reposted task | 1176 // Advance time to start of next long idle period and check task reposted task |
| 1174 // gets run. | 1177 // gets run. |
| (...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1295 | 1298 |
| 1296 // Next long idle period will be for the maximum time, so | 1299 // Next long idle period will be for the maximum time, so |
| 1297 // CanExceedIdleDeadlineIfRequired should return true. | 1300 // CanExceedIdleDeadlineIfRequired should return true. |
| 1298 scheduler_->WillBeginFrame(cc::BeginFrameArgs::Create( | 1301 scheduler_->WillBeginFrame(cc::BeginFrameArgs::Create( |
| 1299 BEGINFRAME_FROM_HERE, clock_->Now(), base::TimeTicks(), | 1302 BEGINFRAME_FROM_HERE, clock_->Now(), base::TimeTicks(), |
| 1300 base::TimeDelta::FromMilliseconds(1000), cc::BeginFrameArgs::NORMAL)); | 1303 base::TimeDelta::FromMilliseconds(1000), cc::BeginFrameArgs::NORMAL)); |
| 1301 EXPECT_FALSE(scheduler_->CanExceedIdleDeadlineIfRequired()); | 1304 EXPECT_FALSE(scheduler_->CanExceedIdleDeadlineIfRequired()); |
| 1302 } | 1305 } |
| 1303 | 1306 |
| 1304 } // namespace content | 1307 } // namespace content |
| OLD | NEW |