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

Side by Side Diff: components/scheduler/renderer/renderer_scheduler_impl_unittest.cc

Issue 1411133003: A better idle time estimator (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@2526
Patch Set: Created 5 years, 1 month 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
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 "components/scheduler/renderer/renderer_scheduler_impl.h" 5 #include "components/scheduler/renderer/renderer_scheduler_impl.h"
6 6
7 #include "base/callback.h" 7 #include "base/callback.h"
8 #include "base/test/simple_test_tick_clock.h" 8 #include "base/test/simple_test_tick_clock.h"
9 #include "cc/output/begin_frame_args.h" 9 #include "cc/output/begin_frame_args.h"
10 #include "cc/test/ordered_simple_task_runner.h" 10 #include "cc/test/ordered_simple_task_runner.h"
(...skipping 248 matching lines...) Expand 10 before | Expand all | Expand 10 after
259 make_scoped_ptr(new TestTimeSource(clock_.get()))); 259 make_scoped_ptr(new TestTimeSource(clock_.get())));
260 scheduler_->GetSchedulerHelperForTesting() 260 scheduler_->GetSchedulerHelperForTesting()
261 ->GetTaskQueueManagerForTesting() 261 ->GetTaskQueueManagerForTesting()
262 ->SetTimeSourceForTesting( 262 ->SetTimeSourceForTesting(
263 make_scoped_ptr(new TestTimeSource(clock_.get()))); 263 make_scoped_ptr(new TestTimeSource(clock_.get())));
264 scheduler_->GetLoadingTaskCostEstimatorForTesting() 264 scheduler_->GetLoadingTaskCostEstimatorForTesting()
265 ->SetTimeSourceForTesting( 265 ->SetTimeSourceForTesting(
266 make_scoped_ptr(new TestTimeSource(clock_.get()))); 266 make_scoped_ptr(new TestTimeSource(clock_.get())));
267 scheduler_->GetTimerTaskCostEstimatorForTesting()->SetTimeSourceForTesting( 267 scheduler_->GetTimerTaskCostEstimatorForTesting()->SetTimeSourceForTesting(
268 make_scoped_ptr(new TestTimeSource(clock_.get()))); 268 make_scoped_ptr(new TestTimeSource(clock_.get())));
269 scheduler_->GetIdleTimeEstimatorForTesting()->SetTimeSourceForTesting(
270 make_scoped_ptr(new TestTimeSource(clock_.get())));
269 } 271 }
270 272
271 void TearDown() override { 273 void TearDown() override {
272 DCHECK(!mock_task_runner_.get() || !message_loop_.get()); 274 DCHECK(!mock_task_runner_.get() || !message_loop_.get());
273 scheduler_->Shutdown(); 275 scheduler_->Shutdown();
274 if (mock_task_runner_.get()) { 276 if (mock_task_runner_.get()) {
275 // Check that all tests stop posting tasks. 277 // Check that all tests stop posting tasks.
276 mock_task_runner_->SetAutoAdvanceNowToPendingTasks(true); 278 mock_task_runner_->SetAutoAdvanceNowToPendingTasks(true);
277 while (mock_task_runner_->RunUntilIdle()) { 279 while (mock_task_runner_->RunUntilIdle()) {
278 } 280 }
279 } else { 281 } else {
280 message_loop_->RunUntilIdle(); 282 message_loop_->RunUntilIdle();
281 } 283 }
282 scheduler_.reset(); 284 scheduler_.reset();
283 } 285 }
284 286
285 void RunUntilIdle() { 287 void RunUntilIdle() {
286 // Only one of mock_task_runner_ or message_loop_ should be set. 288 // Only one of mock_task_runner_ or message_loop_ should be set.
287 DCHECK(!mock_task_runner_.get() || !message_loop_.get()); 289 DCHECK(!mock_task_runner_.get() || !message_loop_.get());
288 if (mock_task_runner_.get()) 290 if (mock_task_runner_.get())
289 mock_task_runner_->RunUntilIdle(); 291 mock_task_runner_->RunUntilIdle();
290 else 292 else
291 message_loop_->RunUntilIdle(); 293 message_loop_->RunUntilIdle();
292 } 294 }
293 295
294 void DoMainFrame() { 296 void DoMainFrame() {
295 cc::BeginFrameArgs begin_frame_args = cc::BeginFrameArgs::Create( 297 cc::BeginFrameArgs begin_frame_args = cc::BeginFrameArgs::Create(
296 BEGINFRAME_FROM_HERE, clock_->NowTicks(), base::TimeTicks(), 298 BEGINFRAME_FROM_HERE, clock_->NowTicks(), base::TimeTicks(),
297 base::TimeDelta::FromMilliseconds(1000), cc::BeginFrameArgs::NORMAL); 299 base::TimeDelta::FromMilliseconds(16), cc::BeginFrameArgs::NORMAL);
298 begin_frame_args.on_critical_path = false; 300 begin_frame_args.on_critical_path = false;
299 scheduler_->WillBeginFrame(begin_frame_args); 301 scheduler_->WillBeginFrame(begin_frame_args);
300 scheduler_->DidCommitFrameToCompositor(); 302 scheduler_->DidCommitFrameToCompositor();
301 } 303 }
302 304
303 void ForceMainThreadScrollingUseCase() { 305 void ForceMainThreadScrollingUseCase() {
304 cc::BeginFrameArgs begin_frame_args = cc::BeginFrameArgs::Create( 306 cc::BeginFrameArgs begin_frame_args = cc::BeginFrameArgs::Create(
305 BEGINFRAME_FROM_HERE, clock_->NowTicks(), base::TimeTicks(), 307 BEGINFRAME_FROM_HERE, clock_->NowTicks(), base::TimeTicks(),
306 base::TimeDelta::FromMilliseconds(1000), cc::BeginFrameArgs::NORMAL); 308 base::TimeDelta::FromMilliseconds(16), cc::BeginFrameArgs::NORMAL);
307 begin_frame_args.on_critical_path = true; 309 begin_frame_args.on_critical_path = true;
308 scheduler_->WillBeginFrame(begin_frame_args); 310 scheduler_->WillBeginFrame(begin_frame_args);
309 } 311 }
310 312
311 void ForceTouchStartToBeExpectedSoon() { 313 void ForceTouchStartToBeExpectedSoon() {
312 scheduler_->DidHandleInputEventOnCompositorThread( 314 scheduler_->DidHandleInputEventOnCompositorThread(
313 FakeInputEvent(blink::WebInputEvent::GestureScrollEnd), 315 FakeInputEvent(blink::WebInputEvent::GestureScrollEnd),
314 RendererScheduler::InputEventState::EVENT_CONSUMED_BY_COMPOSITOR); 316 RendererScheduler::InputEventState::EVENT_CONSUMED_BY_COMPOSITOR);
315 clock_->Advance(priority_escalation_after_input_duration() * 2); 317 clock_->Advance(priority_escalation_after_input_duration() * 2);
316 scheduler_->ForceUpdatePolicy(); 318 scheduler_->ForceUpdatePolicy();
(...skipping 13 matching lines...) Expand all
330 base::TimeDelta::FromMilliseconds(500))); 332 base::TimeDelta::FromMilliseconds(500)));
331 } 333 }
332 334
333 RunUntilIdle(); 335 RunUntilIdle();
334 336
335 // Switch back to not auto-advancing because we want to be in control of 337 // Switch back to not auto-advancing because we want to be in control of
336 // when time advances. 338 // when time advances.
337 mock_task_runner_->SetAutoAdvanceNowToPendingTasks(false); 339 mock_task_runner_->SetAutoAdvanceNowToPendingTasks(false);
338 } 340 }
339 341
342 void WillBeginMainThreadGestureFrame() {
343 scheduler_->DidAnimateForInputOnCompositorThread();
344 cc::BeginFrameArgs begin_frame_args = cc::BeginFrameArgs::Create(
345 BEGINFRAME_FROM_HERE, clock_->NowTicks(), base::TimeTicks(),
346 base::TimeDelta::FromMilliseconds(16), cc::BeginFrameArgs::NORMAL);
347 begin_frame_args.on_critical_path = true;
348 scheduler_->WillBeginFrame(begin_frame_args);
349 }
350
351 void SimulateMainThreadGestureCompositorTask(
352 base::TimeDelta begin_main_frame_duration) {
353 WillBeginMainThreadGestureFrame();
354 clock_->Advance(begin_main_frame_duration);
355 scheduler_->DidCommitFrameToCompositor();
356 }
357
358 void SimulateTimerTask(base::TimeDelta duration) {
359 clock_->Advance(duration);
360 simulate_timer_task_ran_ = true;
361 }
362
340 void EnableIdleTasks() { DoMainFrame(); } 363 void EnableIdleTasks() { DoMainFrame(); }
341 364
342 UseCase CurrentUseCase() { 365 UseCase CurrentUseCase() {
343 return scheduler_->MainThreadOnly().current_use_case; 366 return scheduler_->MainThreadOnly().current_use_case;
344 } 367 }
345 368
346 UseCase ForceUpdatePolicyAndGetCurrentUseCase() { 369 UseCase ForceUpdatePolicyAndGetCurrentUseCase() {
347 scheduler_->ForceUpdatePolicy(); 370 scheduler_->ForceUpdatePolicy();
348 return scheduler_->MainThreadOnly().current_use_case; 371 return scheduler_->MainThreadOnly().current_use_case;
349 } 372 }
350 373
351 bool TouchStartExpectedSoon() { 374 bool TouchStartExpectedSoon() {
352 return scheduler_->MainThreadOnly().touchstart_expected_soon; 375 return scheduler_->MainThreadOnly().touchstart_expected_soon;
353 } 376 }
354 377
355 bool HaveSeenABeginMainframe() { 378 bool HaveSeenABeginMainframe() {
356 return scheduler_->MainThreadOnly().have_seen_a_begin_main_frame; 379 return scheduler_->MainThreadOnly().have_seen_a_begin_main_frame;
357 } 380 }
358 381
359 bool LoadingTasksSeemExpensive() { 382 bool LoadingTasksSeemExpensive() {
360 return scheduler_->MainThreadOnly().loading_tasks_seem_expensive; 383 return scheduler_->MainThreadOnly().loading_tasks_seem_expensive;
361 } 384 }
362 385
363 bool TimerTasksSeemExpensive() { 386 bool TimerTasksSeemExpensive() {
364 return scheduler_->MainThreadOnly().timer_tasks_seem_expensive; 387 return scheduler_->MainThreadOnly().timer_tasks_seem_expensive;
365 } 388 }
366 389
390 base::TimeTicks EstimatedNextFrameBegin() {
391 return scheduler_->MainThreadOnly().estimated_next_frame_begin;
392 }
393
367 // Helper for posting several tasks of specific types. |task_descriptor| is a 394 // Helper for posting several tasks of specific types. |task_descriptor| is a
368 // string with space delimited task identifiers. The first letter of each 395 // string with space delimited task identifiers. The first letter of each
369 // task identifier specifies the task type: 396 // task identifier specifies the task type:
370 // - 'D': Default task 397 // - 'D': Default task
371 // - 'C': Compositor task 398 // - 'C': Compositor task
372 // - 'L': Loading task 399 // - 'L': Loading task
373 // - 'I': Idle task 400 // - 'I': Idle task
374 // - 'T': Timer task 401 // - 'T': Timer task
375 void PostTestTasks(std::vector<std::string>* run_order, 402 void PostTestTasks(std::vector<std::string>* run_order,
376 const std::string& task_descriptor) { 403 const std::string& task_descriptor) {
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
459 scoped_refptr<cc::OrderedSimpleTaskRunner> mock_task_runner_; 486 scoped_refptr<cc::OrderedSimpleTaskRunner> mock_task_runner_;
460 scoped_ptr<base::MessageLoop> message_loop_; 487 scoped_ptr<base::MessageLoop> message_loop_;
461 488
462 scoped_refptr<SchedulerTaskRunnerDelegate> main_task_runner_; 489 scoped_refptr<SchedulerTaskRunnerDelegate> main_task_runner_;
463 scoped_ptr<RendererSchedulerImplForTest> scheduler_; 490 scoped_ptr<RendererSchedulerImplForTest> scheduler_;
464 scoped_refptr<base::SingleThreadTaskRunner> default_task_runner_; 491 scoped_refptr<base::SingleThreadTaskRunner> default_task_runner_;
465 scoped_refptr<base::SingleThreadTaskRunner> compositor_task_runner_; 492 scoped_refptr<base::SingleThreadTaskRunner> compositor_task_runner_;
466 scoped_refptr<base::SingleThreadTaskRunner> loading_task_runner_; 493 scoped_refptr<base::SingleThreadTaskRunner> loading_task_runner_;
467 scoped_refptr<SingleThreadIdleTaskRunner> idle_task_runner_; 494 scoped_refptr<SingleThreadIdleTaskRunner> idle_task_runner_;
468 scoped_refptr<base::SingleThreadTaskRunner> timer_task_runner_; 495 scoped_refptr<base::SingleThreadTaskRunner> timer_task_runner_;
496 bool simulate_timer_task_ran_;
469 497
470 DISALLOW_COPY_AND_ASSIGN(RendererSchedulerImplTest); 498 DISALLOW_COPY_AND_ASSIGN(RendererSchedulerImplTest);
471 }; 499 };
472 500
473 TEST_F(RendererSchedulerImplTest, TestPostDefaultTask) { 501 TEST_F(RendererSchedulerImplTest, TestPostDefaultTask) {
474 std::vector<std::string> run_order; 502 std::vector<std::string> run_order;
475 PostTestTasks(&run_order, "D1 D2 D3 D4"); 503 PostTestTasks(&run_order, "D1 D2 D3 D4");
476 504
477 RunUntilIdle(); 505 RunUntilIdle();
478 EXPECT_THAT(run_order, 506 EXPECT_THAT(run_order,
(...skipping 250 matching lines...) Expand 10 before | Expand all | Expand 10 after
729 scheduler_->DidAnimateForInputOnCompositorThread(); 757 scheduler_->DidAnimateForInputOnCompositorThread();
730 EnableIdleTasks(); 758 EnableIdleTasks();
731 RunUntilIdle(); 759 RunUntilIdle();
732 EXPECT_THAT(run_order, 760 EXPECT_THAT(run_order,
733 testing::ElementsAre(std::string("D1"), std::string("C1"), 761 testing::ElementsAre(std::string("D1"), std::string("C1"),
734 std::string("D2"), std::string("C2"), 762 std::string("D2"), std::string("C2"),
735 std::string("I1"))); 763 std::string("I1")));
736 EXPECT_EQ(RendererScheduler::UseCase::COMPOSITOR_GESTURE, CurrentUseCase()); 764 EXPECT_EQ(RendererScheduler::UseCase::COMPOSITOR_GESTURE, CurrentUseCase());
737 } 765 }
738 766
739 // TODO(skyostil): Re-enable once timer blocking is re-enabled.
740 TEST_F( 767 TEST_F(
741 RendererSchedulerImplTest, 768 RendererSchedulerImplTest,
742 DISABLED_TestCompositorPolicy_ExpensiveTimersDontRunWhenMainThreadOnCritical Path) { 769 TestCompositorPolicy_ExpensiveTimersDontRunWhenMainThreadOnCriticalPath) {
743 std::vector<std::string> run_order; 770 std::vector<std::string> run_order;
744 771
745 SimulateExpensiveTasks(timer_task_runner_); 772 SimulateExpensiveTasks(timer_task_runner_);
746 773
747 // Timers should now be disabled during main thread user user interactions. 774 // Timers should now be disabled during main thread user user interactions.
748 PostTestTasks(&run_order, "C1 T1"); 775 PostTestTasks(&run_order, "C1 T1");
749 776
750 // Trigger main_thread_gesture UseCase 777 // Trigger main_thread_gesture UseCase
751 scheduler_->DidAnimateForInputOnCompositorThread(); 778 WillBeginMainThreadGestureFrame();
752 cc::BeginFrameArgs begin_frame_args1 = cc::BeginFrameArgs::Create(
753 BEGINFRAME_FROM_HERE, clock_->NowTicks(), base::TimeTicks(),
754 base::TimeDelta::FromMilliseconds(16), cc::BeginFrameArgs::NORMAL);
755 begin_frame_args1.on_critical_path = true;
756 scheduler_->WillBeginFrame(begin_frame_args1);
757 RunUntilIdle(); 779 RunUntilIdle();
758 EXPECT_EQ(RendererScheduler::UseCase::MAIN_THREAD_GESTURE, CurrentUseCase()); 780 EXPECT_EQ(RendererScheduler::UseCase::MAIN_THREAD_GESTURE, CurrentUseCase());
759 781
760 EXPECT_THAT(run_order, testing::ElementsAre(std::string("C1"))); 782 EXPECT_THAT(run_order, testing::ElementsAre(std::string("C1")));
761 clock_->Advance(subsequent_input_expected_after_input_duration() * 2); 783 clock_->Advance(subsequent_input_expected_after_input_duration() * 2);
762 784
763 run_order.clear(); 785 run_order.clear();
764 RunUntilIdle(); 786 RunUntilIdle();
765 EXPECT_EQ(RendererScheduler::UseCase::NONE, CurrentUseCase()); 787 EXPECT_EQ(RendererScheduler::UseCase::NONE, CurrentUseCase());
766 EXPECT_THAT(run_order, testing::ElementsAre(std::string("T1"))); 788 EXPECT_THAT(run_order, testing::ElementsAre(std::string("T1")));
767 } 789 }
768 790
769 TEST_F(RendererSchedulerImplTest, Navigation_ResetsTaskCostEstimations) { 791 TEST_F(RendererSchedulerImplTest, Navigation_ResetsTaskCostEstimations) {
770 std::vector<std::string> run_order; 792 std::vector<std::string> run_order;
771 793
772 SimulateExpensiveTasks(timer_task_runner_); 794 SimulateExpensiveTasks(timer_task_runner_);
773 scheduler_->OnNavigationStarted(); 795 scheduler_->OnNavigationStarted();
774 PostTestTasks(&run_order, "C1 T1"); 796 PostTestTasks(&run_order, "C1 T1");
775 797
776 scheduler_->DidAnimateForInputOnCompositorThread(); 798 WillBeginMainThreadGestureFrame();
777 cc::BeginFrameArgs begin_frame_args1 = cc::BeginFrameArgs::Create(
778 BEGINFRAME_FROM_HERE, clock_->NowTicks(), base::TimeTicks(),
779 base::TimeDelta::FromMilliseconds(1000), cc::BeginFrameArgs::NORMAL);
780 begin_frame_args1.on_critical_path = true;
781 scheduler_->WillBeginFrame(begin_frame_args1);
782 scheduler_->DidCommitFrameToCompositor(); // Starts Idle Period 799 scheduler_->DidCommitFrameToCompositor(); // Starts Idle Period
783 RunUntilIdle(); 800 RunUntilIdle();
784 801
785 EXPECT_THAT(run_order, 802 EXPECT_THAT(run_order,
786 testing::ElementsAre(std::string("C1"), std::string("T1"))); 803 testing::ElementsAre(std::string("C1"), std::string("T1")));
787 } 804 }
788 805
789 TEST_F(RendererSchedulerImplTest, 806 TEST_F(RendererSchedulerImplTest,
790 TestCompositorPolicy_TimersAlwaysRun_MainThreadNotOnCriticalPath) { 807 TestCompositorPolicy_TimersAlwaysRun_MainThreadNotOnCriticalPath) {
791 std::vector<std::string> run_order; 808 std::vector<std::string> run_order;
(...skipping 1302 matching lines...) Expand 10 before | Expand all | Expand 10 after
2094 RunUntilIdle(); 2111 RunUntilIdle();
2095 2112
2096 EXPECT_EQ(RendererScheduler::UseCase::NONE, CurrentUseCase()); 2113 EXPECT_EQ(RendererScheduler::UseCase::NONE, CurrentUseCase());
2097 EXPECT_TRUE(HaveSeenABeginMainframe()); 2114 EXPECT_TRUE(HaveSeenABeginMainframe());
2098 EXPECT_TRUE(LoadingTasksSeemExpensive()); 2115 EXPECT_TRUE(LoadingTasksSeemExpensive());
2099 EXPECT_FALSE(TimerTasksSeemExpensive()); 2116 EXPECT_FALSE(TimerTasksSeemExpensive());
2100 EXPECT_TRUE(TouchStartExpectedSoon()); 2117 EXPECT_TRUE(TouchStartExpectedSoon());
2101 EXPECT_THAT(run_order, testing::ElementsAre(std::string("D1"))); 2118 EXPECT_THAT(run_order, testing::ElementsAre(std::string("D1")));
2102 } 2119 }
2103 2120
2121 TEST_F(RendererSchedulerImplTest, ModeratelyExpensiveTimer_NotBlocked) {
2122 for (int i = 0; i < 20; i++) {
2123 simulate_timer_task_ran_ = false;
2124 compositor_task_runner_->PostTask(
2125 FROM_HERE,
2126 base::Bind(
2127 &RendererSchedulerImplTest::SimulateMainThreadGestureCompositorTask,
2128 base::Unretained(this), base::TimeDelta::FromMilliseconds(4)));
2129 timer_task_runner_->PostTask(
2130 FROM_HERE, base::Bind(&RendererSchedulerImplTest::SimulateTimerTask,
2131 base::Unretained(this),
2132 base::TimeDelta::FromMilliseconds(10)));
2104 2133
2134 RunUntilIdle();
2135 EXPECT_TRUE(simulate_timer_task_ran_);
2136 EXPECT_EQ(RendererScheduler::UseCase::MAIN_THREAD_GESTURE,
2137 CurrentUseCase());
2138 EXPECT_FALSE(LoadingTasksSeemExpensive());
2139 EXPECT_FALSE(TimerTasksSeemExpensive());
2140
2141 base::TimeDelta time_till_next_frame =
2142 EstimatedNextFrameBegin() - clock_->NowTicks();
2143 if (time_till_next_frame > base::TimeDelta())
2144 clock_->Advance(time_till_next_frame);
2145 }
2146 }
2147
2148 TEST_F(RendererSchedulerImplTest, ExpensiveTimer_Blocked) {
2149 for (int i = 0; i < 20; i++) {
2150 simulate_timer_task_ran_ = false;
2151 compositor_task_runner_->PostTask(
2152 FROM_HERE,
2153 base::Bind(
2154 &RendererSchedulerImplTest::SimulateMainThreadGestureCompositorTask,
2155 base::Unretained(this), base::TimeDelta::FromMilliseconds(8)));
2156 timer_task_runner_->PostTask(
2157 FROM_HERE, base::Bind(&RendererSchedulerImplTest::SimulateTimerTask,
2158 base::Unretained(this),
2159 base::TimeDelta::FromMilliseconds(10)));
2160
2161 RunUntilIdle();
2162 EXPECT_EQ(RendererScheduler::UseCase::MAIN_THREAD_GESTURE,
2163 CurrentUseCase());
2164 EXPECT_FALSE(LoadingTasksSeemExpensive());
2165 if (i == 0) {
2166 EXPECT_FALSE(TimerTasksSeemExpensive());
2167 EXPECT_TRUE(simulate_timer_task_ran_);
2168 } else {
2169 EXPECT_TRUE(TimerTasksSeemExpensive());
2170 EXPECT_FALSE(simulate_timer_task_ran_);
2171 }
2172
2173 base::TimeDelta time_till_next_frame =
2174 EstimatedNextFrameBegin() - clock_->NowTicks();
2175 if (time_till_next_frame > base::TimeDelta())
2176 clock_->Advance(time_till_next_frame);
2177 }
2178 }
2105 } // namespace scheduler 2179 } // namespace scheduler
OLDNEW
« no previous file with comments | « components/scheduler/renderer/renderer_scheduler_impl.cc ('k') | components/scheduler/scheduler.gypi » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698