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

Side by Side Diff: third_party/WebKit/Source/platform/scheduler/renderer/throttling_helper_unittest.cc

Issue 2258133002: [scheduler] Implement time-based cpu throttling. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebased Created 4 years, 2 months 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
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "platform/scheduler/renderer/throttling_helper.h"
6
7 #include <stddef.h>
8
9 #include <memory>
10
11 #include "base/callback.h"
12 #include "base/macros.h"
13 #include "base/memory/ptr_util.h"
14 #include "base/test/simple_test_tick_clock.h"
15 #include "cc/test/ordered_simple_task_runner.h"
16 #include "platform/scheduler/base/test_time_source.h"
17 #include "platform/scheduler/base/real_time_domain.h"
18 #include "platform/scheduler/child/scheduler_tqm_delegate_for_test.h"
19 #include "platform/scheduler/renderer/auto_advancing_virtual_time_domain.h"
20 #include "platform/scheduler/renderer/renderer_scheduler_impl.h"
21 #include "platform/scheduler/renderer/web_frame_scheduler_impl.h"
22 #include "platform/scheduler/renderer/web_view_scheduler_impl.h"
23 #include "testing/gmock/include/gmock/gmock.h"
24 #include "testing/gtest/include/gtest/gtest.h"
25
26 using testing::ElementsAre;
27
28 namespace blink {
29 namespace scheduler {
30
31 namespace {
32 void RunTenTimesTask(size_t* count, scoped_refptr<TaskQueue> timer_queue) {
33 if (++(*count) < 10) {
34 timer_queue->PostTask(FROM_HERE,
35 base::Bind(&RunTenTimesTask, count, timer_queue));
36 }
37 }
38 }
39
40 class ThrottlingHelperTest : public testing::Test {
41 public:
42 ThrottlingHelperTest() {}
43 ~ThrottlingHelperTest() override {}
44
45 void SetUp() override {
46 clock_.reset(new base::SimpleTestTickClock());
47 clock_->Advance(base::TimeDelta::FromMicroseconds(5000));
48 mock_task_runner_ =
49 make_scoped_refptr(new cc::OrderedSimpleTaskRunner(clock_.get(), true));
50 delegate_ = SchedulerTqmDelegateForTest::Create(
51 mock_task_runner_, base::MakeUnique<TestTimeSource>(clock_.get()));
52 scheduler_.reset(new RendererSchedulerImpl(delegate_));
53 throttling_helper_ = scheduler_->throttling_helper();
54 timer_queue_ = scheduler_->NewTimerTaskRunner("test_queue");
55 }
56
57 void TearDown() override {
58 scheduler_->Shutdown();
59 scheduler_.reset();
60 }
61
62 void ExpectThrottled(scoped_refptr<TaskQueue> timer_queue) {
63 size_t count = 0;
64 timer_queue->PostTask(FROM_HERE,
65 base::Bind(&RunTenTimesTask, &count, timer_queue));
66
67 mock_task_runner_->RunForPeriod(base::TimeDelta::FromSeconds(1));
68 EXPECT_LE(count, 1u);
69
70 // Make sure the rest of the tasks run or we risk a UAF on |count|.
71 mock_task_runner_->RunForPeriod(base::TimeDelta::FromSeconds(10));
72 EXPECT_EQ(10u, count);
73 }
74
75 void ExpectUnthrottled(scoped_refptr<TaskQueue> timer_queue) {
76 size_t count = 0;
77 timer_queue->PostTask(FROM_HERE,
78 base::Bind(&RunTenTimesTask, &count, timer_queue));
79
80 mock_task_runner_->RunForPeriod(base::TimeDelta::FromSeconds(1));
81 EXPECT_EQ(10u, count);
82 mock_task_runner_->RunUntilIdle();
83 }
84
85 protected:
86 std::unique_ptr<base::SimpleTestTickClock> clock_;
87 scoped_refptr<cc::OrderedSimpleTaskRunner> mock_task_runner_;
88 scoped_refptr<SchedulerTqmDelegate> delegate_;
89 std::unique_ptr<RendererSchedulerImpl> scheduler_;
90 scoped_refptr<TaskQueue> timer_queue_;
91 ThrottlingHelper* throttling_helper_; // NOT OWNED
92
93 DISALLOW_COPY_AND_ASSIGN(ThrottlingHelperTest);
94 };
95
96 TEST_F(ThrottlingHelperTest, ThrottledRunTime) {
97 EXPECT_EQ(base::TimeTicks() + base::TimeDelta::FromSecondsD(1.0),
98 ThrottlingHelper::ThrottledRunTime(
99 base::TimeTicks() + base::TimeDelta::FromSecondsD(0.0)));
100
101 EXPECT_EQ(base::TimeTicks() + base::TimeDelta::FromSecondsD(1.0),
102 ThrottlingHelper::ThrottledRunTime(
103 base::TimeTicks() + base::TimeDelta::FromSecondsD(0.1)));
104
105 EXPECT_EQ(base::TimeTicks() + base::TimeDelta::FromSecondsD(1.0),
106 ThrottlingHelper::ThrottledRunTime(
107 base::TimeTicks() + base::TimeDelta::FromSecondsD(0.2)));
108
109 EXPECT_EQ(base::TimeTicks() + base::TimeDelta::FromSecondsD(1.0),
110 ThrottlingHelper::ThrottledRunTime(
111 base::TimeTicks() + base::TimeDelta::FromSecondsD(0.5)));
112
113 EXPECT_EQ(base::TimeTicks() + base::TimeDelta::FromSecondsD(1.0),
114 ThrottlingHelper::ThrottledRunTime(
115 base::TimeTicks() + base::TimeDelta::FromSecondsD(0.8)));
116
117 EXPECT_EQ(base::TimeTicks() + base::TimeDelta::FromSecondsD(1.0),
118 ThrottlingHelper::ThrottledRunTime(
119 base::TimeTicks() + base::TimeDelta::FromSecondsD(0.9)));
120
121 EXPECT_EQ(base::TimeTicks() + base::TimeDelta::FromSecondsD(2.0),
122 ThrottlingHelper::ThrottledRunTime(
123 base::TimeTicks() + base::TimeDelta::FromSecondsD(1.0)));
124
125 EXPECT_EQ(base::TimeTicks() + base::TimeDelta::FromSecondsD(2.0),
126 ThrottlingHelper::ThrottledRunTime(
127 base::TimeTicks() + base::TimeDelta::FromSecondsD(1.1)));
128
129 EXPECT_EQ(base::TimeTicks() + base::TimeDelta::FromSecondsD(9.0),
130 ThrottlingHelper::ThrottledRunTime(
131 base::TimeTicks() + base::TimeDelta::FromSecondsD(8.0)));
132
133 EXPECT_EQ(base::TimeTicks() + base::TimeDelta::FromSecondsD(9.0),
134 ThrottlingHelper::ThrottledRunTime(
135 base::TimeTicks() + base::TimeDelta::FromSecondsD(8.1)));
136 }
137
138 namespace {
139 void TestTask(std::vector<base::TimeTicks>* run_times,
140 base::SimpleTestTickClock* clock) {
141 run_times->push_back(clock->NowTicks());
142 }
143 } // namespace
144
145 TEST_F(ThrottlingHelperTest, TimerAlignment) {
146 std::vector<base::TimeTicks> run_times;
147 timer_queue_->PostDelayedTask(FROM_HERE,
148 base::Bind(&TestTask, &run_times, clock_.get()),
149 base::TimeDelta::FromMilliseconds(200.0));
150
151 timer_queue_->PostDelayedTask(FROM_HERE,
152 base::Bind(&TestTask, &run_times, clock_.get()),
153 base::TimeDelta::FromMilliseconds(800.0));
154
155 timer_queue_->PostDelayedTask(FROM_HERE,
156 base::Bind(&TestTask, &run_times, clock_.get()),
157 base::TimeDelta::FromMilliseconds(1200.0));
158
159 timer_queue_->PostDelayedTask(FROM_HERE,
160 base::Bind(&TestTask, &run_times, clock_.get()),
161 base::TimeDelta::FromMilliseconds(8300.0));
162
163 throttling_helper_->IncreaseThrottleRefCount(timer_queue_.get());
164
165 mock_task_runner_->RunUntilIdle();
166
167 // Times are aligned to a multipple of 1000 milliseconds.
168 EXPECT_THAT(
169 run_times,
170 ElementsAre(
171 base::TimeTicks() + base::TimeDelta::FromMilliseconds(1000.0),
172 base::TimeTicks() + base::TimeDelta::FromMilliseconds(1000.0),
173 base::TimeTicks() + base::TimeDelta::FromMilliseconds(2000.0),
174 base::TimeTicks() + base::TimeDelta::FromMilliseconds(9000.0)));
175 }
176
177 TEST_F(ThrottlingHelperTest, TimerAlignment_Unthrottled) {
178 std::vector<base::TimeTicks> run_times;
179 base::TimeTicks start_time = clock_->NowTicks();
180 timer_queue_->PostDelayedTask(FROM_HERE,
181 base::Bind(&TestTask, &run_times, clock_.get()),
182 base::TimeDelta::FromMilliseconds(200.0));
183
184 timer_queue_->PostDelayedTask(FROM_HERE,
185 base::Bind(&TestTask, &run_times, clock_.get()),
186 base::TimeDelta::FromMilliseconds(800.0));
187
188 timer_queue_->PostDelayedTask(FROM_HERE,
189 base::Bind(&TestTask, &run_times, clock_.get()),
190 base::TimeDelta::FromMilliseconds(1200.0));
191
192 timer_queue_->PostDelayedTask(FROM_HERE,
193 base::Bind(&TestTask, &run_times, clock_.get()),
194 base::TimeDelta::FromMilliseconds(8300.0));
195
196 throttling_helper_->IncreaseThrottleRefCount(timer_queue_.get());
197 throttling_helper_->DecreaseThrottleRefCount(timer_queue_.get());
198
199 mock_task_runner_->RunUntilIdle();
200
201 // Times are not aligned.
202 EXPECT_THAT(
203 run_times,
204 ElementsAre(start_time + base::TimeDelta::FromMilliseconds(200.0),
205 start_time + base::TimeDelta::FromMilliseconds(800.0),
206 start_time + base::TimeDelta::FromMilliseconds(1200.0),
207 start_time + base::TimeDelta::FromMilliseconds(8300.0)));
208 }
209
210 TEST_F(ThrottlingHelperTest, Refcount) {
211 ExpectUnthrottled(timer_queue_.get());
212
213 throttling_helper_->IncreaseThrottleRefCount(timer_queue_.get());
214 ExpectThrottled(timer_queue_);
215
216 throttling_helper_->IncreaseThrottleRefCount(timer_queue_.get());
217 ExpectThrottled(timer_queue_);
218
219 throttling_helper_->DecreaseThrottleRefCount(timer_queue_.get());
220 ExpectThrottled(timer_queue_);
221
222 throttling_helper_->DecreaseThrottleRefCount(timer_queue_.get());
223 ExpectUnthrottled(timer_queue_);
224
225 // Should be a NOP.
226 throttling_helper_->DecreaseThrottleRefCount(timer_queue_.get());
227 ExpectUnthrottled(timer_queue_);
228
229 throttling_helper_->IncreaseThrottleRefCount(timer_queue_.get());
230 ExpectThrottled(timer_queue_);
231 }
232
233 TEST_F(ThrottlingHelperTest,
234 ThrotlingAnEmptyQueueDoesNotPostPumpThrottledTasksLocked) {
235 throttling_helper_->IncreaseThrottleRefCount(timer_queue_.get());
236
237 EXPECT_TRUE(throttling_helper_->task_runner()->IsEmpty());
238 }
239
240 TEST_F(ThrottlingHelperTest, WakeUpForNonDelayedTask) {
241 std::vector<base::TimeTicks> run_times;
242
243 // Nothing is posted on timer_queue_ so PumpThrottledTasks will not tick.
244 throttling_helper_->IncreaseThrottleRefCount(timer_queue_.get());
245
246 // Posting a task should trigger the pump.
247 timer_queue_->PostTask(FROM_HERE,
248 base::Bind(&TestTask, &run_times, clock_.get()));
249
250 mock_task_runner_->RunUntilIdle();
251 EXPECT_THAT(run_times,
252 ElementsAre(base::TimeTicks() +
253 base::TimeDelta::FromMilliseconds(1000.0)));
254 }
255
256 TEST_F(ThrottlingHelperTest, WakeUpForDelayedTask) {
257 std::vector<base::TimeTicks> run_times;
258
259 // Nothing is posted on timer_queue_ so PumpThrottledTasks will not tick.
260 throttling_helper_->IncreaseThrottleRefCount(timer_queue_.get());
261
262 // Posting a task should trigger the pump.
263 timer_queue_->PostDelayedTask(FROM_HERE,
264 base::Bind(&TestTask, &run_times, clock_.get()),
265 base::TimeDelta::FromMilliseconds(1200.0));
266
267 mock_task_runner_->RunUntilIdle();
268 EXPECT_THAT(run_times,
269 ElementsAre(base::TimeTicks() +
270 base::TimeDelta::FromMilliseconds(2000.0)));
271 }
272
273 namespace {
274 bool MessageLoopTaskCounter(size_t* count) {
275 *count = *count + 1;
276 return true;
277 }
278
279 void NopTask() {}
280
281 void AddOneTask(size_t* count) {
282 (*count)++;
283 }
284
285 } // namespace
286
287 TEST_F(ThrottlingHelperTest,
288 SingleThrottledTaskPumpedAndRunWithNoExtraneousMessageLoopTasks) {
289 throttling_helper_->IncreaseThrottleRefCount(timer_queue_.get());
290
291 base::TimeDelta delay(base::TimeDelta::FromMilliseconds(10));
292 timer_queue_->PostDelayedTask(FROM_HERE, base::Bind(&NopTask), delay);
293
294 size_t task_count = 0;
295 mock_task_runner_->RunTasksWhile(
296 base::Bind(&MessageLoopTaskCounter, &task_count));
297
298 // Run the task.
299 EXPECT_EQ(1u, task_count);
300 }
301
302 TEST_F(ThrottlingHelperTest,
303 SingleFutureThrottledTaskPumpedAndRunWithNoExtraneousMessageLoopTasks) {
304 throttling_helper_->IncreaseThrottleRefCount(timer_queue_.get());
305
306 base::TimeDelta delay(base::TimeDelta::FromSecondsD(15.5));
307 timer_queue_->PostDelayedTask(FROM_HERE, base::Bind(&NopTask), delay);
308
309 size_t task_count = 0;
310 mock_task_runner_->RunTasksWhile(
311 base::Bind(&MessageLoopTaskCounter, &task_count));
312
313 // Run the delayed task.
314 EXPECT_EQ(1u, task_count);
315 }
316
317 TEST_F(ThrottlingHelperTest,
318 TwoFutureThrottledTaskPumpedAndRunWithNoExtraneousMessageLoopTasks) {
319 throttling_helper_->IncreaseThrottleRefCount(timer_queue_.get());
320 std::vector<base::TimeTicks> run_times;
321
322 base::TimeDelta delay(base::TimeDelta::FromSecondsD(15.5));
323 timer_queue_->PostDelayedTask(
324 FROM_HERE, base::Bind(&TestTask, &run_times, clock_.get()), delay);
325
326 base::TimeDelta delay2(base::TimeDelta::FromSecondsD(5.5));
327 timer_queue_->PostDelayedTask(
328 FROM_HERE, base::Bind(&TestTask, &run_times, clock_.get()), delay2);
329
330 size_t task_count = 0;
331 mock_task_runner_->RunTasksWhile(
332 base::Bind(&MessageLoopTaskCounter, &task_count));
333
334 // Run both delayed tasks.
335 EXPECT_EQ(2u, task_count);
336
337 EXPECT_THAT(
338 run_times,
339 ElementsAre(base::TimeTicks() + base::TimeDelta::FromSeconds(6),
340 base::TimeTicks() + base::TimeDelta::FromSeconds(16)));
341 }
342
343 TEST_F(ThrottlingHelperTest, TaskDelayIsBasedOnRealTime) {
344 std::vector<base::TimeTicks> run_times;
345
346 throttling_helper_->IncreaseThrottleRefCount(timer_queue_.get());
347
348 // Post an initial task that should run at the first aligned time period.
349 timer_queue_->PostDelayedTask(FROM_HERE,
350 base::Bind(&TestTask, &run_times, clock_.get()),
351 base::TimeDelta::FromMilliseconds(900.0));
352
353 mock_task_runner_->RunUntilIdle();
354
355 // Advance realtime.
356 clock_->Advance(base::TimeDelta::FromMilliseconds(250));
357
358 // Post a task that due to real time + delay must run in the third aligned
359 // time period.
360 timer_queue_->PostDelayedTask(FROM_HERE,
361 base::Bind(&TestTask, &run_times, clock_.get()),
362 base::TimeDelta::FromMilliseconds(900.0));
363
364 mock_task_runner_->RunUntilIdle();
365
366 EXPECT_THAT(
367 run_times,
368 ElementsAre(
369 base::TimeTicks() + base::TimeDelta::FromMilliseconds(1000.0),
370 base::TimeTicks() + base::TimeDelta::FromMilliseconds(3000.0)));
371 }
372
373 TEST_F(ThrottlingHelperTest, ThrottledTasksReportRealTime) {
374 EXPECT_EQ(timer_queue_->GetTimeDomain()->Now(), clock_->NowTicks());
375
376 throttling_helper_->IncreaseThrottleRefCount(timer_queue_.get());
377 EXPECT_EQ(timer_queue_->GetTimeDomain()->Now(), clock_->NowTicks());
378
379 clock_->Advance(base::TimeDelta::FromMilliseconds(250));
380 // Make sure the throttled time domain's Now() reports the same as the
381 // underlying clock.
382 EXPECT_EQ(timer_queue_->GetTimeDomain()->Now(), clock_->NowTicks());
383 }
384
385 TEST_F(ThrottlingHelperTest, TaskQueueDisabledTillPump) {
386 size_t count = 0;
387 timer_queue_->PostTask(FROM_HERE, base::Bind(&AddOneTask, &count));
388
389 EXPECT_TRUE(timer_queue_->IsQueueEnabled());
390 throttling_helper_->IncreaseThrottleRefCount(timer_queue_.get());
391 EXPECT_FALSE(timer_queue_->IsQueueEnabled());
392
393 mock_task_runner_->RunUntilIdle(); // Wait until the pump.
394 EXPECT_EQ(1u, count); // The task got run
395 EXPECT_TRUE(timer_queue_->IsQueueEnabled());
396 }
397
398 TEST_F(ThrottlingHelperTest, TaskQueueUnthrottle_InitiallyEnabled) {
399 timer_queue_->PostTask(FROM_HERE, base::Bind(&NopTask));
400
401 timer_queue_->SetQueueEnabled(true); // NOP
402 throttling_helper_->IncreaseThrottleRefCount(timer_queue_.get());
403 EXPECT_FALSE(timer_queue_->IsQueueEnabled());
404
405 throttling_helper_->DecreaseThrottleRefCount(timer_queue_.get());
406 EXPECT_TRUE(timer_queue_->IsQueueEnabled());
407 }
408
409 TEST_F(ThrottlingHelperTest, TaskQueueUnthrottle_InitiallyDisabled) {
410 timer_queue_->PostTask(FROM_HERE, base::Bind(&NopTask));
411
412 timer_queue_->SetQueueEnabled(false);
413 throttling_helper_->IncreaseThrottleRefCount(timer_queue_.get());
414 EXPECT_FALSE(timer_queue_->IsQueueEnabled());
415
416 throttling_helper_->DecreaseThrottleRefCount(timer_queue_.get());
417 EXPECT_FALSE(timer_queue_->IsQueueEnabled());
418 }
419
420 TEST_F(ThrottlingHelperTest, SetQueueEnabled_Unthrottled) {
421 timer_queue_->PostTask(FROM_HERE, base::Bind(&NopTask));
422
423 throttling_helper_->SetQueueEnabled(timer_queue_.get(), false);
424 EXPECT_FALSE(timer_queue_->IsQueueEnabled());
425
426 throttling_helper_->SetQueueEnabled(timer_queue_.get(), true);
427 EXPECT_TRUE(timer_queue_->IsQueueEnabled());
428 }
429
430 TEST_F(ThrottlingHelperTest, SetQueueEnabled_DisabledWhileThrottled) {
431 timer_queue_->PostTask(FROM_HERE, base::Bind(&NopTask));
432
433 throttling_helper_->IncreaseThrottleRefCount(timer_queue_.get());
434 EXPECT_FALSE(timer_queue_->IsQueueEnabled());
435
436 throttling_helper_->SetQueueEnabled(timer_queue_.get(), false);
437 throttling_helper_->DecreaseThrottleRefCount(timer_queue_.get());
438 EXPECT_FALSE(timer_queue_->IsQueueEnabled());
439 }
440
441 TEST_F(ThrottlingHelperTest, TaskQueueDisabledTillPump_ThenManuallyDisabled) {
442 size_t count = 0;
443 timer_queue_->PostTask(FROM_HERE, base::Bind(&AddOneTask, &count));
444
445 EXPECT_TRUE(timer_queue_->IsQueueEnabled());
446 throttling_helper_->IncreaseThrottleRefCount(timer_queue_.get());
447 EXPECT_FALSE(timer_queue_->IsQueueEnabled());
448
449 mock_task_runner_->RunUntilIdle(); // Wait until the pump.
450 EXPECT_EQ(1u, count); // Task ran
451 EXPECT_TRUE(timer_queue_->IsQueueEnabled());
452
453 throttling_helper_->SetQueueEnabled(timer_queue_.get(), false);
454 EXPECT_FALSE(timer_queue_->IsQueueEnabled());
455 }
456
457 TEST_F(ThrottlingHelperTest, DoubleIncrementDoubleDecrement) {
458 timer_queue_->PostTask(FROM_HERE, base::Bind(&NopTask));
459
460 EXPECT_TRUE(timer_queue_->IsQueueEnabled());
461 throttling_helper_->IncreaseThrottleRefCount(timer_queue_.get());
462 throttling_helper_->IncreaseThrottleRefCount(timer_queue_.get());
463 EXPECT_FALSE(timer_queue_->IsQueueEnabled());
464 throttling_helper_->DecreaseThrottleRefCount(timer_queue_.get());
465 throttling_helper_->DecreaseThrottleRefCount(timer_queue_.get());
466 EXPECT_TRUE(timer_queue_->IsQueueEnabled());
467 }
468
469 TEST_F(ThrottlingHelperTest, EnableVirtualTimeThenIncrement) {
470 timer_queue_->PostTask(FROM_HERE, base::Bind(&NopTask));
471
472 scheduler_->EnableVirtualTime();
473 EXPECT_EQ(timer_queue_->GetTimeDomain(), scheduler_->GetVirtualTimeDomain());
474
475 EXPECT_TRUE(timer_queue_->IsQueueEnabled());
476 throttling_helper_->IncreaseThrottleRefCount(timer_queue_.get());
477 EXPECT_TRUE(timer_queue_->IsQueueEnabled());
478 EXPECT_EQ(timer_queue_->GetTimeDomain(), scheduler_->GetVirtualTimeDomain());
479 }
480
481 TEST_F(ThrottlingHelperTest, IncrementThenEnableVirtualTime) {
482 timer_queue_->PostTask(FROM_HERE, base::Bind(&NopTask));
483
484 EXPECT_TRUE(timer_queue_->IsQueueEnabled());
485 throttling_helper_->IncreaseThrottleRefCount(timer_queue_.get());
486 EXPECT_FALSE(timer_queue_->IsQueueEnabled());
487
488 scheduler_->EnableVirtualTime();
489 EXPECT_TRUE(timer_queue_->IsQueueEnabled());
490 EXPECT_EQ(timer_queue_->GetTimeDomain(), scheduler_->GetVirtualTimeDomain());
491 }
492
493 } // namespace scheduler
494 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698