Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1016)

Side by Side Diff: cc/scheduler/scheduler.cc

Issue 1133673004: cc: Heuristic for Renderer latency recovery (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: rebase; really simplify heuristic Created 5 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2011 The Chromium Authors. All rights reserved. 1 // Copyright 2011 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 "cc/scheduler/scheduler.h" 5 #include "cc/scheduler/scheduler.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 8
9 #include "base/auto_reset.h" 9 #include "base/auto_reset.h"
10 #include "base/logging.h" 10 #include "base/logging.h"
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after
122 122
123 base::TimeTicks Scheduler::Now() const { 123 base::TimeTicks Scheduler::Now() const {
124 base::TimeTicks now = gfx::FrameTime::Now(); 124 base::TimeTicks now = gfx::FrameTime::Now();
125 TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler.now"), 125 TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler.now"),
126 "Scheduler::Now", 126 "Scheduler::Now",
127 "now", 127 "now",
128 now); 128 now);
129 return now; 129 return now;
130 } 130 }
131 131
132 void Scheduler::SetAuthoritativeVSyncInterval(const base::TimeDelta& interval) {
133 authoritative_vsync_interval_ = interval;
134 if (vsync_observer_)
135 vsync_observer_->OnUpdateVSyncParameters(last_vsync_timebase_, interval);
136 }
137
132 void Scheduler::CommitVSyncParameters(base::TimeTicks timebase, 138 void Scheduler::CommitVSyncParameters(base::TimeTicks timebase,
133 base::TimeDelta interval) { 139 base::TimeDelta interval) {
140 TRACE_EVENT2("cc", "Scheduler::CommitVSyncParameters", "timebase",
141 (timebase - base::TimeTicks()).InSecondsF(), "interval",
142 interval.InSecondsF());
143
134 if (authoritative_vsync_interval_ != base::TimeDelta()) { 144 if (authoritative_vsync_interval_ != base::TimeDelta()) {
135 interval = authoritative_vsync_interval_; 145 interval = authoritative_vsync_interval_;
136 } else if (interval == base::TimeDelta()) { 146 } else if (interval == base::TimeDelta()) {
137 // TODO(brianderson): We should not be receiving 0 intervals. 147 // TODO(brianderson): We should not be receiving 0 intervals.
138 interval = BeginFrameArgs::DefaultInterval(); 148 interval = BeginFrameArgs::DefaultInterval();
139 } 149 }
140 150
141 last_vsync_timebase_ = timebase; 151 last_vsync_timebase_ = timebase;
142 152
143 if (vsync_observer_) 153 if (vsync_observer_)
(...skipping 236 matching lines...) Expand 10 before | Expand all | Expand 10 after
380 BeginImplFrameWithDeadline(adjusted_args); 390 BeginImplFrameWithDeadline(adjusted_args);
381 } 391 }
382 return true; 392 return true;
383 } 393 }
384 394
385 void Scheduler::SetChildrenNeedBeginFrames(bool children_need_begin_frames) { 395 void Scheduler::SetChildrenNeedBeginFrames(bool children_need_begin_frames) {
386 state_machine_.SetChildrenNeedBeginFrames(children_need_begin_frames); 396 state_machine_.SetChildrenNeedBeginFrames(children_need_begin_frames);
387 ProcessScheduledActions(); 397 ProcessScheduledActions();
388 } 398 }
389 399
390 void Scheduler::SetAuthoritativeVSyncInterval(const base::TimeDelta& interval) {
391 authoritative_vsync_interval_ = interval;
392 if (vsync_observer_)
393 vsync_observer_->OnUpdateVSyncParameters(last_vsync_timebase_, interval);
394 }
395
396 void Scheduler::SetVideoNeedsBeginFrames(bool video_needs_begin_frames) { 400 void Scheduler::SetVideoNeedsBeginFrames(bool video_needs_begin_frames) {
397 state_machine_.SetVideoNeedsBeginFrames(video_needs_begin_frames); 401 state_machine_.SetVideoNeedsBeginFrames(video_needs_begin_frames);
398 ProcessScheduledActions(); 402 ProcessScheduledActions();
399 } 403 }
400 404
401 void Scheduler::OnDrawForOutputSurface() { 405 void Scheduler::OnDrawForOutputSurface() {
402 DCHECK(settings_.using_synchronous_renderer_compositor); 406 DCHECK(settings_.using_synchronous_renderer_compositor);
403 DCHECK_EQ(state_machine_.begin_impl_frame_state(), 407 DCHECK_EQ(state_machine_.begin_impl_frame_state(),
404 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE); 408 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE);
405 DCHECK(!BeginImplFrameDeadlinePending()); 409 DCHECK(!BeginImplFrameDeadlinePending());
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
491 args.AsValue(), "main_thread_is_high_latency", 495 args.AsValue(), "main_thread_is_high_latency",
492 main_thread_is_in_high_latency_mode); 496 main_thread_is_in_high_latency_mode);
493 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler"), 497 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler"),
494 "MainThreadLatency", main_thread_is_in_high_latency_mode); 498 "MainThreadLatency", main_thread_is_in_high_latency_mode);
495 499
496 advance_commit_state_task_.Cancel(); 500 advance_commit_state_task_.Cancel();
497 501
498 begin_impl_frame_args_ = args; 502 begin_impl_frame_args_ = args;
499 begin_impl_frame_args_.deadline -= client_->DrawDurationEstimate(); 503 begin_impl_frame_args_.deadline -= client_->DrawDurationEstimate();
500 504
501 if (!state_machine_.impl_latency_takes_priority() && 505 if (ShouldRecoverMainLatency()) {
502 main_thread_is_in_high_latency_mode && 506 TRACE_EVENT_INSTANT0("cc", "SkipBeginMainFrameToReduceLatency",
503 CanCommitAndActivateBeforeDeadline()) { 507 TRACE_EVENT_SCOPE_THREAD);
504 state_machine_.SetSkipNextBeginMainFrameToReduceLatency(); 508 state_machine_.SetSkipNextBeginMainFrameToReduceLatency();
509 } else if (ShouldRecoverImplLatency()) {
sunnyps 2015/05/22 21:15:04 Does it make sense to prioritize skipping impl fra
brianderson 2015/06/30 22:03:52 I prioritize skipping the main frame first for two
510 TRACE_EVENT_INSTANT0("cc", "SkipBeginImplFrameToReduceLatency",
511 TRACE_EVENT_SCOPE_THREAD);
512 ProcessScheduledActions();
513 return;
sunnyps 2015/05/22 21:15:05 FinishImplFrame should be called here, right?
brianderson 2015/05/23 00:53:56 Ah! I am missing a call to frame_source_->DidFinis
505 } 514 }
506 515
507 BeginImplFrame(); 516 BeginImplFrame();
508 517
509 // The deadline will be scheduled in ProcessScheduledActions. 518 // The deadline will be scheduled in ProcessScheduledActions.
510 state_machine_.OnBeginImplFrameDeadlinePending(); 519 state_machine_.OnBeginImplFrameDeadlinePending();
511 ProcessScheduledActions(); 520 ProcessScheduledActions();
512 } 521 }
513 522
514 void Scheduler::BeginImplFrameSynchronous(const BeginFrameArgs& args) { 523 void Scheduler::BeginImplFrameSynchronous(const BeginFrameArgs& args) {
515 TRACE_EVENT1("cc,benchmark", "Scheduler::BeginImplFrame", "args", 524 TRACE_EVENT1("cc,benchmark", "Scheduler::BeginImplFrame", "args",
516 args.AsValue()); 525 args.AsValue());
517 begin_impl_frame_args_ = args; 526 begin_impl_frame_args_ = args;
518 BeginImplFrame(); 527 BeginImplFrame();
528
519 FinishImplFrame(); 529 FinishImplFrame();
520 } 530 }
521 531
522 void Scheduler::FinishImplFrame() { 532 void Scheduler::FinishImplFrame() {
523 state_machine_.OnBeginImplFrameIdle(); 533 state_machine_.OnBeginImplFrameIdle();
524 ProcessScheduledActions(); 534 ProcessScheduledActions();
525 535
526 client_->DidFinishImplFrame(); 536 client_->DidFinishImplFrame();
527 frame_source_->DidFinishFrame(begin_retro_frame_args_.size()); 537 frame_source_->DidFinishFrame(begin_retro_frame_args_.size());
528 } 538 }
(...skipping 17 matching lines...) Expand all
546 556
547 void Scheduler::ScheduleBeginImplFrameDeadline() { 557 void Scheduler::ScheduleBeginImplFrameDeadline() {
548 // The synchronous compositor does not post a deadline task. 558 // The synchronous compositor does not post a deadline task.
549 DCHECK(!settings_.using_synchronous_renderer_compositor); 559 DCHECK(!settings_.using_synchronous_renderer_compositor);
550 560
551 begin_impl_frame_deadline_task_.Cancel(); 561 begin_impl_frame_deadline_task_.Cancel();
552 begin_impl_frame_deadline_task_.Reset(begin_impl_frame_deadline_closure_); 562 begin_impl_frame_deadline_task_.Reset(begin_impl_frame_deadline_closure_);
553 563
554 begin_impl_frame_deadline_mode_ = 564 begin_impl_frame_deadline_mode_ =
555 state_machine_.CurrentBeginImplFrameDeadlineMode(); 565 state_machine_.CurrentBeginImplFrameDeadlineMode();
556
557 base::TimeTicks deadline; 566 base::TimeTicks deadline;
558 switch (begin_impl_frame_deadline_mode_) { 567 switch (begin_impl_frame_deadline_mode_) {
559 case SchedulerStateMachine::BEGIN_IMPL_FRAME_DEADLINE_MODE_NONE: 568 case SchedulerStateMachine::BEGIN_IMPL_FRAME_DEADLINE_MODE_NONE:
560 // No deadline. 569 // No deadline.
561 return; 570 return;
562 case SchedulerStateMachine::BEGIN_IMPL_FRAME_DEADLINE_MODE_IMMEDIATE: 571 case SchedulerStateMachine::BEGIN_IMPL_FRAME_DEADLINE_MODE_IMMEDIATE:
563 // We are ready to draw a new active tree immediately. 572 // We are ready to draw a new active tree immediately.
564 // We don't use Now() here because it's somewhat expensive to call. 573 // We don't use Now() here because it's somewhat expensive to call.
565 deadline = base::TimeTicks(); 574 deadline = base::TimeTicks();
566 break; 575 break;
(...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after
764 state->SetInteger("begin_retro_frame_args_", begin_retro_frame_args_.size()); 773 state->SetInteger("begin_retro_frame_args_", begin_retro_frame_args_.size());
765 state->SetBoolean("begin_retro_frame_task_", 774 state->SetBoolean("begin_retro_frame_task_",
766 !begin_retro_frame_task_.IsCancelled()); 775 !begin_retro_frame_task_.IsCancelled());
767 state->SetBoolean("begin_impl_frame_deadline_task_", 776 state->SetBoolean("begin_impl_frame_deadline_task_",
768 !begin_impl_frame_deadline_task_.IsCancelled()); 777 !begin_impl_frame_deadline_task_.IsCancelled());
769 state->SetBoolean("advance_commit_state_task_", 778 state->SetBoolean("advance_commit_state_task_",
770 !advance_commit_state_task_.IsCancelled()); 779 !advance_commit_state_task_.IsCancelled());
771 state->BeginDictionary("begin_impl_frame_args"); 780 state->BeginDictionary("begin_impl_frame_args");
772 begin_impl_frame_args_.AsValueInto(state); 781 begin_impl_frame_args_.AsValueInto(state);
773 state->EndDictionary(); 782 state->EndDictionary();
783 state->SetString("begin_impl_frame_deadline_mode_",
784 SchedulerStateMachine::BeginImplFrameDeadlineModeToString(
785 begin_impl_frame_deadline_mode_));
774 786
775 base::TimeTicks now = Now(); 787 base::TimeTicks now = Now();
776 base::TimeTicks frame_time = begin_impl_frame_args_.frame_time; 788 base::TimeTicks frame_time = begin_impl_frame_args_.frame_time;
777 base::TimeTicks deadline = begin_impl_frame_args_.deadline; 789 base::TimeTicks deadline = begin_impl_frame_args_.deadline;
778 base::TimeDelta interval = begin_impl_frame_args_.interval; 790 base::TimeDelta interval = begin_impl_frame_args_.interval;
779 state->BeginDictionary("major_timestamps_in_ms"); 791 state->BeginDictionary("major_timestamps_in_ms");
780 state->SetDouble("0_interval", interval.InMillisecondsF()); 792 state->SetDouble("0_interval", interval.InMillisecondsF());
781 state->SetDouble("1_now_to_deadline", (deadline - now).InMillisecondsF()); 793 state->SetDouble("1_now_to_deadline", (deadline - now).InMillisecondsF());
782 state->SetDouble("2_frame_time_to_now", (now - frame_time).InMillisecondsF()); 794 state->SetDouble("2_frame_time_to_now", (now - frame_time).InMillisecondsF());
783 state->SetDouble("3_frame_time_to_deadline", 795 state->SetDouble("3_frame_time_to_deadline",
(...skipping 12 matching lines...) Expand all
796 client_->DrawDurationEstimate().InMillisecondsF()); 808 client_->DrawDurationEstimate().InMillisecondsF());
797 state->SetDouble( 809 state->SetDouble(
798 "begin_main_frame_to_commit_duration_estimate_ms", 810 "begin_main_frame_to_commit_duration_estimate_ms",
799 client_->BeginMainFrameToCommitDurationEstimate().InMillisecondsF()); 811 client_->BeginMainFrameToCommitDurationEstimate().InMillisecondsF());
800 state->SetDouble( 812 state->SetDouble(
801 "commit_to_activate_duration_estimate_ms", 813 "commit_to_activate_duration_estimate_ms",
802 client_->CommitToActivateDurationEstimate().InMillisecondsF()); 814 client_->CommitToActivateDurationEstimate().InMillisecondsF());
803 state->EndDictionary(); 815 state->EndDictionary();
804 } 816 }
805 817
818 bool Scheduler::ShouldRecoverMainLatency() const {
819 if (!state_machine_.MainThreadIsInHighLatencyMode())
820 return false;
821
822 if (state_machine_.impl_latency_takes_priority())
823 return false;
824
825 return CanCommitAndActivateBeforeDeadline();
826 }
827
828 bool Scheduler::ShouldRecoverImplLatency() const {
829 if (!state_machine_.ImplThreadIsLikelyInHighLatencyMode())
830 return false;
831
832 bool frame_time_is_before_deadline =
833 begin_impl_frame_args_.frame_time < begin_impl_frame_args_.deadline;
834
835 SchedulerStateMachine::BeginImplFrameDeadlineMode
836 next_begin_impl_frame_deadline_mode =
837 state_machine_.CurrentBeginImplFrameDeadlineMode();
838 switch (next_begin_impl_frame_deadline_mode) {
839 case SchedulerStateMachine::BEGIN_IMPL_FRAME_DEADLINE_MODE_NONE:
840 return false;
841 case SchedulerStateMachine::BEGIN_IMPL_FRAME_DEADLINE_MODE_IMMEDIATE:
842 return frame_time_is_before_deadline;
843 case SchedulerStateMachine::BEGIN_IMPL_FRAME_DEADLINE_MODE_REGULAR:
844 return frame_time_is_before_deadline;
845 case SchedulerStateMachine::BEGIN_IMPL_FRAME_DEADLINE_MODE_LATE:
846 return CanCommitAndActivateBeforeDeadline();
847 case SchedulerStateMachine::
848 BEGIN_IMPL_FRAME_DEADLINE_MODE_BLOCKED_ON_READY_TO_DRAW:
849 return false;
850 }
851 NOTREACHED();
852 return false;
853 }
854
806 bool Scheduler::CanCommitAndActivateBeforeDeadline() const { 855 bool Scheduler::CanCommitAndActivateBeforeDeadline() const {
807 // Check if the main thread computation and commit can be finished before the 856 // Check if the main thread computation and commit can be finished before the
808 // impl thread's deadline. 857 // impl thread's deadline.
809 base::TimeTicks estimated_draw_time = 858 base::TimeTicks estimated_draw_time =
810 begin_impl_frame_args_.frame_time + 859 begin_impl_frame_args_.frame_time +
811 client_->BeginMainFrameToCommitDurationEstimate() + 860 client_->BeginMainFrameToCommitDurationEstimate() +
812 client_->CommitToActivateDurationEstimate(); 861 client_->CommitToActivateDurationEstimate();
813 862
814 TRACE_EVENT2(
815 TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler"),
816 "CanCommitAndActivateBeforeDeadline",
817 "time_left_after_drawing_ms",
818 (begin_impl_frame_args_.deadline - estimated_draw_time).InMillisecondsF(),
819 "state",
820 AsValue());
821
822 return estimated_draw_time < begin_impl_frame_args_.deadline; 863 return estimated_draw_time < begin_impl_frame_args_.deadline;
823 } 864 }
824 865
825 bool Scheduler::IsBeginMainFrameSentOrStarted() const { 866 bool Scheduler::IsBeginMainFrameSentOrStarted() const {
826 return (state_machine_.commit_state() == 867 return (state_machine_.commit_state() ==
827 SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT || 868 SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT ||
828 state_machine_.commit_state() == 869 state_machine_.commit_state() ==
829 SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_STARTED); 870 SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_STARTED);
830 } 871 }
831 872
832 } // namespace cc 873 } // namespace cc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698