Index: components/scheduler/renderer/renderer_scheduler_impl.cc |
diff --git a/components/scheduler/renderer/renderer_scheduler_impl.cc b/components/scheduler/renderer/renderer_scheduler_impl.cc |
index 4b565314a7996816887d0a71aaca51161fe5515c..4a2aa633fee93523ccd378844d5ec6c45d94a6a9 100644 |
--- a/components/scheduler/renderer/renderer_scheduler_impl.cc |
+++ b/components/scheduler/renderer/renderer_scheduler_impl.cc |
@@ -15,8 +15,10 @@ |
namespace scheduler { |
namespace { |
-const int kTimerTaskEstimationSampleCount = 4 * 60; |
-const double kTimerTaskEstimationPercentile = 80; |
+const int kLoadingTaskEstimationSampleCount = 200; |
+const double kLoadingTaskEstimationPercentile = 90; |
+const int kTimerTaskEstimationSampleCount = 200; |
+const double kTimerTaskEstimationPercentile = 90; |
Sami
2015/08/26 13:38:01
Any reason for tweaking these in this way?
alex clarke (OOO till 29th)
2015/08/27 12:02:51
Yes, I was hoping for a more pessimistic result th
|
const int kShortIdlePeriodDurationSampleCount = 10; |
const double kShortIdlePeriodDurationPercentile = 20; |
} |
@@ -54,12 +56,19 @@ RendererSchedulerImpl::RendererSchedulerImpl( |
end_renderer_hidden_idle_period_closure_.Reset(base::Bind( |
&RendererSchedulerImpl::EndIdlePeriod, weak_factory_.GetWeakPtr())); |
+ loading_task_runner_->AddTaskObserver( |
+ &MainThreadOnly().loading_task_cost_estimator_); |
+ |
timer_task_runner_->AddTaskObserver( |
&MainThreadOnly().timer_task_cost_estimator_); |
TRACE_EVENT_OBJECT_CREATED_WITH_ID( |
TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), "RendererScheduler", |
this); |
+ |
+ // Make sure that we don't initially assume there is no idle time. |
+ MainThreadOnly().short_idle_period_duration_.InsertSample( |
+ base::TimeDelta::FromMilliseconds(16)); |
Sami
2015/08/26 13:38:01
BeginFrameArgs::DefaultInterval()?
alex clarke (OOO till 29th)
2015/08/27 12:02:51
Done.
|
} |
RendererSchedulerImpl::~RendererSchedulerImpl() { |
@@ -74,14 +83,23 @@ RendererSchedulerImpl::~RendererSchedulerImpl() { |
DCHECK(MainThreadOnly().was_shutdown_); |
} |
+RendererSchedulerImpl::Policy::Policy() |
+ : compositor_queue_priority_(TaskQueue::NORMAL_PRIORITY), |
+ loading_queue_priority_(TaskQueue::NORMAL_PRIORITY), |
+ timer_queue_priority_(TaskQueue::NORMAL_PRIORITY) {} |
+ |
RendererSchedulerImpl::MainThreadOnly::MainThreadOnly() |
- : timer_task_cost_estimator_(kTimerTaskEstimationSampleCount, |
+ : loading_task_cost_estimator_(kLoadingTaskEstimationSampleCount, |
+ kLoadingTaskEstimationPercentile), |
+ timer_task_cost_estimator_(kTimerTaskEstimationSampleCount, |
kTimerTaskEstimationPercentile), |
short_idle_period_duration_(kShortIdlePeriodDurationSampleCount), |
- current_policy_(Policy::NORMAL), |
+ current_use_case_(UseCase::NOT_SCROLLING), |
timer_queue_suspend_count_(0), |
renderer_hidden_(false), |
- was_shutdown_(false) {} |
+ was_shutdown_(false), |
+ loading_tasks_seem_expensive_(false), |
+ timer_tasks_seem_expensive_(false) {} |
RendererSchedulerImpl::MainThreadOnly::~MainThreadOnly() {} |
@@ -89,8 +107,7 @@ RendererSchedulerImpl::AnyThread::AnyThread() |
: pending_main_thread_input_event_count_(0), |
awaiting_touch_start_response_(false), |
in_idle_period_(false), |
- begin_main_frame_on_critical_path_(false), |
- timer_tasks_seem_expensive_(false) {} |
+ begin_main_frame_on_critical_path_(false) {} |
RendererSchedulerImpl::CompositorThreadOnly::CompositorThreadOnly() |
: last_input_type_(blink::WebInputEvent::Undefined) { |
@@ -176,10 +193,15 @@ void RendererSchedulerImpl::DidCommitFrameToCompositor() { |
MainThreadOnly().estimated_next_frame_begin_); |
MainThreadOnly().short_idle_period_duration_.InsertSample( |
MainThreadOnly().estimated_next_frame_begin_ - now); |
- MainThreadOnly().expected_short_idle_period_duration_ = |
- MainThreadOnly().short_idle_period_duration_.Percentile( |
- kShortIdlePeriodDurationPercentile); |
+ } else { |
+ // There was no idle time :( |
+ MainThreadOnly().short_idle_period_duration_.InsertSample( |
+ base::TimeDelta()); |
} |
+ |
+ MainThreadOnly().expected_short_idle_period_duration_ = |
+ MainThreadOnly().short_idle_period_duration_.Percentile( |
+ kShortIdlePeriodDurationPercentile); |
} |
void RendererSchedulerImpl::BeginFrameNotExpectedSoon() { |
@@ -278,12 +300,54 @@ void RendererSchedulerImpl::DidAnimateForInputOnCompositorThread() { |
InputEventState::EVENT_CONSUMED_BY_COMPOSITOR); |
} |
+const char* WebInputEventToString(blink::WebInputEvent::Type type) { |
+#define CASE_TYPE(t) \ |
+ case blink::WebInputEvent::t: \ |
+ return #t |
+ switch (type) { |
+ CASE_TYPE(Undefined); |
Sami
2015/08/26 13:38:01
Instead of duplicating this from RenderWidget, cou
alex clarke (OOO till 29th)
2015/08/27 12:02:51
Acknowledged.
|
+ CASE_TYPE(MouseDown); |
+ CASE_TYPE(MouseUp); |
+ CASE_TYPE(MouseMove); |
+ CASE_TYPE(MouseEnter); |
+ CASE_TYPE(MouseLeave); |
+ CASE_TYPE(ContextMenu); |
+ CASE_TYPE(MouseWheel); |
+ CASE_TYPE(RawKeyDown); |
+ CASE_TYPE(KeyDown); |
+ CASE_TYPE(KeyUp); |
+ CASE_TYPE(Char); |
+ CASE_TYPE(GestureScrollBegin); |
+ CASE_TYPE(GestureScrollEnd); |
+ CASE_TYPE(GestureScrollUpdate); |
+ CASE_TYPE(GestureFlingStart); |
+ CASE_TYPE(GestureFlingCancel); |
+ CASE_TYPE(GestureShowPress); |
+ CASE_TYPE(GestureTap); |
+ CASE_TYPE(GestureTapUnconfirmed); |
+ CASE_TYPE(GestureTapDown); |
+ CASE_TYPE(GestureTapCancel); |
+ CASE_TYPE(GestureDoubleTap); |
+ CASE_TYPE(GestureTwoFingerTap); |
+ CASE_TYPE(GestureLongPress); |
+ CASE_TYPE(GestureLongTap); |
+ CASE_TYPE(GesturePinchBegin); |
+ CASE_TYPE(GesturePinchEnd); |
+ CASE_TYPE(GesturePinchUpdate); |
+ CASE_TYPE(TouchStart); |
+ CASE_TYPE(TouchMove); |
+ CASE_TYPE(TouchEnd); |
+ CASE_TYPE(TouchCancel); |
+ } |
+ return ""; |
+} |
+ |
void RendererSchedulerImpl::UpdateForInputEventOnCompositorThread( |
blink::WebInputEvent::Type type, |
InputEventState input_event_state) { |
base::AutoLock lock(any_thread_lock_); |
base::TimeTicks now = helper_.Now(); |
- bool was_in_compositor_priority = InputSignalsSuggestCompositorPriority(now); |
+ bool already_scrolling = InputSignalsSuggestScrolling(now); |
bool was_awaiting_touch_start_response = |
AnyThread().awaiting_touch_start_response_; |
@@ -291,6 +355,7 @@ void RendererSchedulerImpl::UpdateForInputEventOnCompositorThread( |
switch (type) { |
case blink::WebInputEvent::TouchStart: |
AnyThread().awaiting_touch_start_response_ = true; |
+ AnyThread().last_touchstart_time_ = now; |
break; |
case blink::WebInputEvent::TouchMove: |
@@ -322,7 +387,7 @@ void RendererSchedulerImpl::UpdateForInputEventOnCompositorThread( |
} |
// Avoid unnecessary policy updates, while in compositor priority. |
- if (!was_in_compositor_priority || |
+ if (!already_scrolling || |
was_awaiting_touch_start_response != |
AnyThread().awaiting_touch_start_response_) { |
EnsureUrgentPolicyUpdatePostedOnMainThread(FROM_HERE); |
@@ -330,8 +395,12 @@ void RendererSchedulerImpl::UpdateForInputEventOnCompositorThread( |
AnyThread().last_input_signal_time_ = now; |
CompositorThreadOnly().last_input_type_ = type; |
- if (input_event_state == InputEventState::EVENT_FORWARDED_TO_MAIN_THREAD) |
+ if (input_event_state == InputEventState::EVENT_FORWARDED_TO_MAIN_THREAD) { |
+ TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), |
+ "InputEventState::EVENT_FORWARDED_TO_MAIN_THREAD", "type", |
+ WebInputEventToString(type)); |
AnyThread().pending_main_thread_input_event_count_++; |
+ } |
} |
void RendererSchedulerImpl::DidHandleInputEventOnMainThread( |
@@ -353,12 +422,12 @@ bool RendererSchedulerImpl::IsHighPriorityWorkAnticipated() { |
return false; |
MaybeUpdatePolicy(); |
- // The touchstart and compositor policies indicate a strong likelihood of |
- // high-priority work in the near future. |
- return MainThreadOnly().current_policy_ == Policy::COMPOSITOR_PRIORITY || |
- MainThreadOnly().current_policy_ == |
- Policy::COMPOSITOR_CRITICAL_PATH_PRIORITY || |
- MainThreadOnly().current_policy_ == Policy::TOUCHSTART_PRIORITY; |
+ // The touchstart and main-thread scrolling states indicate a strong |
+ // likelihood of high-priority work in the near future. |
+ UseCase use_case = MainThreadOnly().current_use_case_; |
+ return MainThreadOnly().scroll_expected_soon_ || |
+ use_case == UseCase::MAINTHREAD_SCROLLING || |
+ use_case == UseCase::TOUCHSTART; |
} |
bool RendererSchedulerImpl::ShouldYieldForHighPriorityWork() { |
@@ -367,25 +436,25 @@ bool RendererSchedulerImpl::ShouldYieldForHighPriorityWork() { |
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 (MainThreadOnly().current_policy_) { |
- case Policy::NORMAL: |
+ // We only yield if there's a urgent task to be run now, or we are expecting |
+ // one soon (touch start). |
+ // Note: even though the control queue has the highest 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 (MainThreadOnly().current_use_case_) { |
+ case UseCase::NOT_SCROLLING: |
Sami
2015/08/26 13:38:01
Could we not be expecting a scroll in this state?
alex clarke (OOO till 29th)
2015/08/27 12:02:51
Yeah we could. Maybe we should yeild in that situ
|
return false; |
- case Policy::COMPOSITOR_PRIORITY: |
- return !compositor_task_runner_->IsQueueEmpty(); |
+ case UseCase::COMPOSITOR_SCROLLING: |
+ return MainThreadOnly().scroll_expected_soon_; |
- case Policy::COMPOSITOR_CRITICAL_PATH_PRIORITY: |
+ case UseCase::MAINTHREAD_SCROLLING: |
return !compositor_task_runner_->IsQueueEmpty(); |
- case Policy::TOUCHSTART_PRIORITY: |
+ case UseCase::TOUCHSTART: |
return true; |
- case Policy::LOADING_PRIORITY: |
+ case UseCase::LOADING: |
return false; |
default: |
@@ -427,6 +496,41 @@ void RendererSchedulerImpl::ForceUpdatePolicy() { |
UpdatePolicyLocked(UpdateType::FORCE_UPDATE); |
} |
+bool RendererSchedulerImpl::ScrollExpectedSoon( |
+ UseCase use_case, |
+ const base::TimeTicks now, |
+ base::TimeDelta* new_policy_duration) const { |
+ if (use_case == UseCase::NOT_SCROLLING) { |
+ // If we've scrolled recently then future scrolling is likely. |
+ base::TimeDelta expect_subsequent_input_for = |
+ base::TimeDelta::FromMilliseconds(kExpectSubsequentInputMillis); |
+ if (AnyThread().last_input_signal_time_.is_null() || |
+ AnyThread().last_input_signal_time_ + expect_subsequent_input_for <= |
+ now) { |
+ return false; |
+ } |
+ *new_policy_duration = |
+ AnyThread().last_input_signal_time_ + expect_subsequent_input_for - now; |
+ return true; |
+ } |
+ |
+ if (use_case == UseCase::COMPOSITOR_SCROLLING) { |
+ // If we've only just started scrolling then, then future scrolling is |
+ // unlikely. |
+ base::TimeDelta minimum_typical_scroll_duration = |
+ base::TimeDelta::FromMilliseconds(kMinimumTypicalScrollDurationMillis); |
+ if (AnyThread().last_touchstart_time_.is_null() || |
Sami
2015/08/26 13:38:01
Touchstart doesn't get sent if there are no touch
alex clarke (OOO till 29th)
2015/08/27 12:02:51
Maybe this function is badly named then (see comme
|
+ AnyThread().last_touchstart_time_ + minimum_typical_scroll_duration <= |
+ now) { |
+ return true; |
+ } |
+ *new_policy_duration = AnyThread().last_touchstart_time_ + |
+ minimum_typical_scroll_duration - now; |
+ return false; |
+ } |
+ return false; |
Sami
2015/08/26 13:38:01
Should we always return true for main thread scrol
alex clarke (OOO till 29th)
2015/08/27 12:02:51
Good question. I think that depends on what we wa
|
+} |
+ |
void RendererSchedulerImpl::UpdatePolicyLocked(UpdateType update_type) { |
helper_.CheckOnValidThread(); |
any_thread_lock_.AssertAcquired(); |
@@ -436,14 +540,23 @@ void RendererSchedulerImpl::UpdatePolicyLocked(UpdateType update_type) { |
base::TimeTicks now = helper_.Now(); |
policy_may_need_update_.SetWhileLocked(false); |
- AnyThread().timer_tasks_seem_expensive_ = |
- MainThreadOnly().expected_short_idle_period_duration_ > |
- base::TimeDelta() && |
+ base::TimeDelta new_policy_duration; |
+ UseCase use_case = ComputeCurrentUseCase(now, &new_policy_duration); |
+ |
+ // Adjust the policy duration if |scroll_expected_soon| is likely to change. |
+ bool scroll_expected_soon = ScrollExpectedSoon(use_case, |
+ now, |
+ &new_policy_duration); |
+ bool loading_tasks_seem_expensive = |
+ MainThreadOnly().loading_task_cost_estimator_.expected_task_duration() > |
+ MainThreadOnly().expected_short_idle_period_duration_; |
+ bool timer_tasks_seem_expensive = |
MainThreadOnly().timer_task_cost_estimator_.expected_task_duration() > |
- MainThreadOnly().expected_short_idle_period_duration_; |
+ MainThreadOnly().expected_short_idle_period_duration_; |
+ MainThreadOnly().scroll_expected_soon_ = scroll_expected_soon; |
+ MainThreadOnly().loading_tasks_seem_expensive_ = loading_tasks_seem_expensive; |
+ MainThreadOnly().timer_tasks_seem_expensive_ = timer_tasks_seem_expensive; |
- base::TimeDelta new_policy_duration; |
- Policy new_policy = ComputeNewPolicy(now, &new_policy_duration); |
if (new_policy_duration > base::TimeDelta()) { |
MainThreadOnly().current_policy_expiration_time_ = |
now + new_policy_duration; |
@@ -453,73 +566,86 @@ void RendererSchedulerImpl::UpdatePolicyLocked(UpdateType update_type) { |
MainThreadOnly().current_policy_expiration_time_ = base::TimeTicks(); |
} |
- if (update_type == UpdateType::MAY_EARLY_OUT_IF_POLICY_UNCHANGED && |
- new_policy == MainThreadOnly().current_policy_) |
- return; |
- |
- TaskQueue::QueuePriority compositor_queue_priority = |
- TaskQueue::NORMAL_PRIORITY; |
- TaskQueue::QueuePriority loading_queue_priority = TaskQueue::NORMAL_PRIORITY; |
- TaskQueue::QueuePriority timer_queue_priority = |
- MainThreadOnly().timer_queue_suspend_count_ != 0 |
- ? TaskQueue::DISABLED_PRIORITY |
- : TaskQueue::NORMAL_PRIORITY; |
- |
- switch (new_policy) { |
- case Policy::COMPOSITOR_PRIORITY: |
- compositor_queue_priority = TaskQueue::HIGH_PRIORITY; |
+ Policy new_policy; |
+ bool block_expensive_tasks = false; |
+ switch (use_case) { |
+ case UseCase::COMPOSITOR_SCROLLING: |
+ if (scroll_expected_soon) |
+ block_expensive_tasks = true; |
+ else |
+ new_policy.loading_queue_priority_ = TaskQueue::HIGH_PRIORITY; |
break; |
- case Policy::COMPOSITOR_CRITICAL_PATH_PRIORITY: |
- compositor_queue_priority = TaskQueue::HIGH_PRIORITY; |
- loading_queue_priority = TaskQueue::DISABLED_PRIORITY; |
- timer_queue_priority = TaskQueue::DISABLED_PRIORITY; |
+ |
+ case UseCase::MAINTHREAD_SCROLLING: |
+ new_policy.compositor_queue_priority_ = TaskQueue::HIGH_PRIORITY; |
+ block_expensive_tasks = true; |
break; |
- case Policy::TOUCHSTART_PRIORITY: |
- compositor_queue_priority = TaskQueue::HIGH_PRIORITY; |
- loading_queue_priority = TaskQueue::DISABLED_PRIORITY; |
- timer_queue_priority = TaskQueue::DISABLED_PRIORITY; |
+ |
+ case UseCase::TOUCHSTART: |
+ new_policy.compositor_queue_priority_ = TaskQueue::HIGH_PRIORITY; |
+ new_policy.loading_queue_priority_ = TaskQueue::DISABLED_PRIORITY; |
+ new_policy.timer_queue_priority_ = TaskQueue::DISABLED_PRIORITY; |
Sami
2015/08/26 13:38:01
block_expensive_tasks = true?
alex clarke (OOO till 29th)
2015/08/27 12:02:51
We could do that, but it would be a nop. Do you st
Sami
2015/08/27 15:15:58
Yeah, I was thinking it would be better to have it
alex clarke (OOO till 29th)
2015/09/03 10:34:25
Done.
|
break; |
- case Policy::NORMAL: |
+ |
+ case UseCase::NOT_SCROLLING: |
+ if (scroll_expected_soon) |
+ block_expensive_tasks = true; |
+ else |
+ new_policy.loading_queue_priority_ = TaskQueue::HIGH_PRIORITY; |
break; |
- case Policy::LOADING_PRIORITY: |
- // We prioritize loading tasks by deprioritizing compositing and timers. |
- compositor_queue_priority = TaskQueue::BEST_EFFORT_PRIORITY; |
- timer_queue_priority = TaskQueue::BEST_EFFORT_PRIORITY; |
- // TODO(alexclarke): See if we can safely mark the loading task queue as |
- // high priority. |
+ |
+ case UseCase::LOADING: |
+ new_policy.loading_queue_priority_ = TaskQueue::HIGH_PRIORITY; |
+ new_policy.timer_queue_priority_ = TaskQueue::HIGH_PRIORITY; |
Sami
2015/08/26 13:38:01
Why are timers now high priority? They used to be
alex clarke (OOO till 29th)
2015/08/27 12:02:51
They don't need to be :)
|
break; |
default: |
NOTREACHED(); |
} |
- compositor_task_runner_->SetQueuePriority(compositor_queue_priority); |
- loading_task_runner_->SetQueuePriority(loading_queue_priority); |
- timer_task_runner_->SetQueuePriority(timer_queue_priority); |
+ if (block_expensive_tasks && loading_tasks_seem_expensive) |
+ new_policy.loading_queue_priority_ = TaskQueue::DISABLED_PRIORITY; |
- DCHECK(compositor_task_runner_->IsQueueEnabled()); |
- if (new_policy != Policy::TOUCHSTART_PRIORITY && |
- new_policy != Policy::COMPOSITOR_CRITICAL_PATH_PRIORITY) { |
- DCHECK(loading_task_runner_->IsQueueEnabled()); |
- } |
- MainThreadOnly().current_policy_ = new_policy; |
+ if ((block_expensive_tasks && timer_tasks_seem_expensive) || |
+ MainThreadOnly().timer_queue_suspend_count_ != 0) |
+ new_policy.timer_queue_priority_ = TaskQueue::DISABLED_PRIORITY; |
+ // Tracing is done before the early out check, because it's quite possible we |
+ // will otherwise miss this information in traces. |
TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID( |
TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), "RendererScheduler", |
this, AsValueLocked(now)); |
+ TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), "use_case", |
+ use_case); |
TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), |
- "RendererScheduler.policy", MainThreadOnly().current_policy_); |
+ "RendererScheduler.loading_tasks_seem_expensive", |
+ MainThreadOnly().loading_tasks_seem_expensive_); |
TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), |
"RendererScheduler.timer_tasks_seem_expensive", |
- AnyThread().timer_tasks_seem_expensive_); |
+ MainThreadOnly().timer_tasks_seem_expensive_); |
+ |
+ if (update_type == UpdateType::MAY_EARLY_OUT_IF_POLICY_UNCHANGED && |
+ use_case == MainThreadOnly().current_use_case_ && |
Sami
2015/08/26 13:38:01
Do we need to check if the use case changed? Could
alex clarke (OOO till 29th)
2015/08/27 12:02:51
Yeah I think we could do that.
|
+ new_policy == MainThreadOnly().current_policy_) { |
+ return; |
+ } |
+ |
+ compositor_task_runner_->SetQueuePriority( |
+ new_policy.compositor_queue_priority_); |
+ loading_task_runner_->SetQueuePriority(new_policy.loading_queue_priority_); |
+ timer_task_runner_->SetQueuePriority(new_policy.timer_queue_priority_); |
+ |
+ DCHECK(compositor_task_runner_->IsQueueEnabled()); |
+ MainThreadOnly().current_use_case_ = use_case; |
+ MainThreadOnly().current_policy_ = new_policy; |
} |
-bool RendererSchedulerImpl::InputSignalsSuggestCompositorPriority( |
+bool RendererSchedulerImpl::InputSignalsSuggestScrolling( |
base::TimeTicks now) const { |
base::TimeDelta unused_policy_duration; |
- switch (ComputeNewPolicy(now, &unused_policy_duration)) { |
- case Policy::TOUCHSTART_PRIORITY: |
- case Policy::COMPOSITOR_PRIORITY: |
- case Policy::COMPOSITOR_CRITICAL_PATH_PRIORITY: |
+ switch (ComputeCurrentUseCase(now, &unused_policy_duration)) { |
+ case UseCase::COMPOSITOR_SCROLLING: |
+ case UseCase::MAINTHREAD_SCROLLING: |
+ case UseCase::TOUCHSTART: |
return true; |
default: |
@@ -528,33 +654,34 @@ bool RendererSchedulerImpl::InputSignalsSuggestCompositorPriority( |
return false; |
} |
-RendererSchedulerImpl::Policy RendererSchedulerImpl::ComputeNewPolicy( |
+RendererSchedulerImpl::UseCase RendererSchedulerImpl::ComputeCurrentUseCase( |
base::TimeTicks now, |
base::TimeDelta* new_policy_duration) const { |
any_thread_lock_.AssertAcquired(); |
// Above all else we want to be responsive to user input. |
*new_policy_duration = TimeLeftInInputEscalatedPolicy(now); |
if (*new_policy_duration > base::TimeDelta()) { |
- if (AnyThread().awaiting_touch_start_response_) |
- return Policy::TOUCHSTART_PRIORITY; |
- // If BeginMainFrame is on the critical path, we want to try and prevent |
- // timers and loading tasks from running if we think they might be |
- // expensive. |
- // TODO(skyostil): Consider removing in_idle_period_ and |
Sami
2015/08/26 13:38:01
Wanna keep this todo since the code is still here?
alex clarke (OOO till 29th)
2015/08/27 12:02:51
Done.
|
- // HadAnIdlePeriodRecently() unless we need them here. |
- if (AnyThread().timer_tasks_seem_expensive_ && |
- AnyThread().begin_main_frame_on_critical_path_) { |
- return Policy::COMPOSITOR_CRITICAL_PATH_PRIORITY; |
+ // Has scrolling been fully established? |
+ if (AnyThread().awaiting_touch_start_response_) { |
+ // No., so arrange for compositor tasks to be run at the highest priority. |
Sami
2015/08/26 13:38:01
typo: .
alex clarke (OOO till 29th)
2015/08/27 12:02:51
Done.
|
+ return UseCase::TOUCHSTART; |
+ } |
+ // Yes scrolling has been established. If BeginMainFrame is on the critical |
+ // path, compositor tasks need to be prioritized, otherwise now might be a |
+ // good time to run potentially expensive work. |
+ if (AnyThread().begin_main_frame_on_critical_path_) { |
+ return UseCase::MAINTHREAD_SCROLLING; |
+ } else { |
+ return UseCase::COMPOSITOR_SCROLLING; |
} |
- return Policy::COMPOSITOR_PRIORITY; |
} |
if (AnyThread().rails_loading_priority_deadline_ > now) { |
*new_policy_duration = AnyThread().rails_loading_priority_deadline_ - now; |
- return Policy::LOADING_PRIORITY; |
+ return UseCase::LOADING; |
} |
- return Policy::NORMAL; |
+ return UseCase::NOT_SCROLLING; |
} |
base::TimeDelta RendererSchedulerImpl::TimeLeftInInputEscalatedPolicy( |
@@ -582,7 +709,7 @@ bool RendererSchedulerImpl::CanEnterLongIdlePeriod( |
helper_.CheckOnValidThread(); |
MaybeUpdatePolicy(); |
- if (MainThreadOnly().current_policy_ == Policy::TOUCHSTART_PRIORITY) { |
+ if (MainThreadOnly().current_use_case_ == UseCase::TOUCHSTART) { |
// 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 = |
@@ -609,17 +736,17 @@ void RendererSchedulerImpl::ResumeTimerQueue() { |
} |
// static |
-const char* RendererSchedulerImpl::PolicyToString(Policy policy) { |
- switch (policy) { |
- case Policy::NORMAL: |
- return "normal"; |
- case Policy::COMPOSITOR_PRIORITY: |
- return "compositor"; |
- case Policy::COMPOSITOR_CRITICAL_PATH_PRIORITY: |
- return "compositor_critical_path"; |
- case Policy::TOUCHSTART_PRIORITY: |
+const char* RendererSchedulerImpl::UseCaseToString(UseCase use_case) { |
+ switch (use_case) { |
+ case UseCase::NOT_SCROLLING: |
+ return "not_scrolling"; |
+ case UseCase::COMPOSITOR_SCROLLING: |
+ return "compositor_scrolling"; |
+ case UseCase::MAINTHREAD_SCROLLING: |
+ return "mainthread_scrolling"; |
+ case UseCase::TOUCHSTART: |
return "touchstart"; |
- case Policy::LOADING_PRIORITY: |
+ case UseCase::LOADING: |
return "loading"; |
default: |
NOTREACHED(); |
@@ -643,8 +770,14 @@ RendererSchedulerImpl::AsValueLocked(base::TimeTicks optional_now) const { |
scoped_refptr<base::trace_event::TracedValue> state = |
new base::trace_event::TracedValue(); |
- state->SetString("current_policy", |
- PolicyToString(MainThreadOnly().current_policy_)); |
+ state->SetString("current_use_case", |
Sami
2015/08/26 13:38:01
Do we want to trace the policy too? One way would
alex clarke (OOO till 29th)
2015/08/27 12:02:51
We could do that, mind you it's already logged in
Sami
2015/08/27 15:15:58
Right, let's add it once it actually adds new info
alex clarke (OOO till 29th)
2015/09/03 10:34:25
Acknowledged.
|
+ UseCaseToString(MainThreadOnly().current_use_case_)); |
+ state->SetBoolean("loading_tasks_seem_expensive", |
+ MainThreadOnly().loading_tasks_seem_expensive_); |
+ state->SetBoolean("timer_tasks_seem_expensive", |
+ MainThreadOnly().timer_tasks_seem_expensive_); |
+ state->SetBoolean("scroll_expected_soon", |
+ MainThreadOnly().scroll_expected_soon_); |
state->SetString("idle_period_state", |
IdleHelper::IdlePeriodStateToString( |
idle_helper_.SchedulerIdlePeriodState())); |
@@ -665,6 +798,10 @@ RendererSchedulerImpl::AsValueLocked(base::TimeTicks optional_now) const { |
AnyThread().awaiting_touch_start_response_); |
state->SetBoolean("begin_main_frame_on_critical_path", |
AnyThread().begin_main_frame_on_critical_path_); |
+ state->SetDouble("expected_loading_task_duration", |
+ MainThreadOnly() |
+ .loading_task_cost_estimator_.expected_task_duration() |
+ .InMillisecondsF()); |
state->SetDouble("expected_timer_task_duration", |
MainThreadOnly() |
.timer_task_cost_estimator_.expected_task_duration() |
@@ -673,8 +810,6 @@ RendererSchedulerImpl::AsValueLocked(base::TimeTicks optional_now) const { |
state->SetDouble( |
"expected_short_idle_period_duration", |
MainThreadOnly().expected_short_idle_period_duration_.InMillisecondsF()); |
- state->SetBoolean("timer_tasks_seem_expensive", |
- AnyThread().timer_tasks_seem_expensive_); |
state->SetDouble("estimated_next_frame_begin", |
(MainThreadOnly().estimated_next_frame_begin_ - |
base::TimeTicks()).InMillisecondsF()); |