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

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, address comments 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
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 441 matching lines...) Expand 10 before | Expand all | Expand 10 after
452 bool main_thread_is_in_high_latency_mode = 452 bool main_thread_is_in_high_latency_mode =
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 begin_impl_frame_tracker_.Start(adjusted_args);
462 463
463 if (!state_machine_.impl_latency_takes_priority() && 464 if (ShouldRecoverMainLatency()) {
464 main_thread_is_in_high_latency_mode && 465 TRACE_EVENT_INSTANT0("cc", "SkipBeginMainFrameToReduceLatency",
465 CanCommitAndActivateBeforeDeadline()) { 466 TRACE_EVENT_SCOPE_THREAD);
466 state_machine_.SetSkipNextBeginMainFrameToReduceLatency(); 467 state_machine_.SetSkipNextBeginMainFrameToReduceLatency();
468 } else if (ShouldRecoverImplLatency()) {
469 TRACE_EVENT_INSTANT0("cc", "SkipBeginImplFrameToReduceLatency",
470 TRACE_EVENT_SCOPE_THREAD);
471 frame_source_->DidFinishFrame(begin_retro_frame_args_.size());
472 begin_impl_frame_tracker_.Finish();
473 return;
467 } 474 }
468 475
469 BeginImplFrame(adjusted_args); 476 BeginImplFrame();
mithro-old 2015/07/06 11:58:42 As discussed, you were going to change this code b
brianderson 2015/07/07 02:04:49 Done.
470 477
471 // The deadline will be scheduled in ProcessScheduledActions. 478 // The deadline will be scheduled in ProcessScheduledActions.
472 state_machine_.OnBeginImplFrameDeadlinePending(); 479 state_machine_.OnBeginImplFrameDeadlinePending();
473 ProcessScheduledActions(); 480 ProcessScheduledActions();
474 } 481 }
475 482
476 void Scheduler::BeginImplFrameSynchronous(const BeginFrameArgs& args) { 483 void Scheduler::BeginImplFrameSynchronous(const BeginFrameArgs& args) {
477 TRACE_EVENT1("cc,benchmark", "Scheduler::BeginImplFrame", "args", 484 TRACE_EVENT1("cc,benchmark", "Scheduler::BeginImplFrame", "args",
478 args.AsValue()); 485 args.AsValue());
479 BeginImplFrame(args); 486 begin_impl_frame_tracker_.Start(args);
487 BeginImplFrame();
480 FinishImplFrame(); 488 FinishImplFrame();
481 } 489 }
482 490
483 void Scheduler::FinishImplFrame() { 491 void Scheduler::FinishImplFrame() {
484 state_machine_.OnBeginImplFrameIdle(); 492 state_machine_.OnBeginImplFrameIdle();
485 ProcessScheduledActions(); 493 ProcessScheduledActions();
486 494
487 client_->DidFinishImplFrame(); 495 client_->DidFinishImplFrame();
488 frame_source_->DidFinishFrame(begin_retro_frame_args_.size()); 496 frame_source_->DidFinishFrame(begin_retro_frame_args_.size());
489 begin_impl_frame_tracker_.Finish(); 497 begin_impl_frame_tracker_.Finish();
490 } 498 }
491 499
492 // BeginImplFrame starts a compositor frame that will wait up until a deadline 500 // BeginImplFrame starts a compositor frame that will wait up until a deadline
493 // for a BeginMainFrame+activation to complete before it times out and draws 501 // for a BeginMainFrame+activation to complete before it times out and draws
494 // any asynchronous animation and scroll/pinch updates. 502 // any asynchronous animation and scroll/pinch updates.
495 void Scheduler::BeginImplFrame(const BeginFrameArgs& args) { 503 void Scheduler::BeginImplFrame() {
496 DCHECK_EQ(state_machine_.begin_impl_frame_state(), 504 DCHECK_EQ(state_machine_.begin_impl_frame_state(),
497 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE); 505 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE);
498 DCHECK(!BeginImplFrameDeadlinePending()); 506 DCHECK(!BeginImplFrameDeadlinePending());
499 DCHECK(state_machine_.HasInitializedOutputSurface()); 507 DCHECK(state_machine_.HasInitializedOutputSurface());
500 508
501 begin_impl_frame_tracker_.Start(args);
502 state_machine_.OnBeginImplFrame(); 509 state_machine_.OnBeginImplFrame();
503 devtools_instrumentation::DidBeginFrame(layer_tree_host_id_); 510 devtools_instrumentation::DidBeginFrame(layer_tree_host_id_);
504 client_->WillBeginImplFrame(begin_impl_frame_tracker_.Current()); 511 client_->WillBeginImplFrame(begin_impl_frame_tracker_.Current());
505 512
506 ProcessScheduledActions(); 513 ProcessScheduledActions();
507 } 514 }
508 515
509 void Scheduler::ScheduleBeginImplFrameDeadline() { 516 void Scheduler::ScheduleBeginImplFrameDeadline() {
510 // The synchronous compositor does not post a deadline task. 517 // The synchronous compositor does not post a deadline task.
511 DCHECK(!settings_.using_synchronous_renderer_compositor); 518 DCHECK(!settings_.using_synchronous_renderer_compositor);
512 519
513 begin_impl_frame_deadline_task_.Cancel(); 520 begin_impl_frame_deadline_task_.Cancel();
514 begin_impl_frame_deadline_task_.Reset(begin_impl_frame_deadline_closure_); 521 begin_impl_frame_deadline_task_.Reset(begin_impl_frame_deadline_closure_);
515 522
516 begin_impl_frame_deadline_mode_ = 523 begin_impl_frame_deadline_mode_ =
517 state_machine_.CurrentBeginImplFrameDeadlineMode(); 524 state_machine_.CurrentBeginImplFrameDeadlineMode();
518
519 base::TimeTicks deadline; 525 base::TimeTicks deadline;
520 switch (begin_impl_frame_deadline_mode_) { 526 switch (begin_impl_frame_deadline_mode_) {
521 case SchedulerStateMachine::BEGIN_IMPL_FRAME_DEADLINE_MODE_NONE: 527 case SchedulerStateMachine::BEGIN_IMPL_FRAME_DEADLINE_MODE_NONE:
522 // No deadline. 528 // No deadline.
523 return; 529 return;
524 case SchedulerStateMachine::BEGIN_IMPL_FRAME_DEADLINE_MODE_IMMEDIATE: 530 case SchedulerStateMachine::BEGIN_IMPL_FRAME_DEADLINE_MODE_IMMEDIATE:
525 // We are ready to draw a new active tree immediately. 531 // We are ready to draw a new active tree immediately.
526 // We don't use Now() here because it's somewhat expensive to call. 532 // We don't use Now() here because it's somewhat expensive to call.
527 deadline = base::TimeTicks(); 533 deadline = base::TimeTicks();
528 break; 534 break;
(...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after
690 696
691 scoped_refptr<base::trace_event::ConvertableToTraceFormat> Scheduler::AsValue() 697 scoped_refptr<base::trace_event::ConvertableToTraceFormat> Scheduler::AsValue()
692 const { 698 const {
693 scoped_refptr<base::trace_event::TracedValue> state = 699 scoped_refptr<base::trace_event::TracedValue> state =
694 new base::trace_event::TracedValue(); 700 new base::trace_event::TracedValue();
695 AsValueInto(state.get()); 701 AsValueInto(state.get());
696 return state; 702 return state;
697 } 703 }
698 704
699 void Scheduler::AsValueInto(base::trace_event::TracedValue* state) const { 705 void Scheduler::AsValueInto(base::trace_event::TracedValue* state) const {
706 base::TimeTicks now = Now();
707
700 state->BeginDictionary("state_machine"); 708 state->BeginDictionary("state_machine");
701 state_machine_.AsValueInto(state); 709 state_machine_.AsValueInto(state);
702 state->EndDictionary(); 710 state->EndDictionary();
703 711
704 // Only trace frame sources when explicitly enabled - http://crbug.com/420607 712 // Only trace frame sources when explicitly enabled - http://crbug.com/420607
705 bool frame_tracing_enabled = false; 713 bool frame_tracing_enabled = false;
706 TRACE_EVENT_CATEGORY_GROUP_ENABLED( 714 TRACE_EVENT_CATEGORY_GROUP_ENABLED(
707 TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler.frames"), 715 TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler.frames"),
708 &frame_tracing_enabled); 716 &frame_tracing_enabled);
709 if (frame_tracing_enabled) { 717 if (frame_tracing_enabled) {
710 state->BeginDictionary("frame_source_"); 718 state->BeginDictionary("frame_source_");
711 frame_source_->AsValueInto(state); 719 frame_source_->AsValueInto(state);
712 state->EndDictionary(); 720 state->EndDictionary();
713 } 721 }
714 722
715 state->BeginDictionary("scheduler_state"); 723 state->BeginDictionary("scheduler_state");
716 state->SetDouble("estimated_parent_draw_time_ms", 724 state->SetDouble("estimated_parent_draw_time_ms",
717 estimated_parent_draw_time_.InMillisecondsF()); 725 estimated_parent_draw_time_.InMillisecondsF());
718 state->SetBoolean("last_set_needs_begin_frame_", 726 state->SetBoolean("last_set_needs_begin_frame_",
719 frame_source_->NeedsBeginFrames()); 727 frame_source_->NeedsBeginFrames());
720 state->SetInteger("begin_retro_frame_args", 728 state->SetInteger("begin_retro_frame_args",
721 static_cast<int>(begin_retro_frame_args_.size())); 729 static_cast<int>(begin_retro_frame_args_.size()));
722 state->SetBoolean("begin_retro_frame_task", 730 state->SetBoolean("begin_retro_frame_task",
723 !begin_retro_frame_task_.IsCancelled()); 731 !begin_retro_frame_task_.IsCancelled());
724 state->SetBoolean("begin_impl_frame_deadline_task", 732 state->SetBoolean("begin_impl_frame_deadline_task",
725 !begin_impl_frame_deadline_task_.IsCancelled()); 733 !begin_impl_frame_deadline_task_.IsCancelled());
726 state->SetString("inside_action", 734 state->SetString("inside_action",
727 SchedulerStateMachine::ActionToString(inside_action_)); 735 SchedulerStateMachine::ActionToString(inside_action_));
736
728 state->BeginDictionary("begin_impl_frame_args"); 737 state->BeginDictionary("begin_impl_frame_args");
729 begin_impl_frame_tracker_.AsValueInto(Now(), state); 738 begin_impl_frame_tracker_.AsValueInto(now, state);
730 state->EndDictionary(); 739 state->EndDictionary();
740
741 state->SetString("begin_impl_frame_deadline_mode_",
742 SchedulerStateMachine::BeginImplFrameDeadlineModeToString(
743 begin_impl_frame_deadline_mode_));
731 state->EndDictionary(); 744 state->EndDictionary();
732 745
733 state->BeginDictionary("compositor_timing_history"); 746 state->BeginDictionary("compositor_timing_history");
734 compositor_timing_history_->AsValueInto(state); 747 compositor_timing_history_->AsValueInto(state);
735 state->EndDictionary(); 748 state->EndDictionary();
736 } 749 }
737 750
738 void Scheduler::UpdateCompositorTimingHistoryRecordingEnabled() { 751 void Scheduler::UpdateCompositorTimingHistoryRecordingEnabled() {
739 compositor_timing_history_->SetRecordingEnabled( 752 compositor_timing_history_->SetRecordingEnabled(
740 state_machine_.HasInitializedOutputSurface() && state_machine_.visible()); 753 state_machine_.HasInitializedOutputSurface() && state_machine_.visible());
741 } 754 }
742 755
756 bool Scheduler::ShouldRecoverMainLatency() const {
757 if (!state_machine_.MainThreadIsInHighLatencyMode())
758 return false;
759
760 if (state_machine_.impl_latency_takes_priority())
761 return false;
762
763 return CanCommitAndActivateBeforeDeadline();
764 }
765
766 bool Scheduler::ShouldRecoverImplLatency() const {
767 if (!state_machine_.SwapThrottled())
768 return false;
769
770 BeginFrameArgs args =
771 begin_impl_frame_tracker_.DangerousMethodCurrentOrLast();
mithro-old 2015/07/06 11:58:42 This seems wrong? Why does this need the *last* Be
brianderson 2015/07/07 02:04:49 Yeah, I should have just called Current(). Latest
772
773 // The deadline may be in the past if our draw time is too long.
774 bool frame_time_is_before_deadline = args.frame_time < args.deadline;
775
776 SchedulerStateMachine::BeginImplFrameDeadlineMode
777 next_begin_impl_frame_deadline_mode =
778 state_machine_.CurrentBeginImplFrameDeadlineMode();
779 switch (next_begin_impl_frame_deadline_mode) {
780 case SchedulerStateMachine::BEGIN_IMPL_FRAME_DEADLINE_MODE_NONE:
781 return false;
782 case SchedulerStateMachine::BEGIN_IMPL_FRAME_DEADLINE_MODE_IMMEDIATE:
783 return frame_time_is_before_deadline;
784 case SchedulerStateMachine::BEGIN_IMPL_FRAME_DEADLINE_MODE_REGULAR:
785 return frame_time_is_before_deadline;
786 case SchedulerStateMachine::BEGIN_IMPL_FRAME_DEADLINE_MODE_LATE:
787 return CanCommitAndActivateBeforeDeadline();
788 case SchedulerStateMachine::
789 BEGIN_IMPL_FRAME_DEADLINE_MODE_BLOCKED_ON_READY_TO_DRAW:
790 return false;
791 }
792 NOTREACHED();
793 return false;
794 }
795
743 bool Scheduler::CanCommitAndActivateBeforeDeadline() const { 796 bool Scheduler::CanCommitAndActivateBeforeDeadline() const {
744 BeginFrameArgs args = 797 BeginFrameArgs args =
745 begin_impl_frame_tracker_.DangerousMethodCurrentOrLast(); 798 begin_impl_frame_tracker_.DangerousMethodCurrentOrLast();
746 799
747 // Check if the main thread computation and commit can be finished before the 800 // Check if the main thread computation and commit can be finished before the
748 // impl thread's deadline. 801 // impl thread's deadline.
749 base::TimeTicks estimated_draw_time = 802 base::TimeTicks estimated_draw_time =
750 args.frame_time + 803 args.frame_time +
751 compositor_timing_history_->BeginMainFrameToCommitDurationEstimate() + 804 compositor_timing_history_->BeginMainFrameToCommitDurationEstimate() +
752 compositor_timing_history_->CommitToReadyToActivateDurationEstimate() + 805 compositor_timing_history_->CommitToReadyToActivateDurationEstimate() +
753 compositor_timing_history_->ActivateDurationEstimate(); 806 compositor_timing_history_->ActivateDurationEstimate();
754 807
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; 808 return estimated_draw_time < args.deadline;
762 } 809 }
763 810
764 bool Scheduler::IsBeginMainFrameSentOrStarted() const { 811 bool Scheduler::IsBeginMainFrameSentOrStarted() const {
765 return (state_machine_.commit_state() == 812 return (state_machine_.commit_state() ==
766 SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT || 813 SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT ||
767 state_machine_.commit_state() == 814 state_machine_.commit_state() ==
768 SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_STARTED); 815 SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_STARTED);
769 } 816 }
770 817
771 } // namespace cc 818 } // namespace cc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698