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

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: rebaswe Created 5 years, 5 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
« no previous file with comments | « cc/scheduler/scheduler.h ('k') | cc/scheduler/scheduler_state_machine.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 442 matching lines...) Expand 10 before | Expand all | Expand 10 after
453 state_machine_.MainThreadIsInHighLatencyMode(); 453 state_machine_.MainThreadIsInHighLatencyMode();
454 TRACE_EVENT2("cc,benchmark", "Scheduler::BeginImplFrame", "args", 454 TRACE_EVENT2("cc,benchmark", "Scheduler::BeginImplFrame", "args",
455 args.AsValue(), "main_thread_is_high_latency", 455 args.AsValue(), "main_thread_is_high_latency",
456 main_thread_is_in_high_latency_mode); 456 main_thread_is_in_high_latency_mode);
457 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler"), 457 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler"),
458 "MainThreadLatency", main_thread_is_in_high_latency_mode); 458 "MainThreadLatency", main_thread_is_in_high_latency_mode);
459 459
460 BeginFrameArgs adjusted_args = args; 460 BeginFrameArgs adjusted_args = args;
461 adjusted_args.deadline -= compositor_timing_history_->DrawDurationEstimate(); 461 adjusted_args.deadline -= compositor_timing_history_->DrawDurationEstimate();
462 462
463 if (!state_machine_.impl_latency_takes_priority() && 463 if (ShouldRecoverMainLatency(adjusted_args)) {
464 main_thread_is_in_high_latency_mode && 464 TRACE_EVENT_INSTANT0("cc", "SkipBeginMainFrameToReduceLatency",
465 CanCommitAndActivateBeforeDeadline()) { 465 TRACE_EVENT_SCOPE_THREAD);
466 state_machine_.SetSkipNextBeginMainFrameToReduceLatency(); 466 state_machine_.SetSkipNextBeginMainFrameToReduceLatency();
467 } else if (ShouldRecoverImplLatency(adjusted_args)) {
468 TRACE_EVENT_INSTANT0("cc", "SkipBeginImplFrameToReduceLatency",
469 TRACE_EVENT_SCOPE_THREAD);
470 frame_source_->DidFinishFrame(begin_retro_frame_args_.size());
471 return;
467 } 472 }
468 473
469 BeginImplFrame(adjusted_args); 474 BeginImplFrame(adjusted_args);
470 475
471 // The deadline will be scheduled in ProcessScheduledActions. 476 // The deadline will be scheduled in ProcessScheduledActions.
472 state_machine_.OnBeginImplFrameDeadlinePending(); 477 state_machine_.OnBeginImplFrameDeadlinePending();
473 ProcessScheduledActions(); 478 ProcessScheduledActions();
474 } 479 }
475 480
476 void Scheduler::BeginImplFrameSynchronous(const BeginFrameArgs& args) { 481 void Scheduler::BeginImplFrameSynchronous(const BeginFrameArgs& args) {
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
508 513
509 void Scheduler::ScheduleBeginImplFrameDeadline() { 514 void Scheduler::ScheduleBeginImplFrameDeadline() {
510 // The synchronous compositor does not post a deadline task. 515 // The synchronous compositor does not post a deadline task.
511 DCHECK(!settings_.using_synchronous_renderer_compositor); 516 DCHECK(!settings_.using_synchronous_renderer_compositor);
512 517
513 begin_impl_frame_deadline_task_.Cancel(); 518 begin_impl_frame_deadline_task_.Cancel();
514 begin_impl_frame_deadline_task_.Reset(begin_impl_frame_deadline_closure_); 519 begin_impl_frame_deadline_task_.Reset(begin_impl_frame_deadline_closure_);
515 520
516 begin_impl_frame_deadline_mode_ = 521 begin_impl_frame_deadline_mode_ =
517 state_machine_.CurrentBeginImplFrameDeadlineMode(); 522 state_machine_.CurrentBeginImplFrameDeadlineMode();
518
519 base::TimeTicks deadline; 523 base::TimeTicks deadline;
520 switch (begin_impl_frame_deadline_mode_) { 524 switch (begin_impl_frame_deadline_mode_) {
521 case SchedulerStateMachine::BEGIN_IMPL_FRAME_DEADLINE_MODE_NONE: 525 case SchedulerStateMachine::BEGIN_IMPL_FRAME_DEADLINE_MODE_NONE:
522 // No deadline. 526 // No deadline.
523 return; 527 return;
524 case SchedulerStateMachine::BEGIN_IMPL_FRAME_DEADLINE_MODE_IMMEDIATE: 528 case SchedulerStateMachine::BEGIN_IMPL_FRAME_DEADLINE_MODE_IMMEDIATE:
525 // We are ready to draw a new active tree immediately. 529 // We are ready to draw a new active tree immediately.
526 // We don't use Now() here because it's somewhat expensive to call. 530 // We don't use Now() here because it's somewhat expensive to call.
527 deadline = base::TimeTicks(); 531 deadline = base::TimeTicks();
528 break; 532 break;
(...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after
690 694
691 scoped_refptr<base::trace_event::ConvertableToTraceFormat> Scheduler::AsValue() 695 scoped_refptr<base::trace_event::ConvertableToTraceFormat> Scheduler::AsValue()
692 const { 696 const {
693 scoped_refptr<base::trace_event::TracedValue> state = 697 scoped_refptr<base::trace_event::TracedValue> state =
694 new base::trace_event::TracedValue(); 698 new base::trace_event::TracedValue();
695 AsValueInto(state.get()); 699 AsValueInto(state.get());
696 return state; 700 return state;
697 } 701 }
698 702
699 void Scheduler::AsValueInto(base::trace_event::TracedValue* state) const { 703 void Scheduler::AsValueInto(base::trace_event::TracedValue* state) const {
704 base::TimeTicks now = Now();
705
700 state->BeginDictionary("state_machine"); 706 state->BeginDictionary("state_machine");
701 state_machine_.AsValueInto(state); 707 state_machine_.AsValueInto(state);
702 state->EndDictionary(); 708 state->EndDictionary();
703 709
704 // Only trace frame sources when explicitly enabled - http://crbug.com/420607 710 // Only trace frame sources when explicitly enabled - http://crbug.com/420607
705 bool frame_tracing_enabled = false; 711 bool frame_tracing_enabled = false;
706 TRACE_EVENT_CATEGORY_GROUP_ENABLED( 712 TRACE_EVENT_CATEGORY_GROUP_ENABLED(
707 TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler.frames"), 713 TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler.frames"),
708 &frame_tracing_enabled); 714 &frame_tracing_enabled);
709 if (frame_tracing_enabled) { 715 if (frame_tracing_enabled) {
710 state->BeginDictionary("frame_source_"); 716 state->BeginDictionary("frame_source_");
711 frame_source_->AsValueInto(state); 717 frame_source_->AsValueInto(state);
712 state->EndDictionary(); 718 state->EndDictionary();
713 } 719 }
714 720
715 state->BeginDictionary("scheduler_state"); 721 state->BeginDictionary("scheduler_state");
716 state->SetDouble("estimated_parent_draw_time_ms", 722 state->SetDouble("estimated_parent_draw_time_ms",
717 estimated_parent_draw_time_.InMillisecondsF()); 723 estimated_parent_draw_time_.InMillisecondsF());
718 state->SetBoolean("last_set_needs_begin_frame_", 724 state->SetBoolean("last_set_needs_begin_frame_",
719 frame_source_->NeedsBeginFrames()); 725 frame_source_->NeedsBeginFrames());
720 state->SetInteger("begin_retro_frame_args", 726 state->SetInteger("begin_retro_frame_args",
721 static_cast<int>(begin_retro_frame_args_.size())); 727 static_cast<int>(begin_retro_frame_args_.size()));
722 state->SetBoolean("begin_retro_frame_task", 728 state->SetBoolean("begin_retro_frame_task",
723 !begin_retro_frame_task_.IsCancelled()); 729 !begin_retro_frame_task_.IsCancelled());
724 state->SetBoolean("begin_impl_frame_deadline_task", 730 state->SetBoolean("begin_impl_frame_deadline_task",
725 !begin_impl_frame_deadline_task_.IsCancelled()); 731 !begin_impl_frame_deadline_task_.IsCancelled());
726 state->SetString("inside_action", 732 state->SetString("inside_action",
727 SchedulerStateMachine::ActionToString(inside_action_)); 733 SchedulerStateMachine::ActionToString(inside_action_));
734
728 state->BeginDictionary("begin_impl_frame_args"); 735 state->BeginDictionary("begin_impl_frame_args");
729 begin_impl_frame_tracker_.AsValueInto(Now(), state); 736 begin_impl_frame_tracker_.AsValueInto(now, state);
730 state->EndDictionary(); 737 state->EndDictionary();
738
739 state->SetString("begin_impl_frame_deadline_mode_",
740 SchedulerStateMachine::BeginImplFrameDeadlineModeToString(
741 begin_impl_frame_deadline_mode_));
731 state->EndDictionary(); 742 state->EndDictionary();
732 743
733 state->BeginDictionary("compositor_timing_history"); 744 state->BeginDictionary("compositor_timing_history");
734 compositor_timing_history_->AsValueInto(state); 745 compositor_timing_history_->AsValueInto(state);
735 state->EndDictionary(); 746 state->EndDictionary();
736 } 747 }
737 748
738 void Scheduler::UpdateCompositorTimingHistoryRecordingEnabled() { 749 void Scheduler::UpdateCompositorTimingHistoryRecordingEnabled() {
739 compositor_timing_history_->SetRecordingEnabled( 750 compositor_timing_history_->SetRecordingEnabled(
740 state_machine_.HasInitializedOutputSurface() && state_machine_.visible()); 751 state_machine_.HasInitializedOutputSurface() && state_machine_.visible());
741 } 752 }
742 753
743 bool Scheduler::CanCommitAndActivateBeforeDeadline() const { 754 bool Scheduler::ShouldRecoverMainLatency(const BeginFrameArgs& args) const {
744 BeginFrameArgs args = 755 DCHECK(!settings_.using_synchronous_renderer_compositor);
745 begin_impl_frame_tracker_.DangerousMethodCurrentOrLast();
746 756
757 if (!state_machine_.MainThreadIsInHighLatencyMode())
758 return false;
759
760 // When prioritizing impl thread latency, we currently put the
761 // main thread in a high latency mode. Don't try to fight it.
762 if (state_machine_.impl_latency_takes_priority())
763 return false;
764
765 return CanCommitAndActivateBeforeDeadline(args);
766 }
767
768 bool Scheduler::ShouldRecoverImplLatency(const BeginFrameArgs& args) const {
769 DCHECK(!settings_.using_synchronous_renderer_compositor);
770
771 // If we are swap throttled at the BeginFrame, that means the impl thread is
772 // very likely in a high latency mode.
773 bool impl_thread_is_likely_high_latency = state_machine_.SwapThrottled();
774 if (!impl_thread_is_likely_high_latency)
775 return false;
776
777 // The deadline may be in the past if our draw time is too long.
778 bool can_draw_before_deadline = args.frame_time < args.deadline;
779
780 // When prioritizing impl thread latency, the deadline doesn't wait
781 // for the main thread.
782 if (state_machine_.impl_latency_takes_priority())
783 return can_draw_before_deadline;
784
785 // If we only have impl-side updates, the deadline doesn't wait for
786 // the main thread.
787 if (state_machine_.OnlyImplSideUpdatesExpected())
788 return can_draw_before_deadline;
789
790 // If we get here, we know the main thread is in a low-latency mode relative
791 // to the impl thread. In this case, only try to also recover impl thread
792 // latency if both the main and impl threads can run serially before the
793 // deadline.
794 return CanCommitAndActivateBeforeDeadline(args);
795 }
796
797 bool Scheduler::CanCommitAndActivateBeforeDeadline(
798 const BeginFrameArgs& args) const {
747 // Check if the main thread computation and commit can be finished before the 799 // Check if the main thread computation and commit can be finished before the
748 // impl thread's deadline. 800 // impl thread's deadline.
749 base::TimeTicks estimated_draw_time = 801 base::TimeTicks estimated_draw_time =
750 args.frame_time + 802 args.frame_time +
751 compositor_timing_history_->BeginMainFrameToCommitDurationEstimate() + 803 compositor_timing_history_->BeginMainFrameToCommitDurationEstimate() +
752 compositor_timing_history_->CommitToReadyToActivateDurationEstimate() + 804 compositor_timing_history_->CommitToReadyToActivateDurationEstimate() +
753 compositor_timing_history_->ActivateDurationEstimate(); 805 compositor_timing_history_->ActivateDurationEstimate();
754 806
755 TRACE_EVENT2(TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler"),
756 "CanCommitAndActivateBeforeDeadline",
757 "time_left_after_drawing_ms",
758 (args.deadline - estimated_draw_time).InMillisecondsF(), "state",
759 AsValue());
760
761 return estimated_draw_time < args.deadline; 807 return estimated_draw_time < args.deadline;
762 } 808 }
763 809
764 bool Scheduler::IsBeginMainFrameSentOrStarted() const { 810 bool Scheduler::IsBeginMainFrameSentOrStarted() const {
765 return (state_machine_.commit_state() == 811 return (state_machine_.commit_state() ==
766 SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT || 812 SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT ||
767 state_machine_.commit_state() == 813 state_machine_.commit_state() ==
768 SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_STARTED); 814 SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_STARTED);
769 } 815 }
770 816
771 } // namespace cc 817 } // namespace cc
OLDNEW
« no previous file with comments | « cc/scheduler/scheduler.h ('k') | cc/scheduler/scheduler_state_machine.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698