OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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 "platform/scheduler/renderer/task_queue_throttler.h" | 5 #include "platform/scheduler/renderer/task_queue_throttler.h" |
6 | 6 |
7 #include <stddef.h> | 7 #include <stddef.h> |
8 | 8 |
9 #include <memory> | 9 #include <memory> |
10 | 10 |
11 #include "base/callback.h" | 11 #include "base/callback.h" |
12 #include "base/macros.h" | 12 #include "base/macros.h" |
13 #include "base/memory/ptr_util.h" | 13 #include "base/memory/ptr_util.h" |
14 #include "base/test/simple_test_tick_clock.h" | 14 #include "base/test/simple_test_tick_clock.h" |
15 #include "cc/test/ordered_simple_task_runner.h" | 15 #include "cc/test/ordered_simple_task_runner.h" |
16 #include "platform/scheduler/base/task_queue_impl.h" | 16 #include "platform/scheduler/base/task_queue_impl.h" |
17 #include "platform/scheduler/base/test_time_source.h" | 17 #include "platform/scheduler/base/test_time_source.h" |
18 #include "platform/scheduler/child/scheduler_tqm_delegate_for_test.h" | 18 #include "platform/scheduler/child/scheduler_tqm_delegate_for_test.h" |
19 #include "platform/scheduler/renderer/budget_pool.h" | 19 #include "platform/scheduler/renderer/budget_pool.h" |
| 20 #include "platform/scheduler/renderer/cpu_time_budget_pool.h" |
20 #include "platform/scheduler/renderer/renderer_scheduler_impl.h" | 21 #include "platform/scheduler/renderer/renderer_scheduler_impl.h" |
| 22 #include "platform/scheduler/renderer/wake_up_budget_pool.h" |
21 #include "testing/gmock/include/gmock/gmock.h" | 23 #include "testing/gmock/include/gmock/gmock.h" |
22 #include "testing/gtest/include/gtest/gtest.h" | 24 #include "testing/gtest/include/gtest/gtest.h" |
23 | 25 |
24 namespace blink { | 26 namespace blink { |
25 namespace scheduler { | 27 namespace scheduler { |
26 | 28 |
27 class BudgetPoolTest : public testing::Test { | 29 class BudgetPoolTest : public testing::Test { |
28 public: | 30 public: |
29 BudgetPoolTest() {} | 31 BudgetPoolTest() {} |
30 ~BudgetPoolTest() override {} | 32 ~BudgetPoolTest() override {} |
31 | 33 |
32 void SetUp() override { | 34 void SetUp() override { |
33 clock_.reset(new base::SimpleTestTickClock()); | 35 clock_.reset(new base::SimpleTestTickClock()); |
34 clock_->Advance(base::TimeDelta::FromMicroseconds(5000)); | 36 clock_->Advance(base::TimeDelta::FromMicroseconds(5000)); |
35 mock_task_runner_ = | 37 mock_task_runner_ = |
36 make_scoped_refptr(new cc::OrderedSimpleTaskRunner(clock_.get(), true)); | 38 make_scoped_refptr(new cc::OrderedSimpleTaskRunner(clock_.get(), true)); |
37 delegate_ = SchedulerTqmDelegateForTest::Create( | 39 delegate_ = SchedulerTqmDelegateForTest::Create( |
38 mock_task_runner_, base::MakeUnique<TestTimeSource>(clock_.get())); | 40 mock_task_runner_, base::MakeUnique<TestTimeSource>(clock_.get())); |
39 scheduler_.reset(new RendererSchedulerImpl(delegate_)); | 41 scheduler_.reset(new RendererSchedulerImpl(delegate_)); |
40 task_queue_throttler_ = scheduler_->task_queue_throttler(); | 42 task_queue_throttler_ = scheduler_->task_queue_throttler(); |
| 43 start_time_ = clock_->NowTicks(); |
41 } | 44 } |
42 | 45 |
43 void TearDown() override { | 46 void TearDown() override { |
44 scheduler_->Shutdown(); | 47 scheduler_->Shutdown(); |
45 scheduler_.reset(); | 48 scheduler_.reset(); |
46 } | 49 } |
47 | 50 |
| 51 base::TimeTicks MillisecondsAfterStart(int milliseconds) { |
| 52 return start_time_ + base::TimeDelta::FromMilliseconds(milliseconds); |
| 53 } |
| 54 |
| 55 base::TimeTicks SecondsAfterStart(int seconds) { |
| 56 return start_time_ + base::TimeDelta::FromSeconds(seconds); |
| 57 } |
| 58 |
48 protected: | 59 protected: |
49 std::unique_ptr<base::SimpleTestTickClock> clock_; | 60 std::unique_ptr<base::SimpleTestTickClock> clock_; |
50 scoped_refptr<cc::OrderedSimpleTaskRunner> mock_task_runner_; | 61 scoped_refptr<cc::OrderedSimpleTaskRunner> mock_task_runner_; |
51 scoped_refptr<SchedulerTqmDelegate> delegate_; | 62 scoped_refptr<SchedulerTqmDelegate> delegate_; |
52 std::unique_ptr<RendererSchedulerImpl> scheduler_; | 63 std::unique_ptr<RendererSchedulerImpl> scheduler_; |
53 TaskQueueThrottler* task_queue_throttler_; // NOT OWNED | 64 TaskQueueThrottler* task_queue_throttler_; // NOT OWNED |
| 65 base::TimeTicks start_time_; |
54 | 66 |
55 DISALLOW_COPY_AND_ASSIGN(BudgetPoolTest); | 67 DISALLOW_COPY_AND_ASSIGN(BudgetPoolTest); |
56 }; | 68 }; |
57 | 69 |
58 TEST_F(BudgetPoolTest, CPUTimeBudgetPool) { | 70 TEST_F(BudgetPoolTest, CPUTimeBudgetPool) { |
59 CPUTimeBudgetPool* pool = | 71 CPUTimeBudgetPool* pool = |
60 task_queue_throttler_->CreateCPUTimeBudgetPool("test"); | 72 task_queue_throttler_->CreateCPUTimeBudgetPool("test"); |
61 | 73 |
62 base::TimeTicks time_zero = clock_->NowTicks(); | 74 pool->SetTimeBudgetRecoveryRate(SecondsAfterStart(0), 0.1); |
63 | 75 |
64 pool->SetTimeBudgetRecoveryRate(time_zero, 0.1); | 76 EXPECT_TRUE(pool->CanRunTasksAt(SecondsAfterStart(0), false)); |
65 | 77 EXPECT_EQ(SecondsAfterStart(0), |
66 EXPECT_TRUE(pool->HasEnoughBudgetToRun(time_zero)); | 78 pool->GetNextAllowedRunTime(SecondsAfterStart(0))); |
67 EXPECT_EQ(time_zero, pool->GetNextAllowedRunTime()); | |
68 | 79 |
69 // Run an expensive task and make sure that we're throttled. | 80 // Run an expensive task and make sure that we're throttled. |
70 pool->RecordTaskRunTime(time_zero, | 81 pool->RecordTaskRunTime(nullptr, SecondsAfterStart(0), |
71 time_zero + base::TimeDelta::FromMilliseconds(100)); | 82 MillisecondsAfterStart(100)); |
72 | 83 |
73 EXPECT_FALSE(pool->HasEnoughBudgetToRun( | 84 EXPECT_FALSE(pool->CanRunTasksAt(MillisecondsAfterStart(500), false)); |
74 time_zero + base::TimeDelta::FromMilliseconds(500))); | 85 EXPECT_EQ(MillisecondsAfterStart(1000), |
75 EXPECT_EQ(time_zero + base::TimeDelta::FromMilliseconds(1000), | 86 pool->GetNextAllowedRunTime(SecondsAfterStart(0))); |
76 pool->GetNextAllowedRunTime()); | 87 EXPECT_TRUE(pool->CanRunTasksAt(MillisecondsAfterStart(1000), false)); |
77 EXPECT_TRUE(pool->HasEnoughBudgetToRun( | |
78 time_zero + base::TimeDelta::FromMilliseconds(1000))); | |
79 | 88 |
80 // Run a cheap task and make sure that it doesn't affect anything. | 89 // Run a cheap task and make sure that it doesn't affect anything. |
81 EXPECT_TRUE(pool->HasEnoughBudgetToRun( | 90 EXPECT_TRUE(pool->CanRunTasksAt(MillisecondsAfterStart(2000), false)); |
82 time_zero + base::TimeDelta::FromMilliseconds(2000))); | 91 pool->RecordTaskRunTime(nullptr, MillisecondsAfterStart(2000), |
83 pool->RecordTaskRunTime(time_zero + base::TimeDelta::FromMilliseconds(2000), | 92 MillisecondsAfterStart(2020)); |
84 time_zero + base::TimeDelta::FromMilliseconds(2020)); | 93 EXPECT_TRUE(pool->CanRunTasksAt(MillisecondsAfterStart(2020), false)); |
85 EXPECT_TRUE(pool->HasEnoughBudgetToRun( | 94 EXPECT_EQ(MillisecondsAfterStart(2020), |
86 time_zero + base::TimeDelta::FromMilliseconds(2020))); | 95 pool->GetNextAllowedRunTime(SecondsAfterStart(0))); |
87 EXPECT_EQ(time_zero + base::TimeDelta::FromMilliseconds(2020), | |
88 pool->GetNextAllowedRunTime()); | |
89 | 96 |
90 pool->Close(); | 97 pool->Close(); |
91 } | 98 } |
92 | 99 |
93 TEST_F(BudgetPoolTest, CPUTimeBudgetPoolMinBudgetLevelToRun) { | 100 TEST_F(BudgetPoolTest, CPUTimeBudgetPoolMinBudgetLevelToRun) { |
94 CPUTimeBudgetPool* pool = | 101 CPUTimeBudgetPool* pool = |
95 task_queue_throttler_->CreateCPUTimeBudgetPool("test"); | 102 task_queue_throttler_->CreateCPUTimeBudgetPool("test"); |
96 | 103 |
97 base::TimeTicks time_zero = clock_->NowTicks(); | 104 pool->SetMinBudgetLevelToRun(SecondsAfterStart(0), |
| 105 base::TimeDelta::FromMilliseconds(10)); |
| 106 pool->SetTimeBudgetRecoveryRate(SecondsAfterStart(0), 0.1); |
98 | 107 |
99 pool->SetMinBudgetLevelToRun(time_zero, | 108 EXPECT_TRUE(pool->CanRunTasksAt(SecondsAfterStart(0), false)); |
100 base::TimeDelta::FromMilliseconds(10)); | 109 EXPECT_EQ(SecondsAfterStart(0), |
101 pool->SetTimeBudgetRecoveryRate(time_zero, 0.1); | 110 pool->GetNextAllowedRunTime(SecondsAfterStart(0))); |
102 | 111 |
103 EXPECT_TRUE(pool->HasEnoughBudgetToRun(time_zero)); | 112 pool->RecordTaskRunTime(nullptr, SecondsAfterStart(0), |
104 EXPECT_EQ(time_zero, pool->GetNextAllowedRunTime()); | 113 MillisecondsAfterStart(10)); |
| 114 EXPECT_FALSE(pool->CanRunTasksAt(MillisecondsAfterStart(15), false)); |
| 115 EXPECT_FALSE(pool->CanRunTasksAt(MillisecondsAfterStart(150), false)); |
| 116 // We need to wait extra 100ms to get budget of 10ms. |
| 117 EXPECT_EQ(MillisecondsAfterStart(200), |
| 118 pool->GetNextAllowedRunTime(SecondsAfterStart(0))); |
105 | 119 |
106 pool->RecordTaskRunTime(time_zero, | 120 pool->RecordTaskRunTime(nullptr, MillisecondsAfterStart(200), |
107 time_zero + base::TimeDelta::FromMilliseconds(10)); | 121 MillisecondsAfterStart(205)); |
108 EXPECT_FALSE(pool->HasEnoughBudgetToRun( | 122 // We can run when budget is non-negative even when it less than 10ms. |
109 time_zero + base::TimeDelta::FromMilliseconds(15))); | 123 EXPECT_EQ(MillisecondsAfterStart(205), |
110 EXPECT_FALSE(pool->HasEnoughBudgetToRun( | 124 pool->GetNextAllowedRunTime(SecondsAfterStart(0))); |
111 time_zero + base::TimeDelta::FromMilliseconds(150))); | |
112 // We need to wait extra 100ms to get budget of 10ms. | |
113 EXPECT_EQ(time_zero + base::TimeDelta::FromMilliseconds(200), | |
114 pool->GetNextAllowedRunTime()); | |
115 | 125 |
116 pool->RecordTaskRunTime(time_zero + base::TimeDelta::FromMilliseconds(200), | 126 pool->RecordTaskRunTime(nullptr, MillisecondsAfterStart(205), |
117 time_zero + base::TimeDelta::FromMilliseconds(205)); | 127 MillisecondsAfterStart(215)); |
118 // We can run when budget is non-negative even when it less than 10ms. | 128 EXPECT_EQ(MillisecondsAfterStart(350), |
119 EXPECT_EQ(time_zero + base::TimeDelta::FromMilliseconds(205), | 129 pool->GetNextAllowedRunTime(SecondsAfterStart(0))); |
120 pool->GetNextAllowedRunTime()); | 130 } |
121 | 131 |
122 pool->RecordTaskRunTime(time_zero + base::TimeDelta::FromMilliseconds(205), | 132 TEST_F(BudgetPoolTest, WakeUpBudgetPool) { |
123 time_zero + base::TimeDelta::FromMilliseconds(215)); | 133 WakeUpBudgetPool* pool = |
124 EXPECT_EQ(time_zero + base::TimeDelta::FromMilliseconds(350), | 134 task_queue_throttler_->CreateWakeUpBudgetPool("test"); |
125 pool->GetNextAllowedRunTime()); | 135 |
| 136 scoped_refptr<TaskQueue> queue = |
| 137 scheduler_->NewTimerTaskQueue(TaskQueue::QueueType::TEST); |
| 138 |
| 139 pool->SetWakeUpRate(0.1); |
| 140 pool->SetWakeUpDuration(base::TimeDelta::FromMilliseconds(10)); |
| 141 |
| 142 // Can't run tasks until a wake-up. |
| 143 EXPECT_FALSE(pool->CanRunTasksAt(MillisecondsAfterStart(0), false)); |
| 144 EXPECT_FALSE(pool->CanRunTasksAt(MillisecondsAfterStart(5), false)); |
| 145 EXPECT_FALSE(pool->CanRunTasksAt(MillisecondsAfterStart(9), false)); |
| 146 EXPECT_FALSE(pool->CanRunTasksAt(MillisecondsAfterStart(10), false)); |
| 147 EXPECT_FALSE(pool->CanRunTasksAt(MillisecondsAfterStart(11), false)); |
| 148 |
| 149 pool->OnWakeUp(MillisecondsAfterStart(0)); |
| 150 |
| 151 EXPECT_TRUE(pool->CanRunTasksAt(MillisecondsAfterStart(0), false)); |
| 152 EXPECT_TRUE(pool->CanRunTasksAt(MillisecondsAfterStart(5), false)); |
| 153 EXPECT_TRUE(pool->CanRunTasksAt(MillisecondsAfterStart(9), false)); |
| 154 EXPECT_FALSE(pool->CanRunTasksAt(MillisecondsAfterStart(10), false)); |
| 155 EXPECT_FALSE(pool->CanRunTasksAt(MillisecondsAfterStart(11), false)); |
| 156 |
| 157 // GetNextAllowedRunTime should return the desired time when in the |
| 158 // wakeup window and return the next wakeup otherwise. |
| 159 EXPECT_EQ(start_time_, pool->GetNextAllowedRunTime(start_time_)); |
| 160 EXPECT_EQ(SecondsAfterStart(10) - base::TimeDelta::FromMicroseconds(1), |
| 161 pool->GetNextAllowedRunTime(MillisecondsAfterStart(15))); |
| 162 |
| 163 pool->RecordTaskRunTime(queue.get(), MillisecondsAfterStart(5), |
| 164 MillisecondsAfterStart(7)); |
| 165 |
| 166 // Make sure that nothing changes after a task inside wakeup window. |
| 167 EXPECT_TRUE(pool->CanRunTasksAt(MillisecondsAfterStart(0), false)); |
| 168 EXPECT_TRUE(pool->CanRunTasksAt(MillisecondsAfterStart(5), false)); |
| 169 EXPECT_TRUE(pool->CanRunTasksAt(MillisecondsAfterStart(9), false)); |
| 170 EXPECT_FALSE(pool->CanRunTasksAt(MillisecondsAfterStart(10), false)); |
| 171 EXPECT_FALSE(pool->CanRunTasksAt(MillisecondsAfterStart(11), false)); |
| 172 EXPECT_EQ(start_time_, pool->GetNextAllowedRunTime(start_time_)); |
| 173 EXPECT_EQ(SecondsAfterStart(10) - base::TimeDelta::FromMicroseconds(1), |
| 174 pool->GetNextAllowedRunTime(MillisecondsAfterStart(15))); |
| 175 |
| 176 pool->OnWakeUp(MillisecondsAfterStart(12005)); |
| 177 pool->RecordTaskRunTime(queue.get(), MillisecondsAfterStart(12005), |
| 178 MillisecondsAfterStart(12007)); |
| 179 |
| 180 EXPECT_TRUE(pool->CanRunTasksAt(MillisecondsAfterStart(12005), false)); |
| 181 EXPECT_TRUE(pool->CanRunTasksAt(MillisecondsAfterStart(12007), false)); |
| 182 EXPECT_TRUE(pool->CanRunTasksAt(MillisecondsAfterStart(12014), false)); |
| 183 EXPECT_FALSE(pool->CanRunTasksAt(MillisecondsAfterStart(12015), false)); |
| 184 EXPECT_FALSE(pool->CanRunTasksAt(MillisecondsAfterStart(12016), false)); |
| 185 EXPECT_EQ( |
| 186 MillisecondsAfterStart(22005) - base::TimeDelta::FromMicroseconds(1), |
| 187 pool->GetNextAllowedRunTime(SecondsAfterStart(13))); |
126 } | 188 } |
127 | 189 |
128 } // namespace scheduler | 190 } // namespace scheduler |
129 } // namespace blink | 191 } // namespace blink |
OLD | NEW |