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/bind.h" | 7 #include "base/bind.h" |
8 #include "base/message_loop/message_loop_proxy.h" | 8 #include "base/message_loop/message_loop_proxy.h" |
9 #include "base/trace_event/trace_event.h" | 9 #include "base/trace_event/trace_event.h" |
10 #include "base/trace_event/trace_event_argument.h" | 10 #include "base/trace_event/trace_event_argument.h" |
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
131 | 131 |
132 void RendererSchedulerImpl::DidCommitFrameToCompositor() { | 132 void RendererSchedulerImpl::DidCommitFrameToCompositor() { |
133 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), | 133 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), |
134 "RendererSchedulerImpl::DidCommitFrameToCompositor"); | 134 "RendererSchedulerImpl::DidCommitFrameToCompositor"); |
135 DCHECK(main_thread_checker_.CalledOnValidThread()); | 135 DCHECK(main_thread_checker_.CalledOnValidThread()); |
136 if (!task_queue_manager_) | 136 if (!task_queue_manager_) |
137 return; | 137 return; |
138 | 138 |
139 base::TimeTicks now(Now()); | 139 base::TimeTicks now(Now()); |
140 if (now < estimated_next_frame_begin_) { | 140 if (now < estimated_next_frame_begin_) { |
141 StartIdlePeriod(); | 141 StartIdlePeriod(IdlePeriodState::WITHIN_IDLE_PERIOD); |
142 control_task_runner_->PostDelayedTask(FROM_HERE, | 142 control_task_runner_->PostDelayedTask(FROM_HERE, |
143 end_idle_period_closure_.callback(), | 143 end_idle_period_closure_.callback(), |
144 estimated_next_frame_begin_ - now); | 144 estimated_next_frame_begin_ - now); |
145 } | 145 } |
146 } | 146 } |
147 | 147 |
148 void RendererSchedulerImpl::BeginFrameNotExpectedSoon() { | 148 void RendererSchedulerImpl::BeginFrameNotExpectedSoon() { |
149 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), | 149 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), |
150 "RendererSchedulerImpl::BeginFrameNotExpectedSoon"); | 150 "RendererSchedulerImpl::BeginFrameNotExpectedSoon"); |
151 DCHECK(main_thread_checker_.CalledOnValidThread()); | 151 DCHECK(main_thread_checker_.CalledOnValidThread()); |
(...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
387 // Otherwise make sure the input prioritization policy ends on time. | 387 // Otherwise make sure the input prioritization policy ends on time. |
388 base::TimeTicks new_priority_end( | 388 base::TimeTicks new_priority_end( |
389 std::max(last_input_receipt_time_on_compositor_, | 389 std::max(last_input_receipt_time_on_compositor_, |
390 last_input_process_time_on_main_) + | 390 last_input_process_time_on_main_) + |
391 escalated_priority_duration); | 391 escalated_priority_duration); |
392 time_left_in_policy = new_priority_end - Now(); | 392 time_left_in_policy = new_priority_end - Now(); |
393 } | 393 } |
394 return time_left_in_policy; | 394 return time_left_in_policy; |
395 } | 395 } |
396 | 396 |
397 bool RendererSchedulerImpl::ShouldStartLongIdlePeriod( | 397 RendererSchedulerImpl::IdlePeriodState |
398 RendererSchedulerImpl::ComputeNewLongIdlePeriodState( | |
398 const base::TimeTicks now, | 399 const base::TimeTicks now, |
399 base::TimeDelta* next_long_idle_period_delay_out) { | 400 base::TimeDelta* next_long_idle_period_delay_out) { |
400 DCHECK(main_thread_checker_.CalledOnValidThread()); | 401 DCHECK(main_thread_checker_.CalledOnValidThread()); |
401 | 402 |
402 MaybeUpdatePolicy(); | 403 MaybeUpdatePolicy(); |
403 if (SchedulerPolicy() == Policy::TOUCHSTART_PRIORITY) { | 404 if (SchedulerPolicy() == Policy::TOUCHSTART_PRIORITY) { |
404 // Don't start a long idle task in touch start priority, try again when | 405 // Don't start a long idle task in touch start priority, try again when |
405 // the policy is scheduled to end. | 406 // the policy is scheduled to end. |
406 *next_long_idle_period_delay_out = current_policy_expiration_time_ - now; | 407 *next_long_idle_period_delay_out = current_policy_expiration_time_ - now; |
407 return false; | 408 return IdlePeriodState::NOT_WITHIN_IDLE_PERIOD; |
408 } | 409 } |
409 | 410 |
410 base::TimeTicks next_pending_delayed_task = | 411 base::TimeTicks next_pending_delayed_task = |
411 task_queue_manager_->NextPendingDelayedTaskRunTime(); | 412 task_queue_manager_->NextPendingDelayedTaskRunTime(); |
412 | 413 base::TimeDelta max_long_idle_period_duration = |
413 base::TimeDelta long_idle_period_duration = | |
414 base::TimeDelta::FromMilliseconds(kMaximumIdlePeriodMillis); | 414 base::TimeDelta::FromMilliseconds(kMaximumIdlePeriodMillis); |
415 base::TimeDelta long_idle_period_duration; | |
415 if (!next_pending_delayed_task.is_null()) { | 416 if (!next_pending_delayed_task.is_null()) { |
416 // Limit the idle period duration to be before the next pending task. | 417 // Limit the idle period duration to be before the next pending task. |
417 long_idle_period_duration = std::min( | 418 long_idle_period_duration = std::min( |
418 next_pending_delayed_task - now, long_idle_period_duration); | 419 next_pending_delayed_task - now, max_long_idle_period_duration); |
420 } else { | |
421 long_idle_period_duration = max_long_idle_period_duration; | |
419 } | 422 } |
420 | 423 |
421 if (long_idle_period_duration > base::TimeDelta()) { | 424 if (long_idle_period_duration > base::TimeDelta()) { |
422 *next_long_idle_period_delay_out = long_idle_period_duration; | 425 *next_long_idle_period_delay_out = long_idle_period_duration; |
423 return true; | 426 return long_idle_period_duration == max_long_idle_period_duration ? |
427 IdlePeriodState::WITHIN_MAX_DEADLINE_IDLE_PERIOD: | |
428 IdlePeriodState::WITHIN_IDLE_PERIOD; | |
424 } else { | 429 } else { |
425 // If we can't start the idle period yet then try again after wakeup. | 430 // If we can't start the idle period yet then try again after wakeup. |
426 *next_long_idle_period_delay_out = base::TimeDelta::FromMilliseconds( | 431 *next_long_idle_period_delay_out = base::TimeDelta::FromMilliseconds( |
427 kRetryInitiateLongIdlePeriodDelayMillis); | 432 kRetryInitiateLongIdlePeriodDelayMillis); |
428 return false; | 433 return IdlePeriodState::NOT_WITHIN_IDLE_PERIOD; |
429 } | 434 } |
430 } | 435 } |
431 | 436 |
432 void RendererSchedulerImpl::InitiateLongIdlePeriod() { | 437 void RendererSchedulerImpl::InitiateLongIdlePeriod() { |
433 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), | 438 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), |
434 "InitiateLongIdlePeriod"); | 439 "InitiateLongIdlePeriod"); |
435 DCHECK(main_thread_checker_.CalledOnValidThread()); | 440 DCHECK(main_thread_checker_.CalledOnValidThread()); |
436 | 441 |
437 // End any previous idle period. | 442 // End any previous idle period. |
438 EndIdlePeriod(); | 443 EndIdlePeriod(); |
439 | 444 |
440 base::TimeTicks now(Now()); | 445 base::TimeTicks now(Now()); |
441 base::TimeDelta next_long_idle_period_delay; | 446 base::TimeDelta next_long_idle_period_delay; |
442 if (ShouldStartLongIdlePeriod(now, &next_long_idle_period_delay)) { | 447 IdlePeriodState new_idle_period_state = ComputeNewLongIdlePeriodState( |
448 now, &next_long_idle_period_delay); | |
449 if (new_idle_period_state != IdlePeriodState::NOT_WITHIN_IDLE_PERIOD) { | |
443 estimated_next_frame_begin_ = now + next_long_idle_period_delay; | 450 estimated_next_frame_begin_ = now + next_long_idle_period_delay; |
444 StartIdlePeriod(); | 451 StartIdlePeriod(new_idle_period_state); |
445 } | 452 } |
446 | 453 |
447 if (task_queue_manager_->IsQueueEmpty(IDLE_TASK_QUEUE)) { | 454 if (task_queue_manager_->IsQueueEmpty(IDLE_TASK_QUEUE)) { |
448 // If there are no current idle tasks then post the call to initiate the | 455 // If there are no current idle tasks then post the call to initiate the |
449 // next idle for execution after wakeup (at which point after-wakeup idle | 456 // next idle for execution after wakeup (at which point after-wakeup idle |
450 // tasks might be eligible to run or more idle tasks posted). | 457 // tasks might be eligible to run or more idle tasks posted). |
451 control_task_after_wakeup_runner_->PostDelayedTask( | 458 control_task_after_wakeup_runner_->PostDelayedTask( |
452 FROM_HERE, | 459 FROM_HERE, |
453 after_wakeup_initiate_next_long_idle_period_closure_.callback(), | 460 after_wakeup_initiate_next_long_idle_period_closure_.callback(), |
454 next_long_idle_period_delay); | 461 next_long_idle_period_delay); |
455 } else { | 462 } else { |
456 // Otherwise post on the normal control task queue. | 463 // Otherwise post on the normal control task queue. |
457 control_task_runner_->PostDelayedTask( | 464 control_task_runner_->PostDelayedTask( |
458 FROM_HERE, | 465 FROM_HERE, |
459 initiate_next_long_idle_period_closure_.callback(), | 466 initiate_next_long_idle_period_closure_.callback(), |
460 next_long_idle_period_delay); | 467 next_long_idle_period_delay); |
461 } | 468 } |
462 } | 469 } |
463 | 470 |
464 void RendererSchedulerImpl::InitiateLongIdlePeriodAfterWakeup() { | 471 void RendererSchedulerImpl::InitiateLongIdlePeriodAfterWakeup() { |
465 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), | 472 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), |
466 "AfterWakeupInitiateLongIdlePeriod"); | 473 "AfterWakeupInitiateLongIdlePeriod"); |
467 DCHECK(main_thread_checker_.CalledOnValidThread()); | 474 DCHECK(main_thread_checker_.CalledOnValidThread()); |
468 | 475 |
469 if (in_idle_period_) { | 476 if (idle_period_state_ != IdlePeriodState::NOT_WITHIN_IDLE_PERIOD) { |
Sami
2015/03/05 11:59:32
Should we still mark the async event as ended here
rmcilroy
2015/03/05 13:50:19
No (for the reasons discussed on the other CL).
| |
470 // Since we were asleep until now, end the async idle period trace event at | 477 // Since we were asleep until now, end the async idle period trace event at |
471 // the time when it would have ended were we awake. | 478 // the time when it would have ended were we awake. |
472 TRACE_EVENT_ASYNC_END_WITH_TIMESTAMP0( | 479 TRACE_EVENT_ASYNC_END_WITH_TIMESTAMP0( |
473 "renderer.scheduler", "RendererSchedulerIdlePeriod", this, | 480 "renderer.scheduler", "RendererSchedulerIdlePeriod", this, |
474 std::min(estimated_next_frame_begin_, Now()).ToInternalValue()); | 481 std::min(estimated_next_frame_begin_, Now()).ToInternalValue()); |
475 } | 482 } |
476 | 483 |
477 // Post a task to initiate the next long idle period rather than calling it | 484 // Post a task to initiate the next long idle period rather than calling it |
478 // directly to allow all pending PostIdleTaskAfterWakeup tasks to get enqueued | 485 // directly to allow all pending PostIdleTaskAfterWakeup tasks to get enqueued |
479 // on the idle task queue before the next idle period starts so they are | 486 // on the idle task queue before the next idle period starts so they are |
480 // eligible to be run during the new idle period. | 487 // eligible to be run during the new idle period. |
481 control_task_runner_->PostTask( | 488 control_task_runner_->PostTask( |
482 FROM_HERE, | 489 FROM_HERE, |
483 initiate_next_long_idle_period_closure_.callback()); | 490 initiate_next_long_idle_period_closure_.callback()); |
484 } | 491 } |
485 | 492 |
486 void RendererSchedulerImpl::StartIdlePeriod() { | 493 void RendererSchedulerImpl::StartIdlePeriod(IdlePeriodState new_state) { |
487 TRACE_EVENT_ASYNC_BEGIN0("renderer.scheduler", | 494 TRACE_EVENT_ASYNC_BEGIN0("renderer.scheduler", |
488 "RendererSchedulerIdlePeriod", this); | 495 "RendererSchedulerIdlePeriod", this); |
489 DCHECK(main_thread_checker_.CalledOnValidThread()); | 496 DCHECK(main_thread_checker_.CalledOnValidThread()); |
497 // TODO(rmcilroy): Change this to DCHECK_EQ when crbug.com/463869 is fixed. | |
498 DCHECK(new_state != IdlePeriodState::NOT_WITHIN_IDLE_PERIOD); | |
499 idle_period_state_ = new_state; | |
490 renderer_task_queue_selector_->EnableQueue( | 500 renderer_task_queue_selector_->EnableQueue( |
491 IDLE_TASK_QUEUE, RendererTaskQueueSelector::BEST_EFFORT_PRIORITY); | 501 IDLE_TASK_QUEUE, RendererTaskQueueSelector::BEST_EFFORT_PRIORITY); |
492 task_queue_manager_->PumpQueue(IDLE_TASK_QUEUE); | 502 task_queue_manager_->PumpQueue(IDLE_TASK_QUEUE); |
493 in_idle_period_ = true; | |
494 } | 503 } |
495 | 504 |
496 void RendererSchedulerImpl::EndIdlePeriod() { | 505 void RendererSchedulerImpl::EndIdlePeriod() { |
497 DCHECK(main_thread_checker_.CalledOnValidThread()); | 506 DCHECK(main_thread_checker_.CalledOnValidThread()); |
498 | 507 |
499 end_idle_period_closure_.Cancel(); | 508 end_idle_period_closure_.Cancel(); |
500 initiate_next_long_idle_period_closure_.Cancel(); | 509 initiate_next_long_idle_period_closure_.Cancel(); |
501 after_wakeup_initiate_next_long_idle_period_closure_.Cancel(); | 510 after_wakeup_initiate_next_long_idle_period_closure_.Cancel(); |
502 | 511 |
503 if (!in_idle_period_) | 512 if (idle_period_state_ == IdlePeriodState::NOT_WITHIN_IDLE_PERIOD) |
504 return; | 513 return; |
505 | 514 |
515 idle_period_state_ = IdlePeriodState::NOT_WITHIN_IDLE_PERIOD; | |
506 renderer_task_queue_selector_->DisableQueue(IDLE_TASK_QUEUE); | 516 renderer_task_queue_selector_->DisableQueue(IDLE_TASK_QUEUE); |
507 bool is_tracing; | 517 bool is_tracing; |
508 TRACE_EVENT_CATEGORY_GROUP_ENABLED("renderer.scheduler", &is_tracing); | 518 TRACE_EVENT_CATEGORY_GROUP_ENABLED("renderer.scheduler", &is_tracing); |
509 if (is_tracing && !estimated_next_frame_begin_.is_null() && | 519 if (is_tracing && !estimated_next_frame_begin_.is_null() && |
510 base::TimeTicks::Now() > estimated_next_frame_begin_) { | 520 base::TimeTicks::Now() > estimated_next_frame_begin_) { |
511 TRACE_EVENT_ASYNC_STEP_INTO_WITH_TIMESTAMP0( | 521 TRACE_EVENT_ASYNC_STEP_INTO_WITH_TIMESTAMP0( |
512 "renderer.scheduler", | 522 "renderer.scheduler", |
513 "RendererSchedulerIdlePeriod", | 523 "RendererSchedulerIdlePeriod", |
514 this, | 524 this, |
515 "DeadlineOverrun", | 525 "DeadlineOverrun", |
516 estimated_next_frame_begin_.ToInternalValue()); | 526 estimated_next_frame_begin_.ToInternalValue()); |
517 } | 527 } |
518 TRACE_EVENT_ASYNC_END0("renderer.scheduler", | 528 TRACE_EVENT_ASYNC_END0("renderer.scheduler", |
519 "RendererSchedulerIdlePeriod", this); | 529 "RendererSchedulerIdlePeriod", this); |
520 } | 530 } |
521 | 531 |
532 bool RendererSchedulerImpl::CanExceedIdleDeadlineIfRequired() const { | |
533 return idle_period_state_ == IdlePeriodState::WITHIN_MAX_DEADLINE_IDLE_PERIOD; | |
Sami
2015/03/05 11:59:32
DCHECK(main_thread_checker_.CalledOnValidThread())
rmcilroy
2015/03/05 13:50:19
Done.
| |
534 } | |
535 | |
522 void RendererSchedulerImpl::SetTimeSourceForTesting( | 536 void RendererSchedulerImpl::SetTimeSourceForTesting( |
523 scoped_refptr<cc::TestNowSource> time_source) { | 537 scoped_refptr<cc::TestNowSource> time_source) { |
524 DCHECK(main_thread_checker_.CalledOnValidThread()); | 538 DCHECK(main_thread_checker_.CalledOnValidThread()); |
525 time_source_ = time_source; | 539 time_source_ = time_source; |
526 task_queue_manager_->SetTimeSourceForTesting(time_source); | 540 task_queue_manager_->SetTimeSourceForTesting(time_source); |
527 } | 541 } |
528 | 542 |
529 void RendererSchedulerImpl::SetWorkBatchSizeForTesting(size_t work_batch_size) { | 543 void RendererSchedulerImpl::SetWorkBatchSizeForTesting(size_t work_batch_size) { |
530 DCHECK(main_thread_checker_.CalledOnValidThread()); | 544 DCHECK(main_thread_checker_.CalledOnValidThread()); |
531 task_queue_manager_->SetWorkBatchSize(work_batch_size); | 545 task_queue_manager_->SetWorkBatchSize(work_batch_size); |
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
675 } | 689 } |
676 | 690 |
677 void RendererSchedulerImpl::RemoveTaskObserver( | 691 void RendererSchedulerImpl::RemoveTaskObserver( |
678 base::MessageLoop::TaskObserver* task_observer) { | 692 base::MessageLoop::TaskObserver* task_observer) { |
679 DCHECK(main_thread_checker_.CalledOnValidThread()); | 693 DCHECK(main_thread_checker_.CalledOnValidThread()); |
680 if (task_queue_manager_) | 694 if (task_queue_manager_) |
681 task_queue_manager_->RemoveTaskObserver(task_observer); | 695 task_queue_manager_->RemoveTaskObserver(task_observer); |
682 } | 696 } |
683 | 697 |
684 } // namespace content | 698 } // namespace content |
OLD | NEW |