Chromium Code Reviews| 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 |