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

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

Issue 1425973003: cc: Don't attempt main thread synchronization if it is slow. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: rebase; change names; use enum class Created 5 years, 1 month 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 193 matching lines...) Expand 10 before | Expand all | Expand 10 after
204 } 204 }
205 } 205 }
206 206
207 void Scheduler::DidSwapBuffersComplete() { 207 void Scheduler::DidSwapBuffersComplete() {
208 DCHECK_GT(state_machine_.pending_swaps(), 0) << AsValue()->ToString(); 208 DCHECK_GT(state_machine_.pending_swaps(), 0) << AsValue()->ToString();
209 compositor_timing_history_->DidSwapBuffersComplete(); 209 compositor_timing_history_->DidSwapBuffersComplete();
210 state_machine_.DidSwapBuffersComplete(); 210 state_machine_.DidSwapBuffersComplete();
211 ProcessScheduledActions(); 211 ProcessScheduledActions();
212 } 212 }
213 213
214 void Scheduler::SetImplLatencyTakesPriority(bool impl_latency_takes_priority) { 214 void Scheduler::SetTreePrioritiesAndScrollState(
215 state_machine_.SetImplLatencyTakesPriority(impl_latency_takes_priority); 215 TreePriority tree_priority,
216 ScrollHandlerState scroll_handler_state) {
217 state_machine_.SetTreePrioritiesAndScrollState(tree_priority,
218 scroll_handler_state);
216 ProcessScheduledActions(); 219 ProcessScheduledActions();
217 } 220 }
218 221
219 void Scheduler::NotifyReadyToCommit() { 222 void Scheduler::NotifyReadyToCommit() {
220 TRACE_EVENT0("cc", "Scheduler::NotifyReadyToCommit"); 223 TRACE_EVENT0("cc", "Scheduler::NotifyReadyToCommit");
221 state_machine_.NotifyReadyToCommit(); 224 state_machine_.NotifyReadyToCommit();
222 ProcessScheduledActions(); 225 ProcessScheduledActions();
223 } 226 }
224 227
225 void Scheduler::DidCommit() { 228 void Scheduler::DidCommit() {
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
303 TRACE_EVENT1("cc,benchmark", "Scheduler::BeginFrame", "args", args.AsValue()); 306 TRACE_EVENT1("cc,benchmark", "Scheduler::BeginFrame", "args", args.AsValue());
304 307
305 // Trace this begin frame time through the Chrome stack 308 // Trace this begin frame time through the Chrome stack
306 TRACE_EVENT_FLOW_BEGIN0( 309 TRACE_EVENT_FLOW_BEGIN0(
307 TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler.frames"), "BeginFrameArgs", 310 TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler.frames"), "BeginFrameArgs",
308 args.frame_time.ToInternalValue()); 311 args.frame_time.ToInternalValue());
309 312
310 // TODO(brianderson): Adjust deadline in the DisplayScheduler. 313 // TODO(brianderson): Adjust deadline in the DisplayScheduler.
311 BeginFrameArgs adjusted_args(args); 314 BeginFrameArgs adjusted_args(args);
312 adjusted_args.deadline -= EstimatedParentDrawTime(); 315 adjusted_args.deadline -= EstimatedParentDrawTime();
313 adjusted_args.on_critical_path = !ImplLatencyTakesPriority();
314 316
315 // Deliver BeginFrames to children. 317 // Deliver BeginFrames to children.
316 // TODO(brianderson): Move this responsibility to the DisplayScheduler. 318 // TODO(brianderson): Move this responsibility to the DisplayScheduler.
317 if (state_machine_.children_need_begin_frames()) 319 if (state_machine_.children_need_begin_frames())
318 client_->SendBeginFramesToChildren(adjusted_args); 320 client_->SendBeginFramesToChildren(adjusted_args);
319 321
320 if (settings_.using_synchronous_renderer_compositor) { 322 if (settings_.using_synchronous_renderer_compositor) {
321 BeginImplFrameSynchronous(adjusted_args); 323 BeginImplFrameSynchronous(adjusted_args);
322 return true; 324 return true;
323 } 325 }
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after
460 TRACE_EVENT2("cc,benchmark", "Scheduler::BeginImplFrame", "args", 462 TRACE_EVENT2("cc,benchmark", "Scheduler::BeginImplFrame", "args",
461 args.AsValue(), "main_thread_missed_last_deadline", 463 args.AsValue(), "main_thread_missed_last_deadline",
462 main_thread_is_in_high_latency_mode); 464 main_thread_is_in_high_latency_mode);
463 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler"), 465 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler"),
464 "MainThreadLatency", main_thread_is_in_high_latency_mode); 466 "MainThreadLatency", main_thread_is_in_high_latency_mode);
465 467
466 BeginFrameArgs adjusted_args = args; 468 BeginFrameArgs adjusted_args = args;
467 adjusted_args.deadline -= compositor_timing_history_->DrawDurationEstimate(); 469 adjusted_args.deadline -= compositor_timing_history_->DrawDurationEstimate();
468 adjusted_args.deadline -= kDeadlineFudgeFactor; 470 adjusted_args.deadline -= kDeadlineFudgeFactor;
469 471
470 if (ShouldRecoverMainLatency(adjusted_args)) { 472 base::TimeDelta bmf_start_to_activate =
473 compositor_timing_history_
474 ->BeginMainFrameStartToCommitDurationEstimate() +
475 compositor_timing_history_->CommitToReadyToActivateDurationEstimate() +
476 compositor_timing_history_->ActivateDurationEstimate();
477
478 base::TimeDelta bmf_to_activate_estimate_if_critical =
479 bmf_start_to_activate +
480 compositor_timing_history_->BeginMainFrameQueueDurationCriticalEstimate();
481
482 bool can_activate_before_deadline_if_critical =
483 CanBeginMainFrameAndActivateBeforeDeadline(
484 adjusted_args, bmf_to_activate_estimate_if_critical);
485 state_machine_.SetCriticalBeginMainFrameToActivateIsFast(
486 can_activate_before_deadline_if_critical);
487
488 // Update the BeginMainFrame args now that we know whether the main
489 // thread will be on the critical path or not.
490 begin_main_frame_args_ = adjusted_args;
491 begin_main_frame_args_.on_critical_path = !ImplLatencyTakesPriority();
492
493 bool can_activate_before_deadline = can_activate_before_deadline_if_critical;
494 if (!begin_main_frame_args_.on_critical_path) {
495 base::TimeDelta bmf_to_activate_estimate =
496 bmf_start_to_activate +
497 compositor_timing_history_
498 ->BeginMainFrameQueueDurationNotCriticalEstimate();
499
500 can_activate_before_deadline = CanBeginMainFrameAndActivateBeforeDeadline(
501 adjusted_args, bmf_to_activate_estimate);
502 }
503
504 if (ShouldRecoverMainLatency(adjusted_args, can_activate_before_deadline)) {
471 TRACE_EVENT_INSTANT0("cc", "SkipBeginMainFrameToReduceLatency", 505 TRACE_EVENT_INSTANT0("cc", "SkipBeginMainFrameToReduceLatency",
472 TRACE_EVENT_SCOPE_THREAD); 506 TRACE_EVENT_SCOPE_THREAD);
473 state_machine_.SetSkipNextBeginMainFrameToReduceLatency(); 507 state_machine_.SetSkipNextBeginMainFrameToReduceLatency();
474 } else if (ShouldRecoverImplLatency(adjusted_args)) { 508 } else if (ShouldRecoverImplLatency(adjusted_args,
509 can_activate_before_deadline)) {
475 TRACE_EVENT_INSTANT0("cc", "SkipBeginImplFrameToReduceLatency", 510 TRACE_EVENT_INSTANT0("cc", "SkipBeginImplFrameToReduceLatency",
476 TRACE_EVENT_SCOPE_THREAD); 511 TRACE_EVENT_SCOPE_THREAD);
477 frame_source_->DidFinishFrame(begin_retro_frame_args_.size()); 512 frame_source_->DidFinishFrame(begin_retro_frame_args_.size());
478 return; 513 return;
479 } 514 }
480 515
481 BeginImplFrame(adjusted_args); 516 BeginImplFrame(adjusted_args);
482 517
483 // The deadline will be scheduled in ProcessScheduledActions. 518 // The deadline will be scheduled in ProcessScheduledActions.
484 state_machine_.OnBeginImplFrameDeadlinePending(); 519 state_machine_.OnBeginImplFrameDeadlinePending();
485 ProcessScheduledActions(); 520 ProcessScheduledActions();
486 } 521 }
487 522
488 void Scheduler::BeginImplFrameSynchronous(const BeginFrameArgs& args) { 523 void Scheduler::BeginImplFrameSynchronous(const BeginFrameArgs& args) {
489 TRACE_EVENT1("cc,benchmark", "Scheduler::BeginImplFrame", "args", 524 TRACE_EVENT1("cc,benchmark", "Scheduler::BeginImplFrame", "args",
490 args.AsValue()); 525 args.AsValue());
526
527 // The main thread currently can't commit before we draw with the
528 // synchronous compositor, so never consider the BeginMainFrame fast.
529 state_machine_.SetCriticalBeginMainFrameToActivateIsFast(false);
530 begin_main_frame_args_ = args;
531 begin_main_frame_args_.on_critical_path = !ImplLatencyTakesPriority();
532
491 BeginImplFrame(args); 533 BeginImplFrame(args);
492 FinishImplFrame(); 534 FinishImplFrame();
493 } 535 }
494 536
495 void Scheduler::FinishImplFrame() { 537 void Scheduler::FinishImplFrame() {
496 state_machine_.OnBeginImplFrameIdle(); 538 state_machine_.OnBeginImplFrameIdle();
497 ProcessScheduledActions(); 539 ProcessScheduledActions();
498 540
499 client_->DidFinishImplFrame(); 541 client_->DidFinishImplFrame();
500 frame_source_->DidFinishFrame(begin_retro_frame_args_.size()); 542 frame_source_->DidFinishFrame(begin_retro_frame_args_.size());
501 begin_impl_frame_tracker_.Finish(); 543 begin_impl_frame_tracker_.Finish();
502 } 544 }
503 545
504 // BeginImplFrame starts a compositor frame that will wait up until a deadline 546 // BeginImplFrame starts a compositor frame that will wait up until a deadline
505 // for a BeginMainFrame+activation to complete before it times out and draws 547 // for a BeginMainFrame+activation to complete before it times out and draws
506 // any asynchronous animation and scroll/pinch updates. 548 // any asynchronous animation and scroll/pinch updates.
507 void Scheduler::BeginImplFrame(const BeginFrameArgs& args) { 549 void Scheduler::BeginImplFrame(const BeginFrameArgs& args) {
508 DCHECK_EQ(state_machine_.begin_impl_frame_state(), 550 DCHECK_EQ(state_machine_.begin_impl_frame_state(),
509 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE); 551 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE);
510 DCHECK(!BeginImplFrameDeadlinePending()); 552 DCHECK(!BeginImplFrameDeadlinePending());
511 DCHECK(state_machine_.HasInitializedOutputSurface()); 553 DCHECK(state_machine_.HasInitializedOutputSurface());
512 554
513 begin_impl_frame_tracker_.Start(args); 555 begin_impl_frame_tracker_.Start(args);
514 begin_main_frame_args_ = args;
515 state_machine_.OnBeginImplFrame(); 556 state_machine_.OnBeginImplFrame();
516 devtools_instrumentation::DidBeginFrame(layer_tree_host_id_); 557 devtools_instrumentation::DidBeginFrame(layer_tree_host_id_);
517 client_->WillBeginImplFrame(begin_impl_frame_tracker_.Current()); 558 client_->WillBeginImplFrame(begin_impl_frame_tracker_.Current());
518 559
519 ProcessScheduledActions(); 560 ProcessScheduledActions();
520 } 561 }
521 562
522 void Scheduler::ScheduleBeginImplFrameDeadline() { 563 void Scheduler::ScheduleBeginImplFrameDeadline() {
523 // The synchronous compositor does not post a deadline task. 564 // The synchronous compositor does not post a deadline task.
524 DCHECK(!settings_.using_synchronous_renderer_compositor); 565 DCHECK(!settings_.using_synchronous_renderer_compositor);
(...skipping 251 matching lines...) Expand 10 before | Expand all | Expand 10 after
776 state->BeginDictionary("compositor_timing_history"); 817 state->BeginDictionary("compositor_timing_history");
777 compositor_timing_history_->AsValueInto(state); 818 compositor_timing_history_->AsValueInto(state);
778 state->EndDictionary(); 819 state->EndDictionary();
779 } 820 }
780 821
781 void Scheduler::UpdateCompositorTimingHistoryRecordingEnabled() { 822 void Scheduler::UpdateCompositorTimingHistoryRecordingEnabled() {
782 compositor_timing_history_->SetRecordingEnabled( 823 compositor_timing_history_->SetRecordingEnabled(
783 state_machine_.HasInitializedOutputSurface() && state_machine_.visible()); 824 state_machine_.HasInitializedOutputSurface() && state_machine_.visible());
784 } 825 }
785 826
786 bool Scheduler::ShouldRecoverMainLatency(const BeginFrameArgs& args) const { 827 bool Scheduler::ShouldRecoverMainLatency(
828 const BeginFrameArgs& args,
829 bool can_activate_before_deadline) const {
787 DCHECK(!settings_.using_synchronous_renderer_compositor); 830 DCHECK(!settings_.using_synchronous_renderer_compositor);
788 831
789 if (!state_machine_.main_thread_missed_last_deadline()) 832 if (!state_machine_.main_thread_missed_last_deadline())
790 return false; 833 return false;
791 834
792 // When prioritizing impl thread latency, we currently put the 835 // When prioritizing impl thread latency, we currently put the
793 // main thread in a high latency mode. Don't try to fight it. 836 // main thread in a high latency mode. Don't try to fight it.
794 if (state_machine_.impl_latency_takes_priority()) 837 if (state_machine_.ImplLatencyTakesPriority())
795 return false; 838 return false;
796 839
797 return CanCommitAndActivateBeforeDeadline(args); 840 return can_activate_before_deadline;
798 } 841 }
799 842
800 bool Scheduler::ShouldRecoverImplLatency(const BeginFrameArgs& args) const { 843 bool Scheduler::ShouldRecoverImplLatency(
844 const BeginFrameArgs& args,
845 bool can_activate_before_deadline) const {
801 DCHECK(!settings_.using_synchronous_renderer_compositor); 846 DCHECK(!settings_.using_synchronous_renderer_compositor);
802 847
803 // Disable impl thread latency recovery when using the unthrottled 848 // Disable impl thread latency recovery when using the unthrottled
804 // begin frame source since we will always get a BeginFrame before 849 // begin frame source since we will always get a BeginFrame before
805 // the swap ack and our heuristics below will not work. 850 // the swap ack and our heuristics below will not work.
806 if (!throttle_frame_production_) 851 if (!throttle_frame_production_)
807 return false; 852 return false;
808 853
809 // If we are swap throttled at the BeginFrame, that means the impl thread is 854 // If we are swap throttled at the BeginFrame, that means the impl thread is
810 // very likely in a high latency mode. 855 // very likely in a high latency mode.
811 bool impl_thread_is_likely_high_latency = state_machine_.SwapThrottled(); 856 bool impl_thread_is_likely_high_latency = state_machine_.SwapThrottled();
812 if (!impl_thread_is_likely_high_latency) 857 if (!impl_thread_is_likely_high_latency)
813 return false; 858 return false;
814 859
815 // The deadline may be in the past if our draw time is too long. 860 // The deadline may be in the past if our draw time is too long.
816 bool can_draw_before_deadline = args.frame_time < args.deadline; 861 bool can_draw_before_deadline = args.frame_time < args.deadline;
817 862
818 // When prioritizing impl thread latency, the deadline doesn't wait 863 // When prioritizing impl thread latency, the deadline doesn't wait
819 // for the main thread. 864 // for the main thread.
820 if (state_machine_.impl_latency_takes_priority()) 865 if (state_machine_.ImplLatencyTakesPriority())
821 return can_draw_before_deadline; 866 return can_draw_before_deadline;
822 867
823 // If we only have impl-side updates, the deadline doesn't wait for 868 // If we only have impl-side updates, the deadline doesn't wait for
824 // the main thread. 869 // the main thread.
825 if (state_machine_.OnlyImplSideUpdatesExpected()) 870 if (state_machine_.OnlyImplSideUpdatesExpected())
826 return can_draw_before_deadline; 871 return can_draw_before_deadline;
827 872
828 // If we get here, we know the main thread is in a low-latency mode relative 873 // If we get here, we know the main thread is in a low-latency mode relative
829 // to the impl thread. In this case, only try to also recover impl thread 874 // to the impl thread. In this case, only try to also recover impl thread
830 // latency if both the main and impl threads can run serially before the 875 // latency if both the main and impl threads can run serially before the
831 // deadline. 876 // deadline.
832 return CanCommitAndActivateBeforeDeadline(args); 877 return can_activate_before_deadline;
833 } 878 }
834 879
835 bool Scheduler::CanCommitAndActivateBeforeDeadline( 880 bool Scheduler::CanBeginMainFrameAndActivateBeforeDeadline(
836 const BeginFrameArgs& args) const { 881 const BeginFrameArgs& args,
882 base::TimeDelta bmf_to_activate_estimate) const {
837 // Check if the main thread computation and commit can be finished before the 883 // Check if the main thread computation and commit can be finished before the
838 // impl thread's deadline. 884 // impl thread's deadline.
839 base::TimeTicks estimated_draw_time = 885 base::TimeTicks estimated_draw_time =
840 args.frame_time + 886 args.frame_time + bmf_to_activate_estimate;
841 compositor_timing_history_->BeginMainFrameToCommitDurationEstimate() +
842 compositor_timing_history_->CommitToReadyToActivateDurationEstimate() +
843 compositor_timing_history_->ActivateDurationEstimate();
844 887
845 return estimated_draw_time < args.deadline; 888 return estimated_draw_time < args.deadline;
846 } 889 }
847 890
848 bool Scheduler::IsBeginMainFrameSentOrStarted() const { 891 bool Scheduler::IsBeginMainFrameSentOrStarted() const {
849 return (state_machine_.begin_main_frame_state() == 892 return (state_machine_.begin_main_frame_state() ==
850 SchedulerStateMachine::BEGIN_MAIN_FRAME_STATE_SENT || 893 SchedulerStateMachine::BEGIN_MAIN_FRAME_STATE_SENT ||
851 state_machine_.begin_main_frame_state() == 894 state_machine_.begin_main_frame_state() ==
852 SchedulerStateMachine::BEGIN_MAIN_FRAME_STATE_STARTED); 895 SchedulerStateMachine::BEGIN_MAIN_FRAME_STATE_STARTED);
853 } 896 }
854 897
855 } // namespace cc 898 } // 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