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 "components/scheduler/renderer/renderer_scheduler_impl.h" | 5 #include "components/scheduler/renderer/renderer_scheduler_impl.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/debug/stack_trace.h" | 8 #include "base/debug/stack_trace.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" |
| 11 #include "cc/output/begin_frame_args.h" | 11 #include "cc/output/begin_frame_args.h" |
| 12 #include "components/scheduler/child/scheduler_task_runner_delegate.h" | 12 #include "components/scheduler/child/scheduler_task_runner_delegate.h" |
| 13 #include "components/scheduler/child/task_queue_impl.h" | 13 #include "components/scheduler/child/task_queue_impl.h" |
| 14 #include "components/scheduler/child/task_queue_selector.h" | 14 #include "components/scheduler/child/task_queue_selector.h" |
| 15 | 15 |
| 16 namespace scheduler { | 16 namespace scheduler { |
| 17 namespace { | 17 namespace { |
| 18 const int kTimerTaskEstimationSampleCount = 4 * 60; | 18 const int kLoadingTaskEstimationSampleCount = 200; |
| 19 const double kTimerTaskEstimationPercentile = 80; | 19 const double kLoadingTaskEstimationPercentile = 90; |
| 20 const int kTimerTaskEstimationSampleCount = 200; | |
| 21 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
| |
| 20 const int kShortIdlePeriodDurationSampleCount = 10; | 22 const int kShortIdlePeriodDurationSampleCount = 10; |
| 21 const double kShortIdlePeriodDurationPercentile = 20; | 23 const double kShortIdlePeriodDurationPercentile = 20; |
| 22 } | 24 } |
| 23 | 25 |
| 24 RendererSchedulerImpl::RendererSchedulerImpl( | 26 RendererSchedulerImpl::RendererSchedulerImpl( |
| 25 scoped_refptr<SchedulerTaskRunnerDelegate> main_task_runner) | 27 scoped_refptr<SchedulerTaskRunnerDelegate> main_task_runner) |
| 26 : helper_(main_task_runner, | 28 : helper_(main_task_runner, |
| 27 "renderer.scheduler", | 29 "renderer.scheduler", |
| 28 TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), | 30 TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), |
| 29 TRACE_DISABLED_BY_DEFAULT("renderer.scheduler.debug")), | 31 TRACE_DISABLED_BY_DEFAULT("renderer.scheduler.debug")), |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 47 base::Bind(&RendererSchedulerImpl::UpdatePolicy, | 49 base::Bind(&RendererSchedulerImpl::UpdatePolicy, |
| 48 base::Unretained(this)), | 50 base::Unretained(this)), |
| 49 helper_.ControlTaskRunner()), | 51 helper_.ControlTaskRunner()), |
| 50 policy_may_need_update_(&any_thread_lock_), | 52 policy_may_need_update_(&any_thread_lock_), |
| 51 weak_factory_(this) { | 53 weak_factory_(this) { |
| 52 update_policy_closure_ = base::Bind(&RendererSchedulerImpl::UpdatePolicy, | 54 update_policy_closure_ = base::Bind(&RendererSchedulerImpl::UpdatePolicy, |
| 53 weak_factory_.GetWeakPtr()); | 55 weak_factory_.GetWeakPtr()); |
| 54 end_renderer_hidden_idle_period_closure_.Reset(base::Bind( | 56 end_renderer_hidden_idle_period_closure_.Reset(base::Bind( |
| 55 &RendererSchedulerImpl::EndIdlePeriod, weak_factory_.GetWeakPtr())); | 57 &RendererSchedulerImpl::EndIdlePeriod, weak_factory_.GetWeakPtr())); |
| 56 | 58 |
| 59 loading_task_runner_->AddTaskObserver( | |
| 60 &MainThreadOnly().loading_task_cost_estimator_); | |
| 61 | |
| 57 timer_task_runner_->AddTaskObserver( | 62 timer_task_runner_->AddTaskObserver( |
| 58 &MainThreadOnly().timer_task_cost_estimator_); | 63 &MainThreadOnly().timer_task_cost_estimator_); |
| 59 | 64 |
| 60 TRACE_EVENT_OBJECT_CREATED_WITH_ID( | 65 TRACE_EVENT_OBJECT_CREATED_WITH_ID( |
| 61 TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), "RendererScheduler", | 66 TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), "RendererScheduler", |
| 62 this); | 67 this); |
| 68 | |
| 69 // Make sure that we don't initially assume there is no idle time. | |
| 70 MainThreadOnly().short_idle_period_duration_.InsertSample( | |
| 71 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.
| |
| 63 } | 72 } |
| 64 | 73 |
| 65 RendererSchedulerImpl::~RendererSchedulerImpl() { | 74 RendererSchedulerImpl::~RendererSchedulerImpl() { |
| 66 TRACE_EVENT_OBJECT_DELETED_WITH_ID( | 75 TRACE_EVENT_OBJECT_DELETED_WITH_ID( |
| 67 TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), "RendererScheduler", | 76 TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), "RendererScheduler", |
| 68 this); | 77 this); |
| 69 timer_task_runner_->RemoveTaskObserver( | 78 timer_task_runner_->RemoveTaskObserver( |
| 70 &MainThreadOnly().timer_task_cost_estimator_); | 79 &MainThreadOnly().timer_task_cost_estimator_); |
| 71 // Ensure the renderer scheduler was shut down explicitly, because otherwise | 80 // Ensure the renderer scheduler was shut down explicitly, because otherwise |
| 72 // we could end up having stale pointers to the Blink heap which has been | 81 // we could end up having stale pointers to the Blink heap which has been |
| 73 // terminated by this point. | 82 // terminated by this point. |
| 74 DCHECK(MainThreadOnly().was_shutdown_); | 83 DCHECK(MainThreadOnly().was_shutdown_); |
| 75 } | 84 } |
| 76 | 85 |
| 86 RendererSchedulerImpl::Policy::Policy() | |
| 87 : compositor_queue_priority_(TaskQueue::NORMAL_PRIORITY), | |
| 88 loading_queue_priority_(TaskQueue::NORMAL_PRIORITY), | |
| 89 timer_queue_priority_(TaskQueue::NORMAL_PRIORITY) {} | |
| 90 | |
| 77 RendererSchedulerImpl::MainThreadOnly::MainThreadOnly() | 91 RendererSchedulerImpl::MainThreadOnly::MainThreadOnly() |
| 78 : timer_task_cost_estimator_(kTimerTaskEstimationSampleCount, | 92 : loading_task_cost_estimator_(kLoadingTaskEstimationSampleCount, |
| 93 kLoadingTaskEstimationPercentile), | |
| 94 timer_task_cost_estimator_(kTimerTaskEstimationSampleCount, | |
| 79 kTimerTaskEstimationPercentile), | 95 kTimerTaskEstimationPercentile), |
| 80 short_idle_period_duration_(kShortIdlePeriodDurationSampleCount), | 96 short_idle_period_duration_(kShortIdlePeriodDurationSampleCount), |
| 81 current_policy_(Policy::NORMAL), | 97 current_use_case_(UseCase::NOT_SCROLLING), |
| 82 timer_queue_suspend_count_(0), | 98 timer_queue_suspend_count_(0), |
| 83 renderer_hidden_(false), | 99 renderer_hidden_(false), |
| 84 was_shutdown_(false) {} | 100 was_shutdown_(false), |
| 101 loading_tasks_seem_expensive_(false), | |
| 102 timer_tasks_seem_expensive_(false) {} | |
| 85 | 103 |
| 86 RendererSchedulerImpl::MainThreadOnly::~MainThreadOnly() {} | 104 RendererSchedulerImpl::MainThreadOnly::~MainThreadOnly() {} |
| 87 | 105 |
| 88 RendererSchedulerImpl::AnyThread::AnyThread() | 106 RendererSchedulerImpl::AnyThread::AnyThread() |
| 89 : pending_main_thread_input_event_count_(0), | 107 : pending_main_thread_input_event_count_(0), |
| 90 awaiting_touch_start_response_(false), | 108 awaiting_touch_start_response_(false), |
| 91 in_idle_period_(false), | 109 in_idle_period_(false), |
| 92 begin_main_frame_on_critical_path_(false), | 110 begin_main_frame_on_critical_path_(false) {} |
| 93 timer_tasks_seem_expensive_(false) {} | |
| 94 | 111 |
| 95 RendererSchedulerImpl::CompositorThreadOnly::CompositorThreadOnly() | 112 RendererSchedulerImpl::CompositorThreadOnly::CompositorThreadOnly() |
| 96 : last_input_type_(blink::WebInputEvent::Undefined) { | 113 : last_input_type_(blink::WebInputEvent::Undefined) { |
| 97 } | 114 } |
| 98 | 115 |
| 99 RendererSchedulerImpl::CompositorThreadOnly::~CompositorThreadOnly() { | 116 RendererSchedulerImpl::CompositorThreadOnly::~CompositorThreadOnly() { |
| 100 } | 117 } |
| 101 | 118 |
| 102 void RendererSchedulerImpl::Shutdown() { | 119 void RendererSchedulerImpl::Shutdown() { |
| 103 helper_.Shutdown(); | 120 helper_.Shutdown(); |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 169 | 186 |
| 170 base::TimeTicks now(helper_.Now()); | 187 base::TimeTicks now(helper_.Now()); |
| 171 if (now < MainThreadOnly().estimated_next_frame_begin_) { | 188 if (now < MainThreadOnly().estimated_next_frame_begin_) { |
| 172 // TODO(rmcilroy): Consider reducing the idle period based on the runtime of | 189 // TODO(rmcilroy): Consider reducing the idle period based on the runtime of |
| 173 // the next pending delayed tasks (as currently done in for long idle times) | 190 // the next pending delayed tasks (as currently done in for long idle times) |
| 174 idle_helper_.StartIdlePeriod( | 191 idle_helper_.StartIdlePeriod( |
| 175 IdleHelper::IdlePeriodState::IN_SHORT_IDLE_PERIOD, now, | 192 IdleHelper::IdlePeriodState::IN_SHORT_IDLE_PERIOD, now, |
| 176 MainThreadOnly().estimated_next_frame_begin_); | 193 MainThreadOnly().estimated_next_frame_begin_); |
| 177 MainThreadOnly().short_idle_period_duration_.InsertSample( | 194 MainThreadOnly().short_idle_period_duration_.InsertSample( |
| 178 MainThreadOnly().estimated_next_frame_begin_ - now); | 195 MainThreadOnly().estimated_next_frame_begin_ - now); |
| 179 MainThreadOnly().expected_short_idle_period_duration_ = | 196 } else { |
| 180 MainThreadOnly().short_idle_period_duration_.Percentile( | 197 // There was no idle time :( |
| 181 kShortIdlePeriodDurationPercentile); | 198 MainThreadOnly().short_idle_period_duration_.InsertSample( |
| 199 base::TimeDelta()); | |
| 182 } | 200 } |
| 201 | |
| 202 MainThreadOnly().expected_short_idle_period_duration_ = | |
| 203 MainThreadOnly().short_idle_period_duration_.Percentile( | |
| 204 kShortIdlePeriodDurationPercentile); | |
| 183 } | 205 } |
| 184 | 206 |
| 185 void RendererSchedulerImpl::BeginFrameNotExpectedSoon() { | 207 void RendererSchedulerImpl::BeginFrameNotExpectedSoon() { |
| 186 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), | 208 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), |
| 187 "RendererSchedulerImpl::BeginFrameNotExpectedSoon"); | 209 "RendererSchedulerImpl::BeginFrameNotExpectedSoon"); |
| 188 helper_.CheckOnValidThread(); | 210 helper_.CheckOnValidThread(); |
| 189 if (helper_.IsShutdown()) | 211 if (helper_.IsShutdown()) |
| 190 return; | 212 return; |
| 191 | 213 |
| 192 idle_helper_.EnableLongIdlePeriod(); | 214 idle_helper_.EnableLongIdlePeriod(); |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 271 } | 293 } |
| 272 | 294 |
| 273 void RendererSchedulerImpl::DidAnimateForInputOnCompositorThread() { | 295 void RendererSchedulerImpl::DidAnimateForInputOnCompositorThread() { |
| 274 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), | 296 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), |
| 275 "RendererSchedulerImpl::DidAnimateForInputOnCompositorThread"); | 297 "RendererSchedulerImpl::DidAnimateForInputOnCompositorThread"); |
| 276 UpdateForInputEventOnCompositorThread( | 298 UpdateForInputEventOnCompositorThread( |
| 277 blink::WebInputEvent::Undefined, | 299 blink::WebInputEvent::Undefined, |
| 278 InputEventState::EVENT_CONSUMED_BY_COMPOSITOR); | 300 InputEventState::EVENT_CONSUMED_BY_COMPOSITOR); |
| 279 } | 301 } |
| 280 | 302 |
| 303 const char* WebInputEventToString(blink::WebInputEvent::Type type) { | |
| 304 #define CASE_TYPE(t) \ | |
| 305 case blink::WebInputEvent::t: \ | |
| 306 return #t | |
| 307 switch (type) { | |
| 308 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.
| |
| 309 CASE_TYPE(MouseDown); | |
| 310 CASE_TYPE(MouseUp); | |
| 311 CASE_TYPE(MouseMove); | |
| 312 CASE_TYPE(MouseEnter); | |
| 313 CASE_TYPE(MouseLeave); | |
| 314 CASE_TYPE(ContextMenu); | |
| 315 CASE_TYPE(MouseWheel); | |
| 316 CASE_TYPE(RawKeyDown); | |
| 317 CASE_TYPE(KeyDown); | |
| 318 CASE_TYPE(KeyUp); | |
| 319 CASE_TYPE(Char); | |
| 320 CASE_TYPE(GestureScrollBegin); | |
| 321 CASE_TYPE(GestureScrollEnd); | |
| 322 CASE_TYPE(GestureScrollUpdate); | |
| 323 CASE_TYPE(GestureFlingStart); | |
| 324 CASE_TYPE(GestureFlingCancel); | |
| 325 CASE_TYPE(GestureShowPress); | |
| 326 CASE_TYPE(GestureTap); | |
| 327 CASE_TYPE(GestureTapUnconfirmed); | |
| 328 CASE_TYPE(GestureTapDown); | |
| 329 CASE_TYPE(GestureTapCancel); | |
| 330 CASE_TYPE(GestureDoubleTap); | |
| 331 CASE_TYPE(GestureTwoFingerTap); | |
| 332 CASE_TYPE(GestureLongPress); | |
| 333 CASE_TYPE(GestureLongTap); | |
| 334 CASE_TYPE(GesturePinchBegin); | |
| 335 CASE_TYPE(GesturePinchEnd); | |
| 336 CASE_TYPE(GesturePinchUpdate); | |
| 337 CASE_TYPE(TouchStart); | |
| 338 CASE_TYPE(TouchMove); | |
| 339 CASE_TYPE(TouchEnd); | |
| 340 CASE_TYPE(TouchCancel); | |
| 341 } | |
| 342 return ""; | |
| 343 } | |
| 344 | |
| 281 void RendererSchedulerImpl::UpdateForInputEventOnCompositorThread( | 345 void RendererSchedulerImpl::UpdateForInputEventOnCompositorThread( |
| 282 blink::WebInputEvent::Type type, | 346 blink::WebInputEvent::Type type, |
| 283 InputEventState input_event_state) { | 347 InputEventState input_event_state) { |
| 284 base::AutoLock lock(any_thread_lock_); | 348 base::AutoLock lock(any_thread_lock_); |
| 285 base::TimeTicks now = helper_.Now(); | 349 base::TimeTicks now = helper_.Now(); |
| 286 bool was_in_compositor_priority = InputSignalsSuggestCompositorPriority(now); | 350 bool already_scrolling = InputSignalsSuggestScrolling(now); |
| 287 bool was_awaiting_touch_start_response = | 351 bool was_awaiting_touch_start_response = |
| 288 AnyThread().awaiting_touch_start_response_; | 352 AnyThread().awaiting_touch_start_response_; |
| 289 | 353 |
| 290 if (type) { | 354 if (type) { |
| 291 switch (type) { | 355 switch (type) { |
| 292 case blink::WebInputEvent::TouchStart: | 356 case blink::WebInputEvent::TouchStart: |
| 293 AnyThread().awaiting_touch_start_response_ = true; | 357 AnyThread().awaiting_touch_start_response_ = true; |
| 358 AnyThread().last_touchstart_time_ = now; | |
| 294 break; | 359 break; |
| 295 | 360 |
| 296 case blink::WebInputEvent::TouchMove: | 361 case blink::WebInputEvent::TouchMove: |
| 297 // Observation of consecutive touchmoves is a strong signal that the | 362 // Observation of consecutive touchmoves is a strong signal that the |
| 298 // page is consuming the touch sequence, in which case touchstart | 363 // page is consuming the touch sequence, in which case touchstart |
| 299 // response prioritization is no longer necessary. Otherwise, the | 364 // response prioritization is no longer necessary. Otherwise, the |
| 300 // initial touchmove should preserve the touchstart response pending | 365 // initial touchmove should preserve the touchstart response pending |
| 301 // state. | 366 // state. |
| 302 if (AnyThread().awaiting_touch_start_response_ && | 367 if (AnyThread().awaiting_touch_start_response_ && |
| 303 CompositorThreadOnly().last_input_type_ == | 368 CompositorThreadOnly().last_input_type_ == |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 315 // meaningful touchstart response and should not impact task priority. | 380 // meaningful touchstart response and should not impact task priority. |
| 316 break; | 381 break; |
| 317 | 382 |
| 318 default: | 383 default: |
| 319 AnyThread().awaiting_touch_start_response_ = false; | 384 AnyThread().awaiting_touch_start_response_ = false; |
| 320 break; | 385 break; |
| 321 } | 386 } |
| 322 } | 387 } |
| 323 | 388 |
| 324 // Avoid unnecessary policy updates, while in compositor priority. | 389 // Avoid unnecessary policy updates, while in compositor priority. |
| 325 if (!was_in_compositor_priority || | 390 if (!already_scrolling || |
| 326 was_awaiting_touch_start_response != | 391 was_awaiting_touch_start_response != |
| 327 AnyThread().awaiting_touch_start_response_) { | 392 AnyThread().awaiting_touch_start_response_) { |
| 328 EnsureUrgentPolicyUpdatePostedOnMainThread(FROM_HERE); | 393 EnsureUrgentPolicyUpdatePostedOnMainThread(FROM_HERE); |
| 329 } | 394 } |
| 330 AnyThread().last_input_signal_time_ = now; | 395 AnyThread().last_input_signal_time_ = now; |
| 331 CompositorThreadOnly().last_input_type_ = type; | 396 CompositorThreadOnly().last_input_type_ = type; |
| 332 | 397 |
| 333 if (input_event_state == InputEventState::EVENT_FORWARDED_TO_MAIN_THREAD) | 398 if (input_event_state == InputEventState::EVENT_FORWARDED_TO_MAIN_THREAD) { |
| 399 TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), | |
| 400 "InputEventState::EVENT_FORWARDED_TO_MAIN_THREAD", "type", | |
| 401 WebInputEventToString(type)); | |
| 334 AnyThread().pending_main_thread_input_event_count_++; | 402 AnyThread().pending_main_thread_input_event_count_++; |
| 403 } | |
| 335 } | 404 } |
| 336 | 405 |
| 337 void RendererSchedulerImpl::DidHandleInputEventOnMainThread( | 406 void RendererSchedulerImpl::DidHandleInputEventOnMainThread( |
| 338 const blink::WebInputEvent& web_input_event) { | 407 const blink::WebInputEvent& web_input_event) { |
| 339 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), | 408 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), |
| 340 "RendererSchedulerImpl::DidHandleInputEventOnMainThread"); | 409 "RendererSchedulerImpl::DidHandleInputEventOnMainThread"); |
| 341 helper_.CheckOnValidThread(); | 410 helper_.CheckOnValidThread(); |
| 342 if (ShouldPrioritizeInputEvent(web_input_event)) { | 411 if (ShouldPrioritizeInputEvent(web_input_event)) { |
| 343 base::AutoLock lock(any_thread_lock_); | 412 base::AutoLock lock(any_thread_lock_); |
| 344 AnyThread().last_input_signal_time_ = helper_.Now(); | 413 AnyThread().last_input_signal_time_ = helper_.Now(); |
| 345 if (AnyThread().pending_main_thread_input_event_count_ > 0) | 414 if (AnyThread().pending_main_thread_input_event_count_ > 0) |
| 346 AnyThread().pending_main_thread_input_event_count_--; | 415 AnyThread().pending_main_thread_input_event_count_--; |
| 347 } | 416 } |
| 348 } | 417 } |
| 349 | 418 |
| 350 bool RendererSchedulerImpl::IsHighPriorityWorkAnticipated() { | 419 bool RendererSchedulerImpl::IsHighPriorityWorkAnticipated() { |
| 351 helper_.CheckOnValidThread(); | 420 helper_.CheckOnValidThread(); |
| 352 if (helper_.IsShutdown()) | 421 if (helper_.IsShutdown()) |
| 353 return false; | 422 return false; |
| 354 | 423 |
| 355 MaybeUpdatePolicy(); | 424 MaybeUpdatePolicy(); |
| 356 // The touchstart and compositor policies indicate a strong likelihood of | 425 // The touchstart and main-thread scrolling states indicate a strong |
| 357 // high-priority work in the near future. | 426 // likelihood of high-priority work in the near future. |
| 358 return MainThreadOnly().current_policy_ == Policy::COMPOSITOR_PRIORITY || | 427 UseCase use_case = MainThreadOnly().current_use_case_; |
| 359 MainThreadOnly().current_policy_ == | 428 return MainThreadOnly().scroll_expected_soon_ || |
| 360 Policy::COMPOSITOR_CRITICAL_PATH_PRIORITY || | 429 use_case == UseCase::MAINTHREAD_SCROLLING || |
| 361 MainThreadOnly().current_policy_ == Policy::TOUCHSTART_PRIORITY; | 430 use_case == UseCase::TOUCHSTART; |
| 362 } | 431 } |
| 363 | 432 |
| 364 bool RendererSchedulerImpl::ShouldYieldForHighPriorityWork() { | 433 bool RendererSchedulerImpl::ShouldYieldForHighPriorityWork() { |
| 365 helper_.CheckOnValidThread(); | 434 helper_.CheckOnValidThread(); |
| 366 if (helper_.IsShutdown()) | 435 if (helper_.IsShutdown()) |
| 367 return false; | 436 return false; |
| 368 | 437 |
| 369 MaybeUpdatePolicy(); | 438 MaybeUpdatePolicy(); |
| 370 // We only yield if we are in the compositor priority and there is compositor | 439 // We only yield if there's a urgent task to be run now, or we are expecting |
| 371 // work outstanding, or if we are in the touchstart response priority. | 440 // one soon (touch start). |
| 372 // Note: even though the control queue is higher priority we don't yield for | 441 // Note: even though the control queue has the highest priority we don't yield |
| 373 // it since these tasks are not user-provided work and they are only intended | 442 // for it since these tasks are not user-provided work and they are only |
| 374 // to run before the next task, not interrupt the tasks. | 443 // intended to run before the next task, not interrupt the tasks. |
| 375 switch (MainThreadOnly().current_policy_) { | 444 switch (MainThreadOnly().current_use_case_) { |
| 376 case Policy::NORMAL: | 445 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
| |
| 377 return false; | 446 return false; |
| 378 | 447 |
| 379 case Policy::COMPOSITOR_PRIORITY: | 448 case UseCase::COMPOSITOR_SCROLLING: |
| 449 return MainThreadOnly().scroll_expected_soon_; | |
| 450 | |
| 451 case UseCase::MAINTHREAD_SCROLLING: | |
| 380 return !compositor_task_runner_->IsQueueEmpty(); | 452 return !compositor_task_runner_->IsQueueEmpty(); |
| 381 | 453 |
| 382 case Policy::COMPOSITOR_CRITICAL_PATH_PRIORITY: | 454 case UseCase::TOUCHSTART: |
| 383 return !compositor_task_runner_->IsQueueEmpty(); | |
| 384 | |
| 385 case Policy::TOUCHSTART_PRIORITY: | |
| 386 return true; | 455 return true; |
| 387 | 456 |
| 388 case Policy::LOADING_PRIORITY: | 457 case UseCase::LOADING: |
| 389 return false; | 458 return false; |
| 390 | 459 |
| 391 default: | 460 default: |
| 392 NOTREACHED(); | 461 NOTREACHED(); |
| 393 return false; | 462 return false; |
| 394 } | 463 } |
| 395 } | 464 } |
| 396 | 465 |
| 397 base::TimeTicks RendererSchedulerImpl::CurrentIdleTaskDeadlineForTesting() | 466 base::TimeTicks RendererSchedulerImpl::CurrentIdleTaskDeadlineForTesting() |
| 398 const { | 467 const { |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 420 void RendererSchedulerImpl::UpdatePolicy() { | 489 void RendererSchedulerImpl::UpdatePolicy() { |
| 421 base::AutoLock lock(any_thread_lock_); | 490 base::AutoLock lock(any_thread_lock_); |
| 422 UpdatePolicyLocked(UpdateType::MAY_EARLY_OUT_IF_POLICY_UNCHANGED); | 491 UpdatePolicyLocked(UpdateType::MAY_EARLY_OUT_IF_POLICY_UNCHANGED); |
| 423 } | 492 } |
| 424 | 493 |
| 425 void RendererSchedulerImpl::ForceUpdatePolicy() { | 494 void RendererSchedulerImpl::ForceUpdatePolicy() { |
| 426 base::AutoLock lock(any_thread_lock_); | 495 base::AutoLock lock(any_thread_lock_); |
| 427 UpdatePolicyLocked(UpdateType::FORCE_UPDATE); | 496 UpdatePolicyLocked(UpdateType::FORCE_UPDATE); |
| 428 } | 497 } |
| 429 | 498 |
| 499 bool RendererSchedulerImpl::ScrollExpectedSoon( | |
| 500 UseCase use_case, | |
| 501 const base::TimeTicks now, | |
| 502 base::TimeDelta* new_policy_duration) const { | |
| 503 if (use_case == UseCase::NOT_SCROLLING) { | |
| 504 // If we've scrolled recently then future scrolling is likely. | |
| 505 base::TimeDelta expect_subsequent_input_for = | |
| 506 base::TimeDelta::FromMilliseconds(kExpectSubsequentInputMillis); | |
| 507 if (AnyThread().last_input_signal_time_.is_null() || | |
| 508 AnyThread().last_input_signal_time_ + expect_subsequent_input_for <= | |
| 509 now) { | |
| 510 return false; | |
| 511 } | |
| 512 *new_policy_duration = | |
| 513 AnyThread().last_input_signal_time_ + expect_subsequent_input_for - now; | |
| 514 return true; | |
| 515 } | |
| 516 | |
| 517 if (use_case == UseCase::COMPOSITOR_SCROLLING) { | |
| 518 // If we've only just started scrolling then, then future scrolling is | |
| 519 // unlikely. | |
| 520 base::TimeDelta minimum_typical_scroll_duration = | |
| 521 base::TimeDelta::FromMilliseconds(kMinimumTypicalScrollDurationMillis); | |
| 522 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
| |
| 523 AnyThread().last_touchstart_time_ + minimum_typical_scroll_duration <= | |
| 524 now) { | |
| 525 return true; | |
| 526 } | |
| 527 *new_policy_duration = AnyThread().last_touchstart_time_ + | |
| 528 minimum_typical_scroll_duration - now; | |
| 529 return false; | |
| 530 } | |
| 531 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
| |
| 532 } | |
| 533 | |
| 430 void RendererSchedulerImpl::UpdatePolicyLocked(UpdateType update_type) { | 534 void RendererSchedulerImpl::UpdatePolicyLocked(UpdateType update_type) { |
| 431 helper_.CheckOnValidThread(); | 535 helper_.CheckOnValidThread(); |
| 432 any_thread_lock_.AssertAcquired(); | 536 any_thread_lock_.AssertAcquired(); |
| 433 if (helper_.IsShutdown()) | 537 if (helper_.IsShutdown()) |
| 434 return; | 538 return; |
| 435 | 539 |
| 436 base::TimeTicks now = helper_.Now(); | 540 base::TimeTicks now = helper_.Now(); |
| 437 policy_may_need_update_.SetWhileLocked(false); | 541 policy_may_need_update_.SetWhileLocked(false); |
| 438 | 542 |
| 439 AnyThread().timer_tasks_seem_expensive_ = | 543 base::TimeDelta new_policy_duration; |
| 440 MainThreadOnly().expected_short_idle_period_duration_ > | 544 UseCase use_case = ComputeCurrentUseCase(now, &new_policy_duration); |
| 441 base::TimeDelta() && | 545 |
| 546 // Adjust the policy duration if |scroll_expected_soon| is likely to change. | |
| 547 bool scroll_expected_soon = ScrollExpectedSoon(use_case, | |
| 548 now, | |
| 549 &new_policy_duration); | |
| 550 bool loading_tasks_seem_expensive = | |
| 551 MainThreadOnly().loading_task_cost_estimator_.expected_task_duration() > | |
| 552 MainThreadOnly().expected_short_idle_period_duration_; | |
| 553 bool timer_tasks_seem_expensive = | |
| 442 MainThreadOnly().timer_task_cost_estimator_.expected_task_duration() > | 554 MainThreadOnly().timer_task_cost_estimator_.expected_task_duration() > |
| 443 MainThreadOnly().expected_short_idle_period_duration_; | 555 MainThreadOnly().expected_short_idle_period_duration_; |
| 556 MainThreadOnly().scroll_expected_soon_ = scroll_expected_soon; | |
| 557 MainThreadOnly().loading_tasks_seem_expensive_ = loading_tasks_seem_expensive; | |
| 558 MainThreadOnly().timer_tasks_seem_expensive_ = timer_tasks_seem_expensive; | |
| 444 | 559 |
| 445 base::TimeDelta new_policy_duration; | |
| 446 Policy new_policy = ComputeNewPolicy(now, &new_policy_duration); | |
| 447 if (new_policy_duration > base::TimeDelta()) { | 560 if (new_policy_duration > base::TimeDelta()) { |
| 448 MainThreadOnly().current_policy_expiration_time_ = | 561 MainThreadOnly().current_policy_expiration_time_ = |
| 449 now + new_policy_duration; | 562 now + new_policy_duration; |
| 450 delayed_update_policy_runner_.SetDeadline(FROM_HERE, new_policy_duration, | 563 delayed_update_policy_runner_.SetDeadline(FROM_HERE, new_policy_duration, |
| 451 now); | 564 now); |
| 452 } else { | 565 } else { |
| 453 MainThreadOnly().current_policy_expiration_time_ = base::TimeTicks(); | 566 MainThreadOnly().current_policy_expiration_time_ = base::TimeTicks(); |
| 454 } | 567 } |
| 455 | 568 |
| 456 if (update_type == UpdateType::MAY_EARLY_OUT_IF_POLICY_UNCHANGED && | 569 Policy new_policy; |
| 457 new_policy == MainThreadOnly().current_policy_) | 570 bool block_expensive_tasks = false; |
| 458 return; | 571 switch (use_case) { |
| 572 case UseCase::COMPOSITOR_SCROLLING: | |
| 573 if (scroll_expected_soon) | |
| 574 block_expensive_tasks = true; | |
| 575 else | |
| 576 new_policy.loading_queue_priority_ = TaskQueue::HIGH_PRIORITY; | |
| 577 break; | |
| 459 | 578 |
| 460 TaskQueue::QueuePriority compositor_queue_priority = | 579 case UseCase::MAINTHREAD_SCROLLING: |
| 461 TaskQueue::NORMAL_PRIORITY; | 580 new_policy.compositor_queue_priority_ = TaskQueue::HIGH_PRIORITY; |
| 462 TaskQueue::QueuePriority loading_queue_priority = TaskQueue::NORMAL_PRIORITY; | 581 block_expensive_tasks = true; |
| 463 TaskQueue::QueuePriority timer_queue_priority = | 582 break; |
| 464 MainThreadOnly().timer_queue_suspend_count_ != 0 | |
| 465 ? TaskQueue::DISABLED_PRIORITY | |
| 466 : TaskQueue::NORMAL_PRIORITY; | |
| 467 | 583 |
| 468 switch (new_policy) { | 584 case UseCase::TOUCHSTART: |
| 469 case Policy::COMPOSITOR_PRIORITY: | 585 new_policy.compositor_queue_priority_ = TaskQueue::HIGH_PRIORITY; |
| 470 compositor_queue_priority = TaskQueue::HIGH_PRIORITY; | 586 new_policy.loading_queue_priority_ = TaskQueue::DISABLED_PRIORITY; |
| 587 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.
| |
| 471 break; | 588 break; |
| 472 case Policy::COMPOSITOR_CRITICAL_PATH_PRIORITY: | 589 |
| 473 compositor_queue_priority = TaskQueue::HIGH_PRIORITY; | 590 case UseCase::NOT_SCROLLING: |
| 474 loading_queue_priority = TaskQueue::DISABLED_PRIORITY; | 591 if (scroll_expected_soon) |
| 475 timer_queue_priority = TaskQueue::DISABLED_PRIORITY; | 592 block_expensive_tasks = true; |
| 593 else | |
| 594 new_policy.loading_queue_priority_ = TaskQueue::HIGH_PRIORITY; | |
| 476 break; | 595 break; |
| 477 case Policy::TOUCHSTART_PRIORITY: | 596 |
| 478 compositor_queue_priority = TaskQueue::HIGH_PRIORITY; | 597 case UseCase::LOADING: |
| 479 loading_queue_priority = TaskQueue::DISABLED_PRIORITY; | 598 new_policy.loading_queue_priority_ = TaskQueue::HIGH_PRIORITY; |
| 480 timer_queue_priority = TaskQueue::DISABLED_PRIORITY; | 599 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 :)
| |
| 481 break; | |
| 482 case Policy::NORMAL: | |
| 483 break; | |
| 484 case Policy::LOADING_PRIORITY: | |
| 485 // We prioritize loading tasks by deprioritizing compositing and timers. | |
| 486 compositor_queue_priority = TaskQueue::BEST_EFFORT_PRIORITY; | |
| 487 timer_queue_priority = TaskQueue::BEST_EFFORT_PRIORITY; | |
| 488 // TODO(alexclarke): See if we can safely mark the loading task queue as | |
| 489 // high priority. | |
| 490 break; | 600 break; |
| 491 default: | 601 default: |
| 492 NOTREACHED(); | 602 NOTREACHED(); |
| 493 } | 603 } |
| 494 | 604 |
| 495 compositor_task_runner_->SetQueuePriority(compositor_queue_priority); | 605 if (block_expensive_tasks && loading_tasks_seem_expensive) |
| 496 loading_task_runner_->SetQueuePriority(loading_queue_priority); | 606 new_policy.loading_queue_priority_ = TaskQueue::DISABLED_PRIORITY; |
| 497 timer_task_runner_->SetQueuePriority(timer_queue_priority); | |
| 498 | 607 |
| 499 DCHECK(compositor_task_runner_->IsQueueEnabled()); | 608 if ((block_expensive_tasks && timer_tasks_seem_expensive) || |
| 500 if (new_policy != Policy::TOUCHSTART_PRIORITY && | 609 MainThreadOnly().timer_queue_suspend_count_ != 0) |
| 501 new_policy != Policy::COMPOSITOR_CRITICAL_PATH_PRIORITY) { | 610 new_policy.timer_queue_priority_ = TaskQueue::DISABLED_PRIORITY; |
| 502 DCHECK(loading_task_runner_->IsQueueEnabled()); | |
| 503 } | |
| 504 MainThreadOnly().current_policy_ = new_policy; | |
| 505 | 611 |
| 612 // Tracing is done before the early out check, because it's quite possible we | |
| 613 // will otherwise miss this information in traces. | |
| 506 TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID( | 614 TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID( |
| 507 TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), "RendererScheduler", | 615 TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), "RendererScheduler", |
| 508 this, AsValueLocked(now)); | 616 this, AsValueLocked(now)); |
| 617 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), "use_case", | |
| 618 use_case); | |
| 509 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), | 619 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), |
| 510 "RendererScheduler.policy", MainThreadOnly().current_policy_); | 620 "RendererScheduler.loading_tasks_seem_expensive", |
| 621 MainThreadOnly().loading_tasks_seem_expensive_); | |
| 511 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), | 622 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), |
| 512 "RendererScheduler.timer_tasks_seem_expensive", | 623 "RendererScheduler.timer_tasks_seem_expensive", |
| 513 AnyThread().timer_tasks_seem_expensive_); | 624 MainThreadOnly().timer_tasks_seem_expensive_); |
| 625 | |
| 626 if (update_type == UpdateType::MAY_EARLY_OUT_IF_POLICY_UNCHANGED && | |
| 627 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.
| |
| 628 new_policy == MainThreadOnly().current_policy_) { | |
| 629 return; | |
| 630 } | |
| 631 | |
| 632 compositor_task_runner_->SetQueuePriority( | |
| 633 new_policy.compositor_queue_priority_); | |
| 634 loading_task_runner_->SetQueuePriority(new_policy.loading_queue_priority_); | |
| 635 timer_task_runner_->SetQueuePriority(new_policy.timer_queue_priority_); | |
| 636 | |
| 637 DCHECK(compositor_task_runner_->IsQueueEnabled()); | |
| 638 MainThreadOnly().current_use_case_ = use_case; | |
| 639 MainThreadOnly().current_policy_ = new_policy; | |
| 514 } | 640 } |
| 515 | 641 |
| 516 bool RendererSchedulerImpl::InputSignalsSuggestCompositorPriority( | 642 bool RendererSchedulerImpl::InputSignalsSuggestScrolling( |
| 517 base::TimeTicks now) const { | 643 base::TimeTicks now) const { |
| 518 base::TimeDelta unused_policy_duration; | 644 base::TimeDelta unused_policy_duration; |
| 519 switch (ComputeNewPolicy(now, &unused_policy_duration)) { | 645 switch (ComputeCurrentUseCase(now, &unused_policy_duration)) { |
| 520 case Policy::TOUCHSTART_PRIORITY: | 646 case UseCase::COMPOSITOR_SCROLLING: |
| 521 case Policy::COMPOSITOR_PRIORITY: | 647 case UseCase::MAINTHREAD_SCROLLING: |
| 522 case Policy::COMPOSITOR_CRITICAL_PATH_PRIORITY: | 648 case UseCase::TOUCHSTART: |
| 523 return true; | 649 return true; |
| 524 | 650 |
| 525 default: | 651 default: |
| 526 break; | 652 break; |
| 527 } | 653 } |
| 528 return false; | 654 return false; |
| 529 } | 655 } |
| 530 | 656 |
| 531 RendererSchedulerImpl::Policy RendererSchedulerImpl::ComputeNewPolicy( | 657 RendererSchedulerImpl::UseCase RendererSchedulerImpl::ComputeCurrentUseCase( |
| 532 base::TimeTicks now, | 658 base::TimeTicks now, |
| 533 base::TimeDelta* new_policy_duration) const { | 659 base::TimeDelta* new_policy_duration) const { |
| 534 any_thread_lock_.AssertAcquired(); | 660 any_thread_lock_.AssertAcquired(); |
| 535 // Above all else we want to be responsive to user input. | 661 // Above all else we want to be responsive to user input. |
| 536 *new_policy_duration = TimeLeftInInputEscalatedPolicy(now); | 662 *new_policy_duration = TimeLeftInInputEscalatedPolicy(now); |
| 537 if (*new_policy_duration > base::TimeDelta()) { | 663 if (*new_policy_duration > base::TimeDelta()) { |
| 538 if (AnyThread().awaiting_touch_start_response_) | 664 // Has scrolling been fully established? |
| 539 return Policy::TOUCHSTART_PRIORITY; | 665 if (AnyThread().awaiting_touch_start_response_) { |
| 540 // If BeginMainFrame is on the critical path, we want to try and prevent | 666 // 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.
| |
| 541 // timers and loading tasks from running if we think they might be | 667 return UseCase::TOUCHSTART; |
| 542 // expensive. | |
| 543 // 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.
| |
| 544 // HadAnIdlePeriodRecently() unless we need them here. | |
| 545 if (AnyThread().timer_tasks_seem_expensive_ && | |
| 546 AnyThread().begin_main_frame_on_critical_path_) { | |
| 547 return Policy::COMPOSITOR_CRITICAL_PATH_PRIORITY; | |
| 548 } | 668 } |
| 549 return Policy::COMPOSITOR_PRIORITY; | 669 // Yes scrolling has been established. If BeginMainFrame is on the critical |
| 670 // path, compositor tasks need to be prioritized, otherwise now might be a | |
| 671 // good time to run potentially expensive work. | |
| 672 if (AnyThread().begin_main_frame_on_critical_path_) { | |
| 673 return UseCase::MAINTHREAD_SCROLLING; | |
| 674 } else { | |
| 675 return UseCase::COMPOSITOR_SCROLLING; | |
| 676 } | |
| 550 } | 677 } |
| 551 | 678 |
| 552 if (AnyThread().rails_loading_priority_deadline_ > now) { | 679 if (AnyThread().rails_loading_priority_deadline_ > now) { |
| 553 *new_policy_duration = AnyThread().rails_loading_priority_deadline_ - now; | 680 *new_policy_duration = AnyThread().rails_loading_priority_deadline_ - now; |
| 554 return Policy::LOADING_PRIORITY; | 681 return UseCase::LOADING; |
| 555 } | 682 } |
| 556 | 683 |
| 557 return Policy::NORMAL; | 684 return UseCase::NOT_SCROLLING; |
| 558 } | 685 } |
| 559 | 686 |
| 560 base::TimeDelta RendererSchedulerImpl::TimeLeftInInputEscalatedPolicy( | 687 base::TimeDelta RendererSchedulerImpl::TimeLeftInInputEscalatedPolicy( |
| 561 base::TimeTicks now) const { | 688 base::TimeTicks now) const { |
| 562 any_thread_lock_.AssertAcquired(); | 689 any_thread_lock_.AssertAcquired(); |
| 563 | 690 |
| 564 base::TimeDelta escalated_priority_duration = | 691 base::TimeDelta escalated_priority_duration = |
| 565 base::TimeDelta::FromMilliseconds(kPriorityEscalationAfterInputMillis); | 692 base::TimeDelta::FromMilliseconds(kPriorityEscalationAfterInputMillis); |
| 566 | 693 |
| 567 // If the input event is still pending, go into input prioritized policy | 694 // If the input event is still pending, go into input prioritized policy |
| 568 // and check again later. | 695 // and check again later. |
| 569 if (AnyThread().pending_main_thread_input_event_count_ > 0) | 696 if (AnyThread().pending_main_thread_input_event_count_ > 0) |
| 570 return escalated_priority_duration; | 697 return escalated_priority_duration; |
| 571 if (AnyThread().last_input_signal_time_.is_null() || | 698 if (AnyThread().last_input_signal_time_.is_null() || |
| 572 AnyThread().last_input_signal_time_ + escalated_priority_duration < now) { | 699 AnyThread().last_input_signal_time_ + escalated_priority_duration < now) { |
| 573 return base::TimeDelta(); | 700 return base::TimeDelta(); |
| 574 } | 701 } |
| 575 return AnyThread().last_input_signal_time_ + escalated_priority_duration - | 702 return AnyThread().last_input_signal_time_ + escalated_priority_duration - |
| 576 now; | 703 now; |
| 577 } | 704 } |
| 578 | 705 |
| 579 bool RendererSchedulerImpl::CanEnterLongIdlePeriod( | 706 bool RendererSchedulerImpl::CanEnterLongIdlePeriod( |
| 580 base::TimeTicks now, | 707 base::TimeTicks now, |
| 581 base::TimeDelta* next_long_idle_period_delay_out) { | 708 base::TimeDelta* next_long_idle_period_delay_out) { |
| 582 helper_.CheckOnValidThread(); | 709 helper_.CheckOnValidThread(); |
| 583 | 710 |
| 584 MaybeUpdatePolicy(); | 711 MaybeUpdatePolicy(); |
| 585 if (MainThreadOnly().current_policy_ == Policy::TOUCHSTART_PRIORITY) { | 712 if (MainThreadOnly().current_use_case_ == UseCase::TOUCHSTART) { |
| 586 // Don't start a long idle task in touch start priority, try again when | 713 // Don't start a long idle task in touch start priority, try again when |
| 587 // the policy is scheduled to end. | 714 // the policy is scheduled to end. |
| 588 *next_long_idle_period_delay_out = | 715 *next_long_idle_period_delay_out = |
| 589 MainThreadOnly().current_policy_expiration_time_ - now; | 716 MainThreadOnly().current_policy_expiration_time_ - now; |
| 590 return false; | 717 return false; |
| 591 } | 718 } |
| 592 return true; | 719 return true; |
| 593 } | 720 } |
| 594 | 721 |
| 595 SchedulerHelper* RendererSchedulerImpl::GetSchedulerHelperForTesting() { | 722 SchedulerHelper* RendererSchedulerImpl::GetSchedulerHelperForTesting() { |
| 596 return &helper_; | 723 return &helper_; |
| 597 } | 724 } |
| 598 | 725 |
| 599 void RendererSchedulerImpl::SuspendTimerQueue() { | 726 void RendererSchedulerImpl::SuspendTimerQueue() { |
| 600 MainThreadOnly().timer_queue_suspend_count_++; | 727 MainThreadOnly().timer_queue_suspend_count_++; |
| 601 ForceUpdatePolicy(); | 728 ForceUpdatePolicy(); |
| 602 DCHECK(!timer_task_runner_->IsQueueEnabled()); | 729 DCHECK(!timer_task_runner_->IsQueueEnabled()); |
| 603 } | 730 } |
| 604 | 731 |
| 605 void RendererSchedulerImpl::ResumeTimerQueue() { | 732 void RendererSchedulerImpl::ResumeTimerQueue() { |
| 606 MainThreadOnly().timer_queue_suspend_count_--; | 733 MainThreadOnly().timer_queue_suspend_count_--; |
| 607 DCHECK_GE(MainThreadOnly().timer_queue_suspend_count_, 0); | 734 DCHECK_GE(MainThreadOnly().timer_queue_suspend_count_, 0); |
| 608 ForceUpdatePolicy(); | 735 ForceUpdatePolicy(); |
| 609 } | 736 } |
| 610 | 737 |
| 611 // static | 738 // static |
| 612 const char* RendererSchedulerImpl::PolicyToString(Policy policy) { | 739 const char* RendererSchedulerImpl::UseCaseToString(UseCase use_case) { |
| 613 switch (policy) { | 740 switch (use_case) { |
| 614 case Policy::NORMAL: | 741 case UseCase::NOT_SCROLLING: |
| 615 return "normal"; | 742 return "not_scrolling"; |
| 616 case Policy::COMPOSITOR_PRIORITY: | 743 case UseCase::COMPOSITOR_SCROLLING: |
| 617 return "compositor"; | 744 return "compositor_scrolling"; |
| 618 case Policy::COMPOSITOR_CRITICAL_PATH_PRIORITY: | 745 case UseCase::MAINTHREAD_SCROLLING: |
| 619 return "compositor_critical_path"; | 746 return "mainthread_scrolling"; |
| 620 case Policy::TOUCHSTART_PRIORITY: | 747 case UseCase::TOUCHSTART: |
| 621 return "touchstart"; | 748 return "touchstart"; |
| 622 case Policy::LOADING_PRIORITY: | 749 case UseCase::LOADING: |
| 623 return "loading"; | 750 return "loading"; |
| 624 default: | 751 default: |
| 625 NOTREACHED(); | 752 NOTREACHED(); |
| 626 return nullptr; | 753 return nullptr; |
| 627 } | 754 } |
| 628 } | 755 } |
| 629 | 756 |
| 630 scoped_refptr<base::trace_event::ConvertableToTraceFormat> | 757 scoped_refptr<base::trace_event::ConvertableToTraceFormat> |
| 631 RendererSchedulerImpl::AsValue(base::TimeTicks optional_now) const { | 758 RendererSchedulerImpl::AsValue(base::TimeTicks optional_now) const { |
| 632 base::AutoLock lock(any_thread_lock_); | 759 base::AutoLock lock(any_thread_lock_); |
| 633 return AsValueLocked(optional_now); | 760 return AsValueLocked(optional_now); |
| 634 } | 761 } |
| 635 | 762 |
| 636 scoped_refptr<base::trace_event::ConvertableToTraceFormat> | 763 scoped_refptr<base::trace_event::ConvertableToTraceFormat> |
| 637 RendererSchedulerImpl::AsValueLocked(base::TimeTicks optional_now) const { | 764 RendererSchedulerImpl::AsValueLocked(base::TimeTicks optional_now) const { |
| 638 helper_.CheckOnValidThread(); | 765 helper_.CheckOnValidThread(); |
| 639 any_thread_lock_.AssertAcquired(); | 766 any_thread_lock_.AssertAcquired(); |
| 640 | 767 |
| 641 if (optional_now.is_null()) | 768 if (optional_now.is_null()) |
| 642 optional_now = helper_.Now(); | 769 optional_now = helper_.Now(); |
| 643 scoped_refptr<base::trace_event::TracedValue> state = | 770 scoped_refptr<base::trace_event::TracedValue> state = |
| 644 new base::trace_event::TracedValue(); | 771 new base::trace_event::TracedValue(); |
| 645 | 772 |
| 646 state->SetString("current_policy", | 773 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.
| |
| 647 PolicyToString(MainThreadOnly().current_policy_)); | 774 UseCaseToString(MainThreadOnly().current_use_case_)); |
| 775 state->SetBoolean("loading_tasks_seem_expensive", | |
| 776 MainThreadOnly().loading_tasks_seem_expensive_); | |
| 777 state->SetBoolean("timer_tasks_seem_expensive", | |
| 778 MainThreadOnly().timer_tasks_seem_expensive_); | |
| 779 state->SetBoolean("scroll_expected_soon", | |
| 780 MainThreadOnly().scroll_expected_soon_); | |
| 648 state->SetString("idle_period_state", | 781 state->SetString("idle_period_state", |
| 649 IdleHelper::IdlePeriodStateToString( | 782 IdleHelper::IdlePeriodStateToString( |
| 650 idle_helper_.SchedulerIdlePeriodState())); | 783 idle_helper_.SchedulerIdlePeriodState())); |
| 651 state->SetBoolean("renderer_hidden", MainThreadOnly().renderer_hidden_); | 784 state->SetBoolean("renderer_hidden", MainThreadOnly().renderer_hidden_); |
| 652 state->SetDouble("now", (optional_now - base::TimeTicks()).InMillisecondsF()); | 785 state->SetDouble("now", (optional_now - base::TimeTicks()).InMillisecondsF()); |
| 653 state->SetDouble("last_input_signal_time", | 786 state->SetDouble("last_input_signal_time", |
| 654 (AnyThread().last_input_signal_time_ - base::TimeTicks()) | 787 (AnyThread().last_input_signal_time_ - base::TimeTicks()) |
| 655 .InMillisecondsF()); | 788 .InMillisecondsF()); |
| 656 state->SetDouble("rails_loading_priority_deadline", | 789 state->SetDouble("rails_loading_priority_deadline", |
| 657 (AnyThread().rails_loading_priority_deadline_ - | 790 (AnyThread().rails_loading_priority_deadline_ - |
| 658 base::TimeTicks()).InMillisecondsF()); | 791 base::TimeTicks()).InMillisecondsF()); |
| 659 state->SetDouble("last_idle_period_end_time", | 792 state->SetDouble("last_idle_period_end_time", |
| 660 (AnyThread().last_idle_period_end_time_ - base::TimeTicks()) | 793 (AnyThread().last_idle_period_end_time_ - base::TimeTicks()) |
| 661 .InMillisecondsF()); | 794 .InMillisecondsF()); |
| 662 state->SetInteger("pending_main_thread_input_event_count", | 795 state->SetInteger("pending_main_thread_input_event_count", |
| 663 AnyThread().pending_main_thread_input_event_count_); | 796 AnyThread().pending_main_thread_input_event_count_); |
| 664 state->SetBoolean("awaiting_touch_start_response", | 797 state->SetBoolean("awaiting_touch_start_response", |
| 665 AnyThread().awaiting_touch_start_response_); | 798 AnyThread().awaiting_touch_start_response_); |
| 666 state->SetBoolean("begin_main_frame_on_critical_path", | 799 state->SetBoolean("begin_main_frame_on_critical_path", |
| 667 AnyThread().begin_main_frame_on_critical_path_); | 800 AnyThread().begin_main_frame_on_critical_path_); |
| 801 state->SetDouble("expected_loading_task_duration", | |
| 802 MainThreadOnly() | |
| 803 .loading_task_cost_estimator_.expected_task_duration() | |
| 804 .InMillisecondsF()); | |
| 668 state->SetDouble("expected_timer_task_duration", | 805 state->SetDouble("expected_timer_task_duration", |
| 669 MainThreadOnly() | 806 MainThreadOnly() |
| 670 .timer_task_cost_estimator_.expected_task_duration() | 807 .timer_task_cost_estimator_.expected_task_duration() |
| 671 .InMillisecondsF()); | 808 .InMillisecondsF()); |
| 672 // TODO(skyostil): Can we somehow trace how accurate these estimates were? | 809 // TODO(skyostil): Can we somehow trace how accurate these estimates were? |
| 673 state->SetDouble( | 810 state->SetDouble( |
| 674 "expected_short_idle_period_duration", | 811 "expected_short_idle_period_duration", |
| 675 MainThreadOnly().expected_short_idle_period_duration_.InMillisecondsF()); | 812 MainThreadOnly().expected_short_idle_period_duration_.InMillisecondsF()); |
| 676 state->SetBoolean("timer_tasks_seem_expensive", | |
| 677 AnyThread().timer_tasks_seem_expensive_); | |
| 678 state->SetDouble("estimated_next_frame_begin", | 813 state->SetDouble("estimated_next_frame_begin", |
| 679 (MainThreadOnly().estimated_next_frame_begin_ - | 814 (MainThreadOnly().estimated_next_frame_begin_ - |
| 680 base::TimeTicks()).InMillisecondsF()); | 815 base::TimeTicks()).InMillisecondsF()); |
| 681 state->SetBoolean("in_idle_period", AnyThread().in_idle_period_); | 816 state->SetBoolean("in_idle_period", AnyThread().in_idle_period_); |
| 682 | 817 |
| 683 return state; | 818 return state; |
| 684 } | 819 } |
| 685 | 820 |
| 686 void RendererSchedulerImpl::OnIdlePeriodStarted() { | 821 void RendererSchedulerImpl::OnIdlePeriodStarted() { |
| 687 base::AutoLock lock(any_thread_lock_); | 822 base::AutoLock lock(any_thread_lock_); |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 704 UpdatePolicyLocked(UpdateType::MAY_EARLY_OUT_IF_POLICY_UNCHANGED); | 839 UpdatePolicyLocked(UpdateType::MAY_EARLY_OUT_IF_POLICY_UNCHANGED); |
| 705 } | 840 } |
| 706 | 841 |
| 707 bool RendererSchedulerImpl::HadAnIdlePeriodRecently(base::TimeTicks now) const { | 842 bool RendererSchedulerImpl::HadAnIdlePeriodRecently(base::TimeTicks now) const { |
| 708 return (now - AnyThread().last_idle_period_end_time_) <= | 843 return (now - AnyThread().last_idle_period_end_time_) <= |
| 709 base::TimeDelta::FromMilliseconds( | 844 base::TimeDelta::FromMilliseconds( |
| 710 kIdlePeriodStarvationThresholdMillis); | 845 kIdlePeriodStarvationThresholdMillis); |
| 711 } | 846 } |
| 712 | 847 |
| 713 } // namespace scheduler | 848 } // namespace scheduler |
| OLD | NEW |