Chromium Code Reviews| Index: content/child/scheduler/scheduler_helper.cc |
| diff --git a/content/renderer/scheduler/renderer_scheduler_impl.cc b/content/child/scheduler/scheduler_helper.cc |
| similarity index 22% |
| copy from content/renderer/scheduler/renderer_scheduler_impl.cc |
| copy to content/child/scheduler/scheduler_helper.cc |
| index 53281b81a807a7389d7e3917b86ef822d5c3bcc4..cc03d22d4740423d3932ae40718e3b5c48623f93 100644 |
| --- a/content/renderer/scheduler/renderer_scheduler_impl.cc |
| +++ b/content/child/scheduler/scheduler_helper.cc |
| @@ -1,431 +1,119 @@ |
| -// Copyright 2014 The Chromium Authors. All rights reserved. |
| +// Copyright 2015 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| -#include "content/renderer/scheduler/renderer_scheduler_impl.h" |
| +#include "content/child/scheduler/scheduler_helper.h" |
| -#include "base/bind.h" |
| -#include "base/message_loop/message_loop_proxy.h" |
| #include "base/trace_event/trace_event.h" |
| #include "base/trace_event/trace_event_argument.h" |
| -#include "cc/output/begin_frame_args.h" |
| -#include "content/renderer/scheduler/nestable_single_thread_task_runner.h" |
| -#include "content/renderer/scheduler/renderer_task_queue_selector.h" |
| -#include "ui/gfx/frame_time.h" |
| +#include "content/child/scheduler/nestable_single_thread_task_runner.h" |
| +#include "content/child/scheduler/prioritizing_task_queue_selector.h" |
| namespace content { |
| -RendererSchedulerImpl::RendererSchedulerImpl( |
| - scoped_refptr<NestableSingleThreadTaskRunner> main_task_runner) |
| - : renderer_task_queue_selector_(new RendererTaskQueueSelector()), |
| +SchedulerHelper::SchedulerHelper( |
| + scoped_refptr<NestableSingleThreadTaskRunner> main_task_runner, |
| + SchedulerHelperDelegate* scheduler_helper_delegate, |
| + const char* tracing_category, |
| + const char* disabled_by_default_tracing_category, |
| + size_t total_task_queue_count) |
| + : task_queue_selector_(new PrioritizingTaskQueueSelector()), |
| task_queue_manager_( |
| - new TaskQueueManager(TASK_QUEUE_COUNT, |
| + new TaskQueueManager(total_task_queue_count, |
| main_task_runner, |
| - renderer_task_queue_selector_.get())), |
| + task_queue_selector_.get(), |
| + disabled_by_default_tracing_category)), |
| + idle_period_state_(IdlePeriodState::NOT_IN_IDLE_PERIOD), |
| + scheduler_helper_delegate_(scheduler_helper_delegate), |
| control_task_runner_( |
| - task_queue_manager_->TaskRunnerForQueue(CONTROL_TASK_QUEUE)), |
| + task_queue_manager_->TaskRunnerForQueue(QueueId::CONTROL_TASK_QUEUE)), |
| control_task_after_wakeup_runner_(task_queue_manager_->TaskRunnerForQueue( |
| - CONTROL_TASK_AFTER_WAKEUP_QUEUE)), |
| + QueueId::CONTROL_TASK_AFTER_WAKEUP_QUEUE)), |
| default_task_runner_( |
| - task_queue_manager_->TaskRunnerForQueue(DEFAULT_TASK_QUEUE)), |
| - compositor_task_runner_( |
| - task_queue_manager_->TaskRunnerForQueue(COMPOSITOR_TASK_QUEUE)), |
| - loading_task_runner_( |
| - task_queue_manager_->TaskRunnerForQueue(LOADING_TASK_QUEUE)), |
| - delayed_update_policy_runner_( |
| - base::Bind(&RendererSchedulerImpl::UpdatePolicy, |
| - base::Unretained(this)), |
| - control_task_runner_), |
| - current_policy_(Policy::NORMAL), |
| - idle_period_state_(IdlePeriodState::NOT_IN_IDLE_PERIOD), |
| - last_input_type_(blink::WebInputEvent::Undefined), |
| - input_stream_state_(InputStreamState::INACTIVE), |
| - policy_may_need_update_(&incoming_signals_lock_), |
| + task_queue_manager_->TaskRunnerForQueue(QueueId::DEFAULT_TASK_QUEUE)), |
| + tracing_category_(tracing_category), |
| + disabled_by_default_tracing_category_( |
| + disabled_by_default_tracing_category), |
| weak_factory_(this) { |
| - weak_renderer_scheduler_ptr_ = weak_factory_.GetWeakPtr(); |
| - update_policy_closure_ = base::Bind(&RendererSchedulerImpl::UpdatePolicy, |
| - weak_renderer_scheduler_ptr_); |
| - end_idle_period_closure_.Reset(base::Bind( |
| - &RendererSchedulerImpl::EndIdlePeriod, weak_renderer_scheduler_ptr_)); |
| + DCHECK_GE(total_task_queue_count, QueueId::TASK_QUEUE_COUNT); |
| + weak_scheduler_ptr_ = weak_factory_.GetWeakPtr(); |
| + end_idle_period_closure_.Reset( |
| + base::Bind(&SchedulerHelper::EndIdlePeriod, weak_scheduler_ptr_)); |
| initiate_next_long_idle_period_closure_.Reset(base::Bind( |
| - &RendererSchedulerImpl::InitiateLongIdlePeriod, |
| - weak_renderer_scheduler_ptr_)); |
| - initiate_next_long_idle_period_after_wakeup_closure_.Reset(base::Bind( |
| - &RendererSchedulerImpl::InitiateLongIdlePeriodAfterWakeup, |
| - weak_renderer_scheduler_ptr_)); |
| + &SchedulerHelper::InitiateLongIdlePeriod, weak_scheduler_ptr_)); |
| + initiate_next_long_idle_period_after_wakeup_closure_.Reset( |
| + base::Bind(&SchedulerHelper::InitiateLongIdlePeriodAfterWakeup, |
| + weak_scheduler_ptr_)); |
| idle_task_runner_ = make_scoped_refptr(new SingleThreadIdleTaskRunner( |
| - task_queue_manager_->TaskRunnerForQueue(IDLE_TASK_QUEUE), |
| + task_queue_manager_->TaskRunnerForQueue(QueueId::IDLE_TASK_QUEUE), |
| control_task_after_wakeup_runner_, |
| - base::Bind(&RendererSchedulerImpl::CurrentIdleTaskDeadlineCallback, |
| - weak_renderer_scheduler_ptr_))); |
| + base::Bind(&SchedulerHelper::CurrentIdleTaskDeadlineCallback, |
| + weak_scheduler_ptr_), |
| + tracing_category)); |
| - renderer_task_queue_selector_->SetQueuePriority( |
| - CONTROL_TASK_QUEUE, RendererTaskQueueSelector::CONTROL_PRIORITY); |
| + task_queue_selector_->SetQueuePriority( |
| + QueueId::CONTROL_TASK_QUEUE, |
| + PrioritizingTaskQueueSelector::CONTROL_PRIORITY); |
| - renderer_task_queue_selector_->SetQueuePriority( |
| - CONTROL_TASK_AFTER_WAKEUP_QUEUE, |
| - RendererTaskQueueSelector::CONTROL_PRIORITY); |
| + task_queue_selector_->SetQueuePriority( |
| + QueueId::CONTROL_TASK_AFTER_WAKEUP_QUEUE, |
| + PrioritizingTaskQueueSelector::CONTROL_PRIORITY); |
| task_queue_manager_->SetPumpPolicy( |
| - CONTROL_TASK_AFTER_WAKEUP_QUEUE, |
| + QueueId::CONTROL_TASK_AFTER_WAKEUP_QUEUE, |
| TaskQueueManager::PumpPolicy::AFTER_WAKEUP); |
| - renderer_task_queue_selector_->DisableQueue(IDLE_TASK_QUEUE); |
| - task_queue_manager_->SetPumpPolicy(IDLE_TASK_QUEUE, |
| + task_queue_selector_->DisableQueue(QueueId::IDLE_TASK_QUEUE); |
| + task_queue_manager_->SetPumpPolicy(QueueId::IDLE_TASK_QUEUE, |
| TaskQueueManager::PumpPolicy::MANUAL); |
| // TODO(skyostil): Increase this to 4 (crbug.com/444764). |
| task_queue_manager_->SetWorkBatchSize(1); |
| +} |
| - for (size_t i = 0; i < TASK_QUEUE_COUNT; i++) { |
| - task_queue_manager_->SetQueueName( |
| - i, TaskQueueIdToString(static_cast<QueueId>(i))); |
| - } |
| - TRACE_EVENT_OBJECT_CREATED_WITH_ID( |
| - TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), "RendererScheduler", |
| - this); |
| +SchedulerHelper::~SchedulerHelper() { |
| } |
| -RendererSchedulerImpl::~RendererSchedulerImpl() { |
| - TRACE_EVENT_OBJECT_DELETED_WITH_ID( |
| - TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), "RendererScheduler", |
| - this); |
| +SchedulerHelper::SchedulerHelperDelegate::SchedulerHelperDelegate() { |
| } |
| -void RendererSchedulerImpl::Shutdown() { |
| - DCHECK(main_thread_checker_.CalledOnValidThread()); |
| - task_queue_manager_.reset(); |
| +SchedulerHelper::SchedulerHelperDelegate::~SchedulerHelperDelegate() { |
| } |
| -scoped_refptr<base::SingleThreadTaskRunner> |
| -RendererSchedulerImpl::DefaultTaskRunner() { |
| - DCHECK(main_thread_checker_.CalledOnValidThread()); |
| - return default_task_runner_; |
| +void SchedulerHelper::Shutdown() { |
| + CheckOnValidThread(); |
| + task_queue_manager_.reset(); |
| } |
| scoped_refptr<base::SingleThreadTaskRunner> |
| -RendererSchedulerImpl::CompositorTaskRunner() { |
| - DCHECK(main_thread_checker_.CalledOnValidThread()); |
| - return compositor_task_runner_; |
| +SchedulerHelper::DefaultTaskRunner() { |
| + CheckOnValidThread(); |
| + return default_task_runner_; |
| } |
| -scoped_refptr<SingleThreadIdleTaskRunner> |
| -RendererSchedulerImpl::IdleTaskRunner() { |
| - DCHECK(main_thread_checker_.CalledOnValidThread()); |
| +scoped_refptr<SingleThreadIdleTaskRunner> SchedulerHelper::IdleTaskRunner() { |
| + CheckOnValidThread(); |
| return idle_task_runner_; |
| } |
| scoped_refptr<base::SingleThreadTaskRunner> |
| -RendererSchedulerImpl::LoadingTaskRunner() { |
| - DCHECK(main_thread_checker_.CalledOnValidThread()); |
| - return loading_task_runner_; |
| -} |
| - |
| -void RendererSchedulerImpl::WillBeginFrame(const cc::BeginFrameArgs& args) { |
| - TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), |
| - "RendererSchedulerImpl::WillBeginFrame", "args", args.AsValue()); |
| - DCHECK(main_thread_checker_.CalledOnValidThread()); |
| - if (!task_queue_manager_) |
| - return; |
| - |
| - EndIdlePeriod(); |
| - estimated_next_frame_begin_ = args.frame_time + args.interval; |
| - // TODO(skyostil): Wire up real notification of input events processing |
| - // instead of this approximation. |
| - DidProcessInputEvent(args.frame_time); |
| +SchedulerHelper::ControlTaskRunner() { |
| + return control_task_runner_; |
| } |
| -void RendererSchedulerImpl::DidCommitFrameToCompositor() { |
| - TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), |
| - "RendererSchedulerImpl::DidCommitFrameToCompositor"); |
| - DCHECK(main_thread_checker_.CalledOnValidThread()); |
| - if (!task_queue_manager_) |
| - return; |
| - |
| - base::TimeTicks now(Now()); |
| - if (now < estimated_next_frame_begin_) { |
| - // TODO(rmcilroy): Consider reducing the idle period based on the runtime of |
| - // the next pending delayed tasks (as currently done in for long idle times) |
| - StartIdlePeriod(IdlePeriodState::IN_SHORT_IDLE_PERIOD); |
| - control_task_runner_->PostDelayedTask(FROM_HERE, |
| - end_idle_period_closure_.callback(), |
| - estimated_next_frame_begin_ - now); |
| - } |
| -} |
| - |
| -void RendererSchedulerImpl::BeginFrameNotExpectedSoon() { |
| - TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), |
| - "RendererSchedulerImpl::BeginFrameNotExpectedSoon"); |
| - DCHECK(main_thread_checker_.CalledOnValidThread()); |
| - if (!task_queue_manager_) |
| - return; |
| - |
| - // TODO(skyostil): Wire up real notification of input events processing |
| - // instead of this approximation. |
| - DidProcessInputEvent(base::TimeTicks()); |
| - |
| - InitiateLongIdlePeriod(); |
| -} |
| - |
| -void RendererSchedulerImpl::DidReceiveInputEventOnCompositorThread( |
| - const blink::WebInputEvent& web_input_event) { |
| - TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), |
| - "RendererSchedulerImpl::DidReceiveInputEventOnCompositorThread"); |
| - // We regard MouseMove events with the left mouse button down as a signal |
| - // that the user is doing something requiring a smooth frame rate. |
| - if (web_input_event.type == blink::WebInputEvent::MouseMove && |
| - (web_input_event.modifiers & blink::WebInputEvent::LeftButtonDown)) { |
| - UpdateForInputEvent(web_input_event.type); |
| - return; |
| - } |
| - // Ignore all other mouse events because they probably don't signal user |
| - // interaction needing a smooth framerate. NOTE isMouseEventType returns false |
| - // for mouse wheel events, hence we regard them as user input. |
| - // Ignore keyboard events because it doesn't really make sense to enter |
| - // compositor priority for them. |
| - if (blink::WebInputEvent::isMouseEventType(web_input_event.type) || |
| - blink::WebInputEvent::isKeyboardEventType(web_input_event.type)) { |
| - return; |
| - } |
| - UpdateForInputEvent(web_input_event.type); |
| -} |
| - |
| -void RendererSchedulerImpl::DidAnimateForInputOnCompositorThread() { |
| - UpdateForInputEvent(blink::WebInputEvent::Undefined); |
| -} |
| - |
| -void RendererSchedulerImpl::UpdateForInputEvent( |
| - blink::WebInputEvent::Type type) { |
| - base::AutoLock lock(incoming_signals_lock_); |
| - |
| - InputStreamState new_input_stream_state = |
| - ComputeNewInputStreamState(input_stream_state_, type, last_input_type_); |
| - |
| - if (input_stream_state_ != new_input_stream_state) { |
| - // Update scheduler policy if we should start a new policy mode. |
| - input_stream_state_ = new_input_stream_state; |
| - EnsureUrgentPolicyUpdatePostedOnMainThread(FROM_HERE); |
| - } |
| - last_input_receipt_time_on_compositor_ = Now(); |
| - // Clear the last known input processing time so that we know an input event |
| - // is still queued up. This timestamp will be updated the next time the |
| - // compositor commits or becomes quiescent. Note that this function is always |
| - // called before the input event is processed either on the compositor or |
| - // main threads. |
| - last_input_process_time_on_main_ = base::TimeTicks(); |
| - last_input_type_ = type; |
| -} |
| - |
| -void RendererSchedulerImpl::DidProcessInputEvent( |
| - base::TimeTicks begin_frame_time) { |
| - DCHECK(main_thread_checker_.CalledOnValidThread()); |
| - base::AutoLock lock(incoming_signals_lock_); |
| - if (input_stream_state_ == InputStreamState::INACTIVE) |
| - return; |
| - // Avoid marking input that arrived after the BeginFrame as processed. |
| - if (!begin_frame_time.is_null() && |
| - begin_frame_time < last_input_receipt_time_on_compositor_) |
| - return; |
| - last_input_process_time_on_main_ = Now(); |
| - UpdatePolicyLocked(); |
| -} |
| - |
| -bool RendererSchedulerImpl::IsHighPriorityWorkAnticipated() { |
| - DCHECK(main_thread_checker_.CalledOnValidThread()); |
| - if (!task_queue_manager_) |
| - return false; |
| - |
| - MaybeUpdatePolicy(); |
| - // The touchstart and compositor policies indicate a strong likelihood of |
| - // high-priority work in the near future. |
| - return SchedulerPolicy() == Policy::COMPOSITOR_PRIORITY || |
| - SchedulerPolicy() == Policy::TOUCHSTART_PRIORITY; |
| -} |
| - |
| -bool RendererSchedulerImpl::ShouldYieldForHighPriorityWork() { |
| - DCHECK(main_thread_checker_.CalledOnValidThread()); |
| - if (!task_queue_manager_) |
| - return false; |
| - |
| - MaybeUpdatePolicy(); |
| - // We only yield if we are in the compositor priority and there is compositor |
| - // work outstanding, or if we are in the touchstart response priority. |
| - // Note: even though the control queue is higher priority we don't yield for |
| - // it since these tasks are not user-provided work and they are only intended |
| - // to run before the next task, not interrupt the tasks. |
| - switch (SchedulerPolicy()) { |
| - case Policy::NORMAL: |
| - return false; |
| - |
| - case Policy::COMPOSITOR_PRIORITY: |
| - return !task_queue_manager_->IsQueueEmpty(COMPOSITOR_TASK_QUEUE); |
| - |
| - case Policy::TOUCHSTART_PRIORITY: |
| - return true; |
| - |
| - default: |
| - NOTREACHED(); |
| - return false; |
| - } |
| -} |
| - |
| -void RendererSchedulerImpl::CurrentIdleTaskDeadlineCallback( |
| +void SchedulerHelper::CurrentIdleTaskDeadlineCallback( |
| base::TimeTicks* deadline_out) const { |
| - DCHECK(main_thread_checker_.CalledOnValidThread()); |
| - *deadline_out = estimated_next_frame_begin_; |
| + CheckOnValidThread(); |
| + *deadline_out = estimated_end_of_idle_; |
| } |
| -RendererSchedulerImpl::Policy RendererSchedulerImpl::SchedulerPolicy() const { |
| - DCHECK(main_thread_checker_.CalledOnValidThread()); |
| - return current_policy_; |
| -} |
| - |
| -void RendererSchedulerImpl::MaybeUpdatePolicy() { |
| - DCHECK(main_thread_checker_.CalledOnValidThread()); |
| - if (policy_may_need_update_.IsSet()) { |
| - UpdatePolicy(); |
| - } |
| -} |
| - |
| -void RendererSchedulerImpl::EnsureUrgentPolicyUpdatePostedOnMainThread( |
| - const tracked_objects::Location& from_here) { |
| - // TODO(scheduler-dev): Check that this method isn't called from the main |
| - // thread. |
| - incoming_signals_lock_.AssertAcquired(); |
| - if (!policy_may_need_update_.IsSet()) { |
| - policy_may_need_update_.SetWhileLocked(true); |
| - control_task_runner_->PostTask(from_here, update_policy_closure_); |
| - } |
| -} |
| - |
| -void RendererSchedulerImpl::UpdatePolicy() { |
| - base::AutoLock lock(incoming_signals_lock_); |
| - UpdatePolicyLocked(); |
| -} |
| - |
| -void RendererSchedulerImpl::UpdatePolicyLocked() { |
| - DCHECK(main_thread_checker_.CalledOnValidThread()); |
| - incoming_signals_lock_.AssertAcquired(); |
| - if (!task_queue_manager_) |
| - return; |
| - |
| - base::TimeTicks now = Now(); |
| - policy_may_need_update_.SetWhileLocked(false); |
| - |
| - base::TimeDelta new_policy_duration; |
| - Policy new_policy = ComputeNewPolicy(now, &new_policy_duration); |
| - if (new_policy_duration > base::TimeDelta()) { |
| - current_policy_expiration_time_ = now + new_policy_duration; |
| - delayed_update_policy_runner_.SetDeadline(FROM_HERE, new_policy_duration, |
| - now); |
| - } else { |
| - current_policy_expiration_time_ = base::TimeTicks(); |
| - } |
| - |
| - if (new_policy == current_policy_) |
| - return; |
| - |
| - switch (new_policy) { |
| - case Policy::COMPOSITOR_PRIORITY: |
| - renderer_task_queue_selector_->SetQueuePriority( |
| - COMPOSITOR_TASK_QUEUE, RendererTaskQueueSelector::HIGH_PRIORITY); |
| - // TODO(scheduler-dev): Add a task priority between HIGH and BEST_EFFORT |
| - // that still has some guarantee of running. |
| - renderer_task_queue_selector_->SetQueuePriority( |
| - LOADING_TASK_QUEUE, RendererTaskQueueSelector::BEST_EFFORT_PRIORITY); |
| - break; |
| - case Policy::TOUCHSTART_PRIORITY: |
| - renderer_task_queue_selector_->SetQueuePriority( |
| - COMPOSITOR_TASK_QUEUE, RendererTaskQueueSelector::HIGH_PRIORITY); |
| - renderer_task_queue_selector_->DisableQueue(LOADING_TASK_QUEUE); |
| - break; |
| - case Policy::NORMAL: |
| - renderer_task_queue_selector_->SetQueuePriority( |
| - COMPOSITOR_TASK_QUEUE, RendererTaskQueueSelector::NORMAL_PRIORITY); |
| - renderer_task_queue_selector_->SetQueuePriority( |
| - LOADING_TASK_QUEUE, RendererTaskQueueSelector::NORMAL_PRIORITY); |
| - break; |
| - } |
| - DCHECK(renderer_task_queue_selector_->IsQueueEnabled(COMPOSITOR_TASK_QUEUE)); |
| - if (new_policy != Policy::TOUCHSTART_PRIORITY) |
| - DCHECK(renderer_task_queue_selector_->IsQueueEnabled(LOADING_TASK_QUEUE)); |
| - |
| - current_policy_ = new_policy; |
| - |
| - TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID( |
| - TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), "RendererScheduler", |
| - this, AsValueLocked(now)); |
| - TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), |
| - "RendererScheduler.policy", current_policy_); |
| -} |
| - |
| -RendererSchedulerImpl::Policy RendererSchedulerImpl::ComputeNewPolicy( |
| - base::TimeTicks now, |
| - base::TimeDelta* new_policy_duration) { |
| - DCHECK(main_thread_checker_.CalledOnValidThread()); |
| - incoming_signals_lock_.AssertAcquired(); |
| - |
| - Policy new_policy = Policy::NORMAL; |
| - *new_policy_duration = base::TimeDelta(); |
| - |
| - if (input_stream_state_ == InputStreamState::INACTIVE) |
| - return new_policy; |
| - |
| - Policy input_priority_policy = |
| - input_stream_state_ == |
| - InputStreamState::ACTIVE_AND_AWAITING_TOUCHSTART_RESPONSE |
| - ? Policy::TOUCHSTART_PRIORITY |
| - : Policy::COMPOSITOR_PRIORITY; |
| - base::TimeDelta time_left_in_policy = TimeLeftInInputEscalatedPolicy(now); |
| - if (time_left_in_policy > base::TimeDelta()) { |
| - new_policy = input_priority_policy; |
| - *new_policy_duration = time_left_in_policy; |
| - } else { |
| - // Reset |input_stream_state_| to ensure |
| - // DidReceiveInputEventOnCompositorThread will post an UpdatePolicy task |
| - // when it's next called. |
| - input_stream_state_ = InputStreamState::INACTIVE; |
| - } |
| - return new_policy; |
| -} |
| - |
| -base::TimeDelta RendererSchedulerImpl::TimeLeftInInputEscalatedPolicy( |
| - base::TimeTicks now) const { |
| - DCHECK(main_thread_checker_.CalledOnValidThread()); |
| - // TODO(rmcilroy): Change this to DCHECK_EQ when crbug.com/463869 is fixed. |
| - DCHECK(input_stream_state_ != InputStreamState::INACTIVE); |
| - incoming_signals_lock_.AssertAcquired(); |
| - |
| - base::TimeDelta escalated_priority_duration = |
| - base::TimeDelta::FromMilliseconds(kPriorityEscalationAfterInputMillis); |
| - base::TimeDelta time_left_in_policy; |
| - if (last_input_process_time_on_main_.is_null() && |
| - !task_queue_manager_->IsQueueEmpty(COMPOSITOR_TASK_QUEUE)) { |
| - // If the input event is still pending, go into input prioritized policy |
| - // and check again later. |
| - time_left_in_policy = escalated_priority_duration; |
| - } else { |
| - // Otherwise make sure the input prioritization policy ends on time. |
| - base::TimeTicks new_priority_end( |
| - std::max(last_input_receipt_time_on_compositor_, |
| - last_input_process_time_on_main_) + |
| - escalated_priority_duration); |
| - time_left_in_policy = new_priority_end - now; |
| - } |
| - return time_left_in_policy; |
| -} |
| - |
| -RendererSchedulerImpl::IdlePeriodState |
| -RendererSchedulerImpl::ComputeNewLongIdlePeriodState( |
| +SchedulerHelper::IdlePeriodState SchedulerHelper::ComputeNewLongIdlePeriodState( |
| const base::TimeTicks now, |
| base::TimeDelta* next_long_idle_period_delay_out) { |
| - DCHECK(main_thread_checker_.CalledOnValidThread()); |
| + CheckOnValidThread(); |
| - MaybeUpdatePolicy(); |
| - if (SchedulerPolicy() == Policy::TOUCHSTART_PRIORITY) { |
| - // Don't start a long idle task in touch start priority, try again when |
| - // the policy is scheduled to end. |
| - *next_long_idle_period_delay_out = current_policy_expiration_time_ - now; |
| + if (!scheduler_helper_delegate_->CanEnterLongIdlePeriod( |
| + now, next_long_idle_period_delay_out)) { |
| return IdlePeriodState::NOT_IN_IDLE_PERIOD; |
| } |
| @@ -455,10 +143,9 @@ RendererSchedulerImpl::ComputeNewLongIdlePeriodState( |
| } |
| } |
| -void RendererSchedulerImpl::InitiateLongIdlePeriod() { |
| - TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), |
| - "InitiateLongIdlePeriod"); |
| - DCHECK(main_thread_checker_.CalledOnValidThread()); |
| +void SchedulerHelper::InitiateLongIdlePeriod() { |
| + TRACE_EVENT0(disabled_by_default_tracing_category_, "InitiateLongIdlePeriod"); |
| + CheckOnValidThread(); |
| // End any previous idle period. |
| EndIdlePeriod(); |
| @@ -468,11 +155,11 @@ void RendererSchedulerImpl::InitiateLongIdlePeriod() { |
| IdlePeriodState new_idle_period_state = |
| ComputeNewLongIdlePeriodState(now, &next_long_idle_period_delay); |
| if (IsInIdlePeriod(new_idle_period_state)) { |
| - estimated_next_frame_begin_ = now + next_long_idle_period_delay; |
| + estimated_end_of_idle_ = now + next_long_idle_period_delay; |
| StartIdlePeriod(new_idle_period_state); |
| } |
| - if (task_queue_manager_->IsQueueEmpty(IDLE_TASK_QUEUE)) { |
| + if (task_queue_manager_->IsQueueEmpty(QueueId::IDLE_TASK_QUEUE)) { |
| // If there are no current idle tasks then post the call to initiate the |
| // next idle for execution after wakeup (at which point after-wakeup idle |
| // tasks might be eligible to run or more idle tasks posted). |
| @@ -483,23 +170,22 @@ void RendererSchedulerImpl::InitiateLongIdlePeriod() { |
| } else { |
| // Otherwise post on the normal control task queue. |
| control_task_runner_->PostDelayedTask( |
| - FROM_HERE, |
| - initiate_next_long_idle_period_closure_.callback(), |
| + FROM_HERE, initiate_next_long_idle_period_closure_.callback(), |
| next_long_idle_period_delay); |
| } |
| } |
| -void RendererSchedulerImpl::InitiateLongIdlePeriodAfterWakeup() { |
| - TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), |
| +void SchedulerHelper::InitiateLongIdlePeriodAfterWakeup() { |
| + TRACE_EVENT0(disabled_by_default_tracing_category_, |
| "InitiateLongIdlePeriodAfterWakeup"); |
| - DCHECK(main_thread_checker_.CalledOnValidThread()); |
| + CheckOnValidThread(); |
| if (IsInIdlePeriod(idle_period_state_)) { |
| // Since we were asleep until now, end the async idle period trace event at |
| // the time when it would have ended were we awake. |
| TRACE_EVENT_ASYNC_END_WITH_TIMESTAMP0( |
| - "renderer.scheduler", "RendererSchedulerIdlePeriod", this, |
| - std::min(estimated_next_frame_begin_, Now()).ToInternalValue()); |
| + tracing_category_, "RendererSchedulerIdlePeriod", this, |
| + std::min(estimated_end_of_idle_, Now()).ToInternalValue()); |
| idle_period_state_ = IdlePeriodState::ENDING_LONG_IDLE_PERIOD; |
| EndIdlePeriod(); |
| } |
| @@ -509,24 +195,24 @@ void RendererSchedulerImpl::InitiateLongIdlePeriodAfterWakeup() { |
| // on the idle task queue before the next idle period starts so they are |
| // eligible to be run during the new idle period. |
| control_task_runner_->PostTask( |
| - FROM_HERE, |
| - initiate_next_long_idle_period_closure_.callback()); |
| + FROM_HERE, initiate_next_long_idle_period_closure_.callback()); |
| } |
| -void RendererSchedulerImpl::StartIdlePeriod(IdlePeriodState new_state) { |
| - TRACE_EVENT_ASYNC_BEGIN0("renderer.scheduler", |
| - "RendererSchedulerIdlePeriod", this); |
| - DCHECK(main_thread_checker_.CalledOnValidThread()); |
| +void SchedulerHelper::StartIdlePeriod(IdlePeriodState new_state) { |
| + TRACE_EVENT_ASYNC_BEGIN0(tracing_category_, "RendererSchedulerIdlePeriod", |
| + this); |
| + CheckOnValidThread(); |
| DCHECK(IsInIdlePeriod(new_state)); |
| - renderer_task_queue_selector_->EnableQueue( |
| - IDLE_TASK_QUEUE, RendererTaskQueueSelector::BEST_EFFORT_PRIORITY); |
| - task_queue_manager_->PumpQueue(IDLE_TASK_QUEUE); |
| + task_queue_selector_->EnableQueue( |
| + QueueId::IDLE_TASK_QUEUE, |
| + PrioritizingTaskQueueSelector::BEST_EFFORT_PRIORITY); |
| + task_queue_manager_->PumpQueue(QueueId::IDLE_TASK_QUEUE); |
| idle_period_state_ = new_state; |
| } |
| -void RendererSchedulerImpl::EndIdlePeriod() { |
| - DCHECK(main_thread_checker_.CalledOnValidThread()); |
| +void SchedulerHelper::EndIdlePeriod() { |
| + CheckOnValidThread(); |
| end_idle_period_closure_.Cancel(); |
| initiate_next_long_idle_period_closure_.Cancel(); |
| @@ -540,79 +226,81 @@ void RendererSchedulerImpl::EndIdlePeriod() { |
| // trace event. |
| if (idle_period_state_ != IdlePeriodState::ENDING_LONG_IDLE_PERIOD) { |
| bool is_tracing; |
| - TRACE_EVENT_CATEGORY_GROUP_ENABLED("renderer.scheduler", &is_tracing); |
| - if (is_tracing && !estimated_next_frame_begin_.is_null() && |
| - base::TimeTicks::Now() > estimated_next_frame_begin_) { |
| + TRACE_EVENT_CATEGORY_GROUP_ENABLED(tracing_category_, &is_tracing); |
| + if (is_tracing && !estimated_end_of_idle_.is_null() && |
| + base::TimeTicks::Now() > estimated_end_of_idle_) { |
| TRACE_EVENT_ASYNC_STEP_INTO_WITH_TIMESTAMP0( |
| - "renderer.scheduler", |
| - "RendererSchedulerIdlePeriod", |
| - this, |
| - "DeadlineOverrun", |
| - estimated_next_frame_begin_.ToInternalValue()); |
| + tracing_category_, "RendererSchedulerIdlePeriod", this, |
| + "DeadlineOverrun", estimated_end_of_idle_.ToInternalValue()); |
| } |
| - TRACE_EVENT_ASYNC_END0("renderer.scheduler", |
| - "RendererSchedulerIdlePeriod", this); |
| + TRACE_EVENT_ASYNC_END0(tracing_category_, "RendererSchedulerIdlePeriod", |
| + this); |
| } |
| - renderer_task_queue_selector_->DisableQueue(IDLE_TASK_QUEUE); |
| + task_queue_selector_->DisableQueue(QueueId::IDLE_TASK_QUEUE); |
| idle_period_state_ = IdlePeriodState::NOT_IN_IDLE_PERIOD; |
| } |
| // static |
| -bool RendererSchedulerImpl::IsInIdlePeriod(IdlePeriodState state) { |
| +bool SchedulerHelper::IsInIdlePeriod(IdlePeriodState state) { |
| return state != IdlePeriodState::NOT_IN_IDLE_PERIOD; |
| } |
| -bool RendererSchedulerImpl::CanExceedIdleDeadlineIfRequired() const { |
| - TRACE_EVENT_BEGIN0("renderer.scheduler", "CanExceedIdleDeadlineIfRequired"); |
| - DCHECK(main_thread_checker_.CalledOnValidThread()); |
| +bool SchedulerHelper::CanExceedIdleDeadlineIfRequired() const { |
| + TRACE_EVENT_BEGIN0(tracing_category_, "CanExceedIdleDeadlineIfRequired"); |
| + CheckOnValidThread(); |
| return idle_period_state_ == |
| IdlePeriodState::IN_LONG_IDLE_PERIOD_WITH_MAX_DEADLINE; |
| } |
| -void RendererSchedulerImpl::SetTimeSourceForTesting( |
| +void SchedulerHelper::SetTimeSourceForTesting( |
| scoped_refptr<cc::TestNowSource> time_source) { |
| - DCHECK(main_thread_checker_.CalledOnValidThread()); |
| + CheckOnValidThread(); |
| time_source_ = time_source; |
| task_queue_manager_->SetTimeSourceForTesting(time_source); |
| } |
| -void RendererSchedulerImpl::SetWorkBatchSizeForTesting(size_t work_batch_size) { |
| - DCHECK(main_thread_checker_.CalledOnValidThread()); |
| +void SchedulerHelper::SetWorkBatchSizeForTesting(size_t work_batch_size) { |
| + CheckOnValidThread(); |
| task_queue_manager_->SetWorkBatchSize(work_batch_size); |
| } |
| -base::TimeTicks RendererSchedulerImpl::Now() const { |
| +base::TimeTicks SchedulerHelper::Now() const { |
| return UNLIKELY(time_source_) ? time_source_->Now() : base::TimeTicks::Now(); |
| } |
| -RendererSchedulerImpl::PollableNeedsUpdateFlag::PollableNeedsUpdateFlag( |
| - base::Lock* write_lock_) |
| - : flag_(false), write_lock_(write_lock_) { |
| +base::TimeTicks SchedulerHelper::EstimatedEndOfIdle() const { |
| + return estimated_end_of_idle_; |
| +} |
| + |
| +void SchedulerHelper::SetEstimatedEndOfIdle( |
| + base::TimeTicks estimated_next_frame_begin) { |
|
rmcilroy
2015/03/27 19:01:59
Update arg name here too.
alex clarke (OOO till 29th)
2015/03/30 12:23:29
Done.
|
| + estimated_end_of_idle_ = estimated_next_frame_begin; |
| +} |
| + |
| +const CancelableClosureHolder& SchedulerHelper::EndIdlePeriodClosure() const { |
| + return end_idle_period_closure_; |
| } |
| -RendererSchedulerImpl::PollableNeedsUpdateFlag::~PollableNeedsUpdateFlag() { |
| +SchedulerHelper::IdlePeriodState |
| +SchedulerHelper::SchedulerIdlePeriodState() const { |
| + return idle_period_state_; |
| } |
| -void RendererSchedulerImpl::PollableNeedsUpdateFlag::SetWhileLocked( |
| - bool value) { |
| - write_lock_->AssertAcquired(); |
| - base::subtle::Release_Store(&flag_, value); |
| +PrioritizingTaskQueueSelector* SchedulerHelper::SchedulerTaskQueueSelector() |
| + const { |
|
rmcilroy
2015/03/27 19:01:59
You did the one above but not this one (fine to ig
alex clarke (OOO till 29th)
2015/03/30 12:23:29
Done.
|
| + return task_queue_selector_.get(); |
| } |
| -bool RendererSchedulerImpl::PollableNeedsUpdateFlag::IsSet() const { |
| - return base::subtle::Acquire_Load(&flag_) != 0; |
| +TaskQueueManager* SchedulerHelper::SchedulerTaskQueueManager() const { |
| + return task_queue_manager_.get(); |
| } |
| // static |
| -const char* RendererSchedulerImpl::TaskQueueIdToString(QueueId queue_id) { |
| +const char* SchedulerHelper::TaskQueueIdToString(QueueId queue_id) { |
| switch (queue_id) { |
| case DEFAULT_TASK_QUEUE: |
| return "default_tq"; |
| - case COMPOSITOR_TASK_QUEUE: |
| - return "compositor_tq"; |
| - case LOADING_TASK_QUEUE: |
| - return "loading_tq"; |
| case IDLE_TASK_QUEUE: |
| return "idle_tq"; |
| case CONTROL_TASK_QUEUE: |
| @@ -626,36 +314,7 @@ const char* RendererSchedulerImpl::TaskQueueIdToString(QueueId queue_id) { |
| } |
| // static |
| -const char* RendererSchedulerImpl::PolicyToString(Policy policy) { |
| - switch (policy) { |
| - case Policy::NORMAL: |
| - return "normal"; |
| - case Policy::COMPOSITOR_PRIORITY: |
| - return "compositor"; |
| - case Policy::TOUCHSTART_PRIORITY: |
| - return "touchstart"; |
| - default: |
| - NOTREACHED(); |
| - return nullptr; |
| - } |
| -} |
| - |
| -const char* RendererSchedulerImpl::InputStreamStateToString( |
| - InputStreamState state) { |
| - switch (state) { |
| - case InputStreamState::INACTIVE: |
| - return "inactive"; |
| - case InputStreamState::ACTIVE: |
| - return "active"; |
| - case InputStreamState::ACTIVE_AND_AWAITING_TOUCHSTART_RESPONSE: |
| - return "active_and_awaiting_touchstart_response"; |
| - default: |
| - NOTREACHED(); |
| - return nullptr; |
| - } |
| -} |
| - |
| -const char* RendererSchedulerImpl::IdlePeriodStateToString( |
| +const char* SchedulerHelper::IdlePeriodStateToString( |
| IdlePeriodState idle_period_state) { |
| switch (idle_period_state) { |
| case IdlePeriodState::NOT_IN_IDLE_PERIOD: |
| @@ -674,81 +333,16 @@ const char* RendererSchedulerImpl::IdlePeriodStateToString( |
| } |
| } |
| -scoped_refptr<base::trace_event::ConvertableToTraceFormat> |
| -RendererSchedulerImpl::AsValueLocked(base::TimeTicks optional_now) const { |
| - DCHECK(main_thread_checker_.CalledOnValidThread()); |
| - incoming_signals_lock_.AssertAcquired(); |
| - |
| - if (optional_now.is_null()) |
| - optional_now = Now(); |
| - scoped_refptr<base::trace_event::TracedValue> state = |
| - new base::trace_event::TracedValue(); |
| - |
| - state->SetString("current_policy", PolicyToString(current_policy_)); |
| - state->SetString("idle_period_state", |
| - IdlePeriodStateToString(idle_period_state_)); |
| - state->SetString("input_stream_state", |
| - InputStreamStateToString(input_stream_state_)); |
| - state->SetDouble("now", (optional_now - base::TimeTicks()).InMillisecondsF()); |
| - state->SetDouble("last_input_receipt_time_on_compositor_", |
| - (last_input_receipt_time_on_compositor_ - base::TimeTicks()) |
| - .InMillisecondsF()); |
| - state->SetDouble( |
| - "last_input_process_time_on_main_", |
| - (last_input_process_time_on_main_ - base::TimeTicks()).InMillisecondsF()); |
| - state->SetDouble( |
| - "estimated_next_frame_begin", |
| - (estimated_next_frame_begin_ - base::TimeTicks()).InMillisecondsF()); |
| - |
| - return state; |
| -} |
| - |
| -RendererSchedulerImpl::InputStreamState |
| -RendererSchedulerImpl::ComputeNewInputStreamState( |
| - InputStreamState current_state, |
| - blink::WebInputEvent::Type new_input_type, |
| - blink::WebInputEvent::Type last_input_type) { |
| - switch (new_input_type) { |
| - case blink::WebInputEvent::TouchStart: |
| - return InputStreamState::ACTIVE_AND_AWAITING_TOUCHSTART_RESPONSE; |
| - |
| - case blink::WebInputEvent::TouchMove: |
| - // Observation of consecutive touchmoves is a strong signal that the page |
| - // is consuming the touch sequence, in which case touchstart response |
| - // prioritization is no longer necessary. Otherwise, the initial touchmove |
| - // should preserve the touchstart response pending state. |
| - if (current_state == |
| - InputStreamState::ACTIVE_AND_AWAITING_TOUCHSTART_RESPONSE) { |
| - return last_input_type == blink::WebInputEvent::TouchMove |
| - ? InputStreamState::ACTIVE |
| - : InputStreamState::ACTIVE_AND_AWAITING_TOUCHSTART_RESPONSE; |
| - } |
| - break; |
| - |
| - case blink::WebInputEvent::GestureTapDown: |
| - case blink::WebInputEvent::GestureShowPress: |
| - case blink::WebInputEvent::GestureFlingCancel: |
| - case blink::WebInputEvent::GestureScrollEnd: |
| - // With no observable effect, these meta events do not indicate a |
| - // meaningful touchstart response and should not impact task priority. |
| - return current_state; |
| - |
| - default: |
| - break; |
| - } |
| - return InputStreamState::ACTIVE; |
| -} |
| - |
| -void RendererSchedulerImpl::AddTaskObserver( |
| +void SchedulerHelper::AddTaskObserver( |
| base::MessageLoop::TaskObserver* task_observer) { |
| - DCHECK(main_thread_checker_.CalledOnValidThread()); |
| + CheckOnValidThread(); |
| if (task_queue_manager_) |
| task_queue_manager_->AddTaskObserver(task_observer); |
| } |
| -void RendererSchedulerImpl::RemoveTaskObserver( |
| +void SchedulerHelper::RemoveTaskObserver( |
| base::MessageLoop::TaskObserver* task_observer) { |
| - DCHECK(main_thread_checker_.CalledOnValidThread()); |
| + CheckOnValidThread(); |
| if (task_queue_manager_) |
| task_queue_manager_->RemoveTaskObserver(task_observer); |
| } |