OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "content/renderer/scheduler/renderer_scheduler_impl.h" | 5 #include "content/renderer/scheduler/renderer_scheduler_impl.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/message_loop/message_loop_proxy.h" | 8 #include "base/message_loop/message_loop_proxy.h" |
9 #include "base/trace_event/trace_event.h" | 9 #include "base/trace_event/trace_event.h" |
10 #include "base/trace_event/trace_event_argument.h" | 10 #include "base/trace_event/trace_event_argument.h" |
(...skipping 19 matching lines...) Expand all Loading... |
30 task_queue_manager_->TaskRunnerForQueue(DEFAULT_TASK_QUEUE)), | 30 task_queue_manager_->TaskRunnerForQueue(DEFAULT_TASK_QUEUE)), |
31 compositor_task_runner_( | 31 compositor_task_runner_( |
32 task_queue_manager_->TaskRunnerForQueue(COMPOSITOR_TASK_QUEUE)), | 32 task_queue_manager_->TaskRunnerForQueue(COMPOSITOR_TASK_QUEUE)), |
33 loading_task_runner_( | 33 loading_task_runner_( |
34 task_queue_manager_->TaskRunnerForQueue(LOADING_TASK_QUEUE)), | 34 task_queue_manager_->TaskRunnerForQueue(LOADING_TASK_QUEUE)), |
35 delayed_update_policy_runner_( | 35 delayed_update_policy_runner_( |
36 base::Bind(&RendererSchedulerImpl::UpdatePolicy, | 36 base::Bind(&RendererSchedulerImpl::UpdatePolicy, |
37 base::Unretained(this)), | 37 base::Unretained(this)), |
38 control_task_runner_), | 38 control_task_runner_), |
39 current_policy_(Policy::NORMAL), | 39 current_policy_(Policy::NORMAL), |
| 40 idle_period_state_(IdlePeriodState::NOT_IN_IDLE_PERIOD), |
| 41 long_idle_periods_enabled_(false), |
40 last_input_type_(blink::WebInputEvent::Undefined), | 42 last_input_type_(blink::WebInputEvent::Undefined), |
41 input_stream_state_(InputStreamState::INACTIVE), | 43 input_stream_state_(InputStreamState::INACTIVE), |
42 policy_may_need_update_(&incoming_signals_lock_), | 44 policy_may_need_update_(&incoming_signals_lock_), |
43 weak_factory_(this) { | 45 weak_factory_(this) { |
44 weak_renderer_scheduler_ptr_ = weak_factory_.GetWeakPtr(); | 46 weak_renderer_scheduler_ptr_ = weak_factory_.GetWeakPtr(); |
45 update_policy_closure_ = base::Bind(&RendererSchedulerImpl::UpdatePolicy, | 47 update_policy_closure_ = base::Bind(&RendererSchedulerImpl::UpdatePolicy, |
46 weak_renderer_scheduler_ptr_); | 48 weak_renderer_scheduler_ptr_); |
47 end_idle_period_closure_.Reset(base::Bind( | 49 end_idle_period_closure_.Reset(base::Bind( |
48 &RendererSchedulerImpl::EndIdlePeriod, weak_renderer_scheduler_ptr_)); | 50 &RendererSchedulerImpl::EndIdlePeriod, weak_renderer_scheduler_ptr_)); |
| 51 initiate_next_long_idle_period_closure_.Reset(base::Bind( |
| 52 &RendererSchedulerImpl::InitiateLongIdlePeriod, |
| 53 weak_renderer_scheduler_ptr_)); |
| 54 initiate_next_long_idle_period_after_wakeup_closure_.Reset(base::Bind( |
| 55 &RendererSchedulerImpl::InitiateLongIdlePeriodAfterWakeup, |
| 56 weak_renderer_scheduler_ptr_)); |
| 57 |
49 idle_task_runner_ = make_scoped_refptr(new SingleThreadIdleTaskRunner( | 58 idle_task_runner_ = make_scoped_refptr(new SingleThreadIdleTaskRunner( |
50 task_queue_manager_->TaskRunnerForQueue(IDLE_TASK_QUEUE), | 59 task_queue_manager_->TaskRunnerForQueue(IDLE_TASK_QUEUE), |
51 control_task_after_wakeup_runner_, | 60 control_task_after_wakeup_runner_, |
52 base::Bind(&RendererSchedulerImpl::CurrentIdleTaskDeadlineCallback, | 61 base::Bind(&RendererSchedulerImpl::CurrentIdleTaskDeadlineCallback, |
53 weak_renderer_scheduler_ptr_))); | 62 weak_renderer_scheduler_ptr_))); |
54 | 63 |
55 renderer_task_queue_selector_->SetQueuePriority( | 64 renderer_task_queue_selector_->SetQueuePriority( |
56 CONTROL_TASK_QUEUE, RendererTaskQueueSelector::CONTROL_PRIORITY); | 65 CONTROL_TASK_QUEUE, RendererTaskQueueSelector::CONTROL_PRIORITY); |
57 | 66 |
58 renderer_task_queue_selector_->SetQueuePriority( | 67 renderer_task_queue_selector_->SetQueuePriority( |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
129 | 138 |
130 void RendererSchedulerImpl::DidCommitFrameToCompositor() { | 139 void RendererSchedulerImpl::DidCommitFrameToCompositor() { |
131 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), | 140 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), |
132 "RendererSchedulerImpl::DidCommitFrameToCompositor"); | 141 "RendererSchedulerImpl::DidCommitFrameToCompositor"); |
133 DCHECK(main_thread_checker_.CalledOnValidThread()); | 142 DCHECK(main_thread_checker_.CalledOnValidThread()); |
134 if (!task_queue_manager_) | 143 if (!task_queue_manager_) |
135 return; | 144 return; |
136 | 145 |
137 base::TimeTicks now(Now()); | 146 base::TimeTicks now(Now()); |
138 if (now < estimated_next_frame_begin_) { | 147 if (now < estimated_next_frame_begin_) { |
139 StartIdlePeriod(); | 148 // TODO(rmcilroy): Consider reducing the idle period based on the runtime of |
| 149 // the next pending delayed tasks (as currently done in for long idle times) |
| 150 StartIdlePeriod(IdlePeriodState::IN_SHORT_IDLE_PERIOD); |
140 control_task_runner_->PostDelayedTask(FROM_HERE, | 151 control_task_runner_->PostDelayedTask(FROM_HERE, |
141 end_idle_period_closure_.callback(), | 152 end_idle_period_closure_.callback(), |
142 estimated_next_frame_begin_ - now); | 153 estimated_next_frame_begin_ - now); |
143 } | 154 } |
144 } | 155 } |
145 | 156 |
146 void RendererSchedulerImpl::BeginFrameNotExpectedSoon() { | 157 void RendererSchedulerImpl::BeginFrameNotExpectedSoon() { |
147 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), | 158 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), |
148 "RendererSchedulerImpl::BeginFrameNotExpectedSoon"); | 159 "RendererSchedulerImpl::BeginFrameNotExpectedSoon"); |
149 DCHECK(main_thread_checker_.CalledOnValidThread()); | 160 DCHECK(main_thread_checker_.CalledOnValidThread()); |
| 161 if (!task_queue_manager_) |
| 162 return; |
| 163 |
150 // TODO(skyostil): Wire up real notification of input events processing | 164 // TODO(skyostil): Wire up real notification of input events processing |
151 // instead of this approximation. | 165 // instead of this approximation. |
152 DidProcessInputEvent(base::TimeTicks()); | 166 DidProcessInputEvent(base::TimeTicks()); |
153 // TODO(rmcilroy): Implement long idle times. | 167 |
| 168 InitiateLongIdlePeriod(); |
154 } | 169 } |
155 | 170 |
156 void RendererSchedulerImpl::DidReceiveInputEventOnCompositorThread( | 171 void RendererSchedulerImpl::DidReceiveInputEventOnCompositorThread( |
157 const blink::WebInputEvent& web_input_event) { | 172 const blink::WebInputEvent& web_input_event) { |
158 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), | 173 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), |
159 "RendererSchedulerImpl::DidReceiveInputEventOnCompositorThread"); | 174 "RendererSchedulerImpl::DidReceiveInputEventOnCompositorThread"); |
160 // We regard MouseMove events with the left mouse button down as a signal | 175 // We regard MouseMove events with the left mouse button down as a signal |
161 // that the user is doing something requiring a smooth frame rate. | 176 // that the user is doing something requiring a smooth frame rate. |
162 if (web_input_event.type == blink::WebInputEvent::MouseMove && | 177 if (web_input_event.type == blink::WebInputEvent::MouseMove && |
163 (web_input_event.modifiers & blink::WebInputEvent::LeftButtonDown)) { | 178 (web_input_event.modifiers & blink::WebInputEvent::LeftButtonDown)) { |
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
294 incoming_signals_lock_.AssertAcquired(); | 309 incoming_signals_lock_.AssertAcquired(); |
295 if (!task_queue_manager_) | 310 if (!task_queue_manager_) |
296 return; | 311 return; |
297 | 312 |
298 base::TimeTicks now = Now(); | 313 base::TimeTicks now = Now(); |
299 policy_may_need_update_.SetWhileLocked(false); | 314 policy_may_need_update_.SetWhileLocked(false); |
300 | 315 |
301 base::TimeDelta new_policy_duration; | 316 base::TimeDelta new_policy_duration; |
302 Policy new_policy = ComputeNewPolicy(now, &new_policy_duration); | 317 Policy new_policy = ComputeNewPolicy(now, &new_policy_duration); |
303 if (new_policy_duration > base::TimeDelta()) { | 318 if (new_policy_duration > base::TimeDelta()) { |
| 319 current_policy_expiration_time_ = now + new_policy_duration; |
304 delayed_update_policy_runner_.SetDeadline(FROM_HERE, new_policy_duration, | 320 delayed_update_policy_runner_.SetDeadline(FROM_HERE, new_policy_duration, |
305 now); | 321 now); |
| 322 } else { |
| 323 current_policy_expiration_time_ = base::TimeTicks(); |
306 } | 324 } |
307 | 325 |
308 if (new_policy == current_policy_) | 326 if (new_policy == current_policy_) |
309 return; | 327 return; |
310 | 328 |
311 switch (new_policy) { | 329 switch (new_policy) { |
312 case Policy::COMPOSITOR_PRIORITY: | 330 case Policy::COMPOSITOR_PRIORITY: |
313 renderer_task_queue_selector_->SetQueuePriority( | 331 renderer_task_queue_selector_->SetQueuePriority( |
314 COMPOSITOR_TASK_QUEUE, RendererTaskQueueSelector::HIGH_PRIORITY); | 332 COMPOSITOR_TASK_QUEUE, RendererTaskQueueSelector::HIGH_PRIORITY); |
315 // TODO(scheduler-dev): Add a task priority between HIGH and BEST_EFFORT | 333 // TODO(scheduler-dev): Add a task priority between HIGH and BEST_EFFORT |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
347 base::TimeDelta* new_policy_duration) { | 365 base::TimeDelta* new_policy_duration) { |
348 DCHECK(main_thread_checker_.CalledOnValidThread()); | 366 DCHECK(main_thread_checker_.CalledOnValidThread()); |
349 incoming_signals_lock_.AssertAcquired(); | 367 incoming_signals_lock_.AssertAcquired(); |
350 | 368 |
351 Policy new_policy = Policy::NORMAL; | 369 Policy new_policy = Policy::NORMAL; |
352 *new_policy_duration = base::TimeDelta(); | 370 *new_policy_duration = base::TimeDelta(); |
353 | 371 |
354 if (input_stream_state_ == InputStreamState::INACTIVE) | 372 if (input_stream_state_ == InputStreamState::INACTIVE) |
355 return new_policy; | 373 return new_policy; |
356 | 374 |
357 base::TimeDelta new_priority_duration = | |
358 base::TimeDelta::FromMilliseconds(kPriorityEscalationAfterInputMillis); | |
359 Policy input_priority_policy = | 375 Policy input_priority_policy = |
360 input_stream_state_ == | 376 input_stream_state_ == |
361 InputStreamState::ACTIVE_AND_AWAITING_TOUCHSTART_RESPONSE | 377 InputStreamState::ACTIVE_AND_AWAITING_TOUCHSTART_RESPONSE |
362 ? Policy::TOUCHSTART_PRIORITY | 378 ? Policy::TOUCHSTART_PRIORITY |
363 : Policy::COMPOSITOR_PRIORITY; | 379 : Policy::COMPOSITOR_PRIORITY; |
| 380 base::TimeDelta time_left_in_policy = TimeLeftInInputEscalatedPolicy(now); |
| 381 if (time_left_in_policy > base::TimeDelta()) { |
| 382 new_policy = input_priority_policy; |
| 383 *new_policy_duration = time_left_in_policy; |
| 384 } else { |
| 385 // Reset |input_stream_state_| to ensure |
| 386 // DidReceiveInputEventOnCompositorThread will post an UpdatePolicy task |
| 387 // when it's next called. |
| 388 input_stream_state_ = InputStreamState::INACTIVE; |
| 389 } |
| 390 return new_policy; |
| 391 } |
364 | 392 |
365 // If the input event is still pending, go into input prioritized policy | 393 base::TimeDelta RendererSchedulerImpl::TimeLeftInInputEscalatedPolicy( |
366 // and check again later. | 394 base::TimeTicks now) const { |
| 395 DCHECK(main_thread_checker_.CalledOnValidThread()); |
| 396 // TODO(rmcilroy): Change this to DCHECK_EQ when crbug.com/463869 is fixed. |
| 397 DCHECK(input_stream_state_ != InputStreamState::INACTIVE); |
| 398 incoming_signals_lock_.AssertAcquired(); |
| 399 |
| 400 base::TimeDelta escalated_priority_duration = |
| 401 base::TimeDelta::FromMilliseconds(kPriorityEscalationAfterInputMillis); |
| 402 base::TimeDelta time_left_in_policy; |
367 if (last_input_process_time_on_main_.is_null() && | 403 if (last_input_process_time_on_main_.is_null() && |
368 !task_queue_manager_->IsQueueEmpty(COMPOSITOR_TASK_QUEUE)) { | 404 !task_queue_manager_->IsQueueEmpty(COMPOSITOR_TASK_QUEUE)) { |
369 new_policy = input_priority_policy; | 405 // If the input event is still pending, go into input prioritized policy |
370 *new_policy_duration = new_priority_duration; | 406 // and check again later. |
| 407 time_left_in_policy = escalated_priority_duration; |
371 } else { | 408 } else { |
372 // Otherwise make sure the input prioritization policy ends on time. | 409 // Otherwise make sure the input prioritization policy ends on time. |
373 base::TimeTicks new_priority_end( | 410 base::TimeTicks new_priority_end( |
374 std::max(last_input_receipt_time_on_compositor_, | 411 std::max(last_input_receipt_time_on_compositor_, |
375 last_input_process_time_on_main_) + | 412 last_input_process_time_on_main_) + |
376 new_priority_duration); | 413 escalated_priority_duration); |
377 base::TimeDelta time_left_in_policy = new_priority_end - now; | 414 time_left_in_policy = new_priority_end - now; |
378 | |
379 if (time_left_in_policy > base::TimeDelta()) { | |
380 new_policy = input_priority_policy; | |
381 *new_policy_duration = time_left_in_policy; | |
382 } else { | |
383 // Reset |input_stream_state_| to ensure | |
384 // DidReceiveInputEventOnCompositorThread will post an UpdatePolicy task | |
385 // when it's next called. | |
386 input_stream_state_ = InputStreamState::INACTIVE; | |
387 } | |
388 } | 415 } |
389 return new_policy; | 416 return time_left_in_policy; |
390 } | 417 } |
391 | 418 |
392 void RendererSchedulerImpl::StartIdlePeriod() { | 419 RendererSchedulerImpl::IdlePeriodState |
| 420 RendererSchedulerImpl::ComputeNewLongIdlePeriodState( |
| 421 const base::TimeTicks now, |
| 422 base::TimeDelta* next_long_idle_period_delay_out) { |
| 423 DCHECK(main_thread_checker_.CalledOnValidThread()); |
| 424 |
| 425 MaybeUpdatePolicy(); |
| 426 if (SchedulerPolicy() == Policy::TOUCHSTART_PRIORITY) { |
| 427 // Don't start a long idle task in touch start priority, try again when |
| 428 // the policy is scheduled to end. |
| 429 *next_long_idle_period_delay_out = current_policy_expiration_time_ - now; |
| 430 return IdlePeriodState::NOT_IN_IDLE_PERIOD; |
| 431 } |
| 432 |
| 433 base::TimeTicks next_pending_delayed_task = |
| 434 task_queue_manager_->NextPendingDelayedTaskRunTime(); |
| 435 base::TimeDelta max_long_idle_period_duration = |
| 436 base::TimeDelta::FromMilliseconds(kMaximumIdlePeriodMillis); |
| 437 base::TimeDelta long_idle_period_duration; |
| 438 if (next_pending_delayed_task.is_null()) { |
| 439 long_idle_period_duration = max_long_idle_period_duration; |
| 440 } else { |
| 441 // Limit the idle period duration to be before the next pending task. |
| 442 long_idle_period_duration = std::min(next_pending_delayed_task - now, |
| 443 max_long_idle_period_duration); |
| 444 } |
| 445 |
| 446 if (long_idle_period_duration > base::TimeDelta()) { |
| 447 *next_long_idle_period_delay_out = long_idle_period_duration; |
| 448 return long_idle_period_duration == max_long_idle_period_duration |
| 449 ? IdlePeriodState::IN_LONG_IDLE_PERIOD_WITH_MAX_DEADLINE |
| 450 : IdlePeriodState::IN_LONG_IDLE_PERIOD; |
| 451 } else { |
| 452 // If we can't start the idle period yet then try again after wakeup. |
| 453 *next_long_idle_period_delay_out = base::TimeDelta::FromMilliseconds( |
| 454 kRetryInitiateLongIdlePeriodDelayMillis); |
| 455 return IdlePeriodState::NOT_IN_IDLE_PERIOD; |
| 456 } |
| 457 } |
| 458 |
| 459 void RendererSchedulerImpl::InitiateLongIdlePeriod() { |
| 460 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), |
| 461 "InitiateLongIdlePeriod"); |
| 462 DCHECK(main_thread_checker_.CalledOnValidThread()); |
| 463 |
| 464 // End any previous idle period. |
| 465 EndIdlePeriod(); |
| 466 |
| 467 base::TimeTicks now(Now()); |
| 468 base::TimeDelta next_long_idle_period_delay; |
| 469 IdlePeriodState new_idle_period_state = |
| 470 ComputeNewLongIdlePeriodState(now, &next_long_idle_period_delay); |
| 471 if (long_idle_periods_enabled_ && IsInIdlePeriod(new_idle_period_state)) { |
| 472 estimated_next_frame_begin_ = now + next_long_idle_period_delay; |
| 473 StartIdlePeriod(new_idle_period_state); |
| 474 } |
| 475 |
| 476 if (task_queue_manager_->IsQueueEmpty(IDLE_TASK_QUEUE)) { |
| 477 // If there are no current idle tasks then post the call to initiate the |
| 478 // next idle for execution after wakeup (at which point after-wakeup idle |
| 479 // tasks might be eligible to run or more idle tasks posted). |
| 480 control_task_after_wakeup_runner_->PostDelayedTask( |
| 481 FROM_HERE, |
| 482 initiate_next_long_idle_period_after_wakeup_closure_.callback(), |
| 483 next_long_idle_period_delay); |
| 484 } else { |
| 485 // Otherwise post on the normal control task queue. |
| 486 control_task_runner_->PostDelayedTask( |
| 487 FROM_HERE, |
| 488 initiate_next_long_idle_period_closure_.callback(), |
| 489 next_long_idle_period_delay); |
| 490 } |
| 491 } |
| 492 |
| 493 void RendererSchedulerImpl::InitiateLongIdlePeriodAfterWakeup() { |
| 494 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), |
| 495 "InitiateLongIdlePeriodAfterWakeup"); |
| 496 DCHECK(main_thread_checker_.CalledOnValidThread()); |
| 497 |
| 498 if (IsInIdlePeriod(idle_period_state_)) { |
| 499 // Since we were asleep until now, end the async idle period trace event at |
| 500 // the time when it would have ended were we awake. |
| 501 TRACE_EVENT_ASYNC_END_WITH_TIMESTAMP0( |
| 502 "renderer.scheduler", "RendererSchedulerIdlePeriod", this, |
| 503 std::min(estimated_next_frame_begin_, Now()).ToInternalValue()); |
| 504 idle_period_state_ = IdlePeriodState::ENDING_LONG_IDLE_PERIOD; |
| 505 EndIdlePeriod(); |
| 506 } |
| 507 |
| 508 // Post a task to initiate the next long idle period rather than calling it |
| 509 // directly to allow all pending PostIdleTaskAfterWakeup tasks to get enqueued |
| 510 // on the idle task queue before the next idle period starts so they are |
| 511 // eligible to be run during the new idle period. |
| 512 control_task_runner_->PostTask( |
| 513 FROM_HERE, |
| 514 initiate_next_long_idle_period_closure_.callback()); |
| 515 } |
| 516 |
| 517 void RendererSchedulerImpl::StartIdlePeriod(IdlePeriodState new_state) { |
393 TRACE_EVENT_ASYNC_BEGIN0("renderer.scheduler", | 518 TRACE_EVENT_ASYNC_BEGIN0("renderer.scheduler", |
394 "RendererSchedulerIdlePeriod", this); | 519 "RendererSchedulerIdlePeriod", this); |
395 DCHECK(main_thread_checker_.CalledOnValidThread()); | 520 DCHECK(main_thread_checker_.CalledOnValidThread()); |
| 521 DCHECK(IsInIdlePeriod(new_state)); |
396 renderer_task_queue_selector_->EnableQueue( | 522 renderer_task_queue_selector_->EnableQueue( |
397 IDLE_TASK_QUEUE, RendererTaskQueueSelector::BEST_EFFORT_PRIORITY); | 523 IDLE_TASK_QUEUE, RendererTaskQueueSelector::BEST_EFFORT_PRIORITY); |
398 task_queue_manager_->PumpQueue(IDLE_TASK_QUEUE); | 524 task_queue_manager_->PumpQueue(IDLE_TASK_QUEUE); |
| 525 idle_period_state_ = new_state; |
399 } | 526 } |
400 | 527 |
401 void RendererSchedulerImpl::EndIdlePeriod() { | 528 void RendererSchedulerImpl::EndIdlePeriod() { |
402 bool is_tracing; | 529 DCHECK(main_thread_checker_.CalledOnValidThread()); |
403 TRACE_EVENT_CATEGORY_GROUP_ENABLED("renderer.scheduler", &is_tracing); | 530 |
404 if (is_tracing && !estimated_next_frame_begin_.is_null() && | 531 end_idle_period_closure_.Cancel(); |
405 base::TimeTicks::Now() > estimated_next_frame_begin_) { | 532 initiate_next_long_idle_period_closure_.Cancel(); |
406 TRACE_EVENT_ASYNC_STEP_INTO_WITH_TIMESTAMP0( | 533 initiate_next_long_idle_period_after_wakeup_closure_.Cancel(); |
407 "renderer.scheduler", | 534 |
408 "RendererSchedulerIdlePeriod", | 535 // If we weren't already within an idle period then early-out. |
409 this, | 536 if (!IsInIdlePeriod(idle_period_state_)) |
410 "DeadlineOverrun", | 537 return; |
411 estimated_next_frame_begin_.ToInternalValue()); | 538 |
| 539 // If we are in the ENDING_LONG_IDLE_PERIOD state we have already logged the |
| 540 // trace event. |
| 541 if (idle_period_state_ != IdlePeriodState::ENDING_LONG_IDLE_PERIOD) { |
| 542 bool is_tracing; |
| 543 TRACE_EVENT_CATEGORY_GROUP_ENABLED("renderer.scheduler", &is_tracing); |
| 544 if (is_tracing && !estimated_next_frame_begin_.is_null() && |
| 545 base::TimeTicks::Now() > estimated_next_frame_begin_) { |
| 546 TRACE_EVENT_ASYNC_STEP_INTO_WITH_TIMESTAMP0( |
| 547 "renderer.scheduler", |
| 548 "RendererSchedulerIdlePeriod", |
| 549 this, |
| 550 "DeadlineOverrun", |
| 551 estimated_next_frame_begin_.ToInternalValue()); |
| 552 } |
| 553 TRACE_EVENT_ASYNC_END0("renderer.scheduler", |
| 554 "RendererSchedulerIdlePeriod", this); |
412 } | 555 } |
413 TRACE_EVENT_ASYNC_END0("renderer.scheduler", | 556 |
414 "RendererSchedulerIdlePeriod", this); | |
415 DCHECK(main_thread_checker_.CalledOnValidThread()); | |
416 end_idle_period_closure_.Cancel(); | |
417 renderer_task_queue_selector_->DisableQueue(IDLE_TASK_QUEUE); | 557 renderer_task_queue_selector_->DisableQueue(IDLE_TASK_QUEUE); |
| 558 idle_period_state_ = IdlePeriodState::NOT_IN_IDLE_PERIOD; |
| 559 } |
| 560 |
| 561 // static |
| 562 bool RendererSchedulerImpl::IsInIdlePeriod(IdlePeriodState state) { |
| 563 return state != IdlePeriodState::NOT_IN_IDLE_PERIOD; |
418 } | 564 } |
419 | 565 |
420 void RendererSchedulerImpl::SetTimeSourceForTesting( | 566 void RendererSchedulerImpl::SetTimeSourceForTesting( |
421 scoped_refptr<cc::TestNowSource> time_source) { | 567 scoped_refptr<cc::TestNowSource> time_source) { |
422 DCHECK(main_thread_checker_.CalledOnValidThread()); | 568 DCHECK(main_thread_checker_.CalledOnValidThread()); |
423 time_source_ = time_source; | 569 time_source_ = time_source; |
424 task_queue_manager_->SetTimeSourceForTesting(time_source); | 570 task_queue_manager_->SetTimeSourceForTesting(time_source); |
425 } | 571 } |
426 | 572 |
427 void RendererSchedulerImpl::SetWorkBatchSizeForTesting(size_t work_batch_size) { | 573 void RendererSchedulerImpl::SetWorkBatchSizeForTesting(size_t work_batch_size) { |
428 DCHECK(main_thread_checker_.CalledOnValidThread()); | 574 DCHECK(main_thread_checker_.CalledOnValidThread()); |
429 task_queue_manager_->SetWorkBatchSize(work_batch_size); | 575 task_queue_manager_->SetWorkBatchSize(work_batch_size); |
430 } | 576 } |
431 | 577 |
| 578 void RendererSchedulerImpl::SetLongIdlePeriodsEnabledForTesting( |
| 579 bool long_idle_periods_enabled) { |
| 580 DCHECK(main_thread_checker_.CalledOnValidThread()); |
| 581 long_idle_periods_enabled_ = long_idle_periods_enabled; |
| 582 } |
| 583 |
432 base::TimeTicks RendererSchedulerImpl::Now() const { | 584 base::TimeTicks RendererSchedulerImpl::Now() const { |
433 return UNLIKELY(time_source_) ? time_source_->Now() : base::TimeTicks::Now(); | 585 return UNLIKELY(time_source_) ? time_source_->Now() : base::TimeTicks::Now(); |
434 } | 586 } |
435 | 587 |
436 RendererSchedulerImpl::PollableNeedsUpdateFlag::PollableNeedsUpdateFlag( | 588 RendererSchedulerImpl::PollableNeedsUpdateFlag::PollableNeedsUpdateFlag( |
437 base::Lock* write_lock_) | 589 base::Lock* write_lock_) |
438 : flag_(false), write_lock_(write_lock_) { | 590 : flag_(false), write_lock_(write_lock_) { |
439 } | 591 } |
440 | 592 |
441 RendererSchedulerImpl::PollableNeedsUpdateFlag::~PollableNeedsUpdateFlag() { | 593 RendererSchedulerImpl::PollableNeedsUpdateFlag::~PollableNeedsUpdateFlag() { |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
495 case InputStreamState::ACTIVE: | 647 case InputStreamState::ACTIVE: |
496 return "active"; | 648 return "active"; |
497 case InputStreamState::ACTIVE_AND_AWAITING_TOUCHSTART_RESPONSE: | 649 case InputStreamState::ACTIVE_AND_AWAITING_TOUCHSTART_RESPONSE: |
498 return "active_and_awaiting_touchstart_response"; | 650 return "active_and_awaiting_touchstart_response"; |
499 default: | 651 default: |
500 NOTREACHED(); | 652 NOTREACHED(); |
501 return nullptr; | 653 return nullptr; |
502 } | 654 } |
503 } | 655 } |
504 | 656 |
| 657 const char* RendererSchedulerImpl::IdlePeriodStateToString( |
| 658 IdlePeriodState idle_period_state) { |
| 659 switch (idle_period_state) { |
| 660 case IdlePeriodState::NOT_IN_IDLE_PERIOD: |
| 661 return "not_in_idle_period"; |
| 662 case IdlePeriodState::IN_SHORT_IDLE_PERIOD: |
| 663 return "in_short_idle_period"; |
| 664 case IdlePeriodState::IN_LONG_IDLE_PERIOD: |
| 665 return "in_long_idle_period"; |
| 666 case IdlePeriodState::IN_LONG_IDLE_PERIOD_WITH_MAX_DEADLINE: |
| 667 return "in_long_idle_period_with_max_deadline"; |
| 668 case IdlePeriodState::ENDING_LONG_IDLE_PERIOD: |
| 669 return "ending_long_idle_period"; |
| 670 default: |
| 671 NOTREACHED(); |
| 672 return nullptr; |
| 673 } |
| 674 } |
| 675 |
505 scoped_refptr<base::trace_event::ConvertableToTraceFormat> | 676 scoped_refptr<base::trace_event::ConvertableToTraceFormat> |
506 RendererSchedulerImpl::AsValueLocked(base::TimeTicks optional_now) const { | 677 RendererSchedulerImpl::AsValueLocked(base::TimeTicks optional_now) const { |
507 DCHECK(main_thread_checker_.CalledOnValidThread()); | 678 DCHECK(main_thread_checker_.CalledOnValidThread()); |
508 incoming_signals_lock_.AssertAcquired(); | 679 incoming_signals_lock_.AssertAcquired(); |
509 | 680 |
510 if (optional_now.is_null()) | 681 if (optional_now.is_null()) |
511 optional_now = Now(); | 682 optional_now = Now(); |
512 scoped_refptr<base::trace_event::TracedValue> state = | 683 scoped_refptr<base::trace_event::TracedValue> state = |
513 new base::trace_event::TracedValue(); | 684 new base::trace_event::TracedValue(); |
514 | 685 |
515 state->SetString("current_policy", PolicyToString(current_policy_)); | 686 state->SetString("current_policy", PolicyToString(current_policy_)); |
| 687 state->SetString("idle_period_state", |
| 688 IdlePeriodStateToString(idle_period_state_)); |
516 state->SetString("input_stream_state", | 689 state->SetString("input_stream_state", |
517 InputStreamStateToString(input_stream_state_)); | 690 InputStreamStateToString(input_stream_state_)); |
518 state->SetDouble("now", (optional_now - base::TimeTicks()).InMillisecondsF()); | 691 state->SetDouble("now", (optional_now - base::TimeTicks()).InMillisecondsF()); |
519 state->SetDouble("last_input_receipt_time_on_compositor_", | 692 state->SetDouble("last_input_receipt_time_on_compositor_", |
520 (last_input_receipt_time_on_compositor_ - base::TimeTicks()) | 693 (last_input_receipt_time_on_compositor_ - base::TimeTicks()) |
521 .InMillisecondsF()); | 694 .InMillisecondsF()); |
522 state->SetDouble( | 695 state->SetDouble( |
523 "last_input_process_time_on_main_", | 696 "last_input_process_time_on_main_", |
524 (last_input_process_time_on_main_ - base::TimeTicks()).InMillisecondsF()); | 697 (last_input_process_time_on_main_ - base::TimeTicks()).InMillisecondsF()); |
525 state->SetDouble( | 698 state->SetDouble( |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
573 } | 746 } |
574 | 747 |
575 void RendererSchedulerImpl::RemoveTaskObserver( | 748 void RendererSchedulerImpl::RemoveTaskObserver( |
576 base::MessageLoop::TaskObserver* task_observer) { | 749 base::MessageLoop::TaskObserver* task_observer) { |
577 DCHECK(main_thread_checker_.CalledOnValidThread()); | 750 DCHECK(main_thread_checker_.CalledOnValidThread()); |
578 if (task_queue_manager_) | 751 if (task_queue_manager_) |
579 task_queue_manager_->RemoveTaskObserver(task_observer); | 752 task_queue_manager_->RemoveTaskObserver(task_observer); |
580 } | 753 } |
581 | 754 |
582 } // namespace content | 755 } // namespace content |
OLD | NEW |