| 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 "components/scheduler/renderer/renderer_scheduler_impl.h" | 5 #include "components/scheduler/renderer/renderer_scheduler_impl.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/debug/stack_trace.h" | 8 #include "base/debug/stack_trace.h" |
| 9 #include "base/logging.h" | 9 #include "base/logging.h" |
| 10 #include "base/memory/ptr_util.h" | 10 #include "base/memory/ptr_util.h" |
| 11 #include "base/metrics/histogram_macros.h" |
| 11 #include "base/trace_event/trace_event.h" | 12 #include "base/trace_event/trace_event.h" |
| 12 #include "base/trace_event/trace_event_argument.h" | 13 #include "base/trace_event/trace_event_argument.h" |
| 13 #include "cc/output/begin_frame_args.h" | 14 #include "cc/output/begin_frame_args.h" |
| 14 #include "components/scheduler/base/task_queue_impl.h" | 15 #include "components/scheduler/base/task_queue_impl.h" |
| 15 #include "components/scheduler/base/task_queue_selector.h" | 16 #include "components/scheduler/base/task_queue_selector.h" |
| 16 #include "components/scheduler/base/virtual_time_domain.h" | 17 #include "components/scheduler/base/virtual_time_domain.h" |
| 17 #include "components/scheduler/child/scheduler_tqm_delegate.h" | 18 #include "components/scheduler/child/scheduler_tqm_delegate.h" |
| 18 #include "components/scheduler/renderer/web_view_scheduler_impl.h" | 19 #include "components/scheduler/renderer/web_view_scheduler_impl.h" |
| 19 #include "components/scheduler/renderer/webthread_impl_for_renderer_scheduler.h" | 20 #include "components/scheduler/renderer/webthread_impl_for_renderer_scheduler.h" |
| 20 | 21 |
| 21 namespace scheduler { | 22 namespace scheduler { |
| 22 namespace { | 23 namespace { |
| 23 // The run time of loading tasks is strongly bimodal. The vast majority are | 24 // The run time of loading tasks is strongly bimodal. The vast majority are |
| 24 // very cheap, but there are usually a handful of very expensive tasks (e.g ~1 | 25 // very cheap, but there are usually a handful of very expensive tasks (e.g ~1 |
| 25 // second on a mobile device) so we take a very pesimistic view when estimating | 26 // second on a mobile device) so we take a very pessimistic view when estimating |
| 26 // the cost of loading tasks. | 27 // the cost of loading tasks. |
| 27 const int kLoadingTaskEstimationSampleCount = 1000; | 28 const int kLoadingTaskEstimationSampleCount = 1000; |
| 28 const double kLoadingTaskEstimationPercentile = 99; | 29 const double kLoadingTaskEstimationPercentile = 99; |
| 29 const int kTimerTaskEstimationSampleCount = 1000; | 30 const int kTimerTaskEstimationSampleCount = 1000; |
| 30 const double kTimerTaskEstimationPercentile = 99; | 31 const double kTimerTaskEstimationPercentile = 99; |
| 31 const int kShortIdlePeriodDurationSampleCount = 10; | 32 const int kShortIdlePeriodDurationSampleCount = 10; |
| 32 const double kShortIdlePeriodDurationPercentile = 50; | 33 const double kShortIdlePeriodDurationPercentile = 50; |
| 33 // Amount of idle time left in a frame (as a ratio of the vsync interval) above | 34 // Amount of idle time left in a frame (as a ratio of the vsync interval) above |
| 34 // which main thread compositing can be considered fast. | 35 // which main thread compositing can be considered fast. |
| 35 const double kFastCompositingIdleTimeThreshold = .2; | 36 const double kFastCompositingIdleTimeThreshold = .2; |
| 36 } // namespace | 37 } // namespace |
| 37 | 38 |
| 38 RendererSchedulerImpl::RendererSchedulerImpl( | 39 RendererSchedulerImpl::RendererSchedulerImpl( |
| 39 scoped_refptr<SchedulerTqmDelegate> main_task_runner) | 40 scoped_refptr<SchedulerTqmDelegate> main_task_runner) |
| 40 : helper_(main_task_runner, | 41 : helper_(main_task_runner, |
| 41 "renderer.scheduler", | 42 "renderer.scheduler", |
| 42 TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), | 43 TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), |
| 43 TRACE_DISABLED_BY_DEFAULT("renderer.scheduler.debug")), | 44 TRACE_DISABLED_BY_DEFAULT("renderer.scheduler.debug")), |
| 44 idle_helper_(&helper_, | 45 idle_helper_(&helper_, |
| 45 this, | 46 this, |
| 46 "renderer.scheduler", | 47 "renderer.scheduler", |
| 47 TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), | 48 TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), |
| 48 "RendererSchedulerIdlePeriod", | 49 "RendererSchedulerIdlePeriod", |
| 49 base::TimeDelta()), | 50 base::TimeDelta()), |
| 50 render_widget_scheduler_signals_(this), | 51 render_widget_scheduler_signals_(this), |
| 51 control_task_runner_(helper_.ControlTaskRunner()), | 52 control_task_runner_(helper_.ControlTaskRunner()), |
| 52 compositor_task_runner_( | 53 compositor_task_runner_(helper_.NewTaskQueue( |
| 53 helper_.NewTaskQueue(TaskQueue::Spec("compositor_tq") | 54 TaskQueue::Spec("compositor_tq").SetShouldMonitorQuiescence(true))), |
| 54 .SetShouldMonitorQuiescence(true))), | |
| 55 delayed_update_policy_runner_( | 55 delayed_update_policy_runner_( |
| 56 base::Bind(&RendererSchedulerImpl::UpdatePolicy, | 56 base::Bind(&RendererSchedulerImpl::UpdatePolicy, |
| 57 base::Unretained(this)), | 57 base::Unretained(this)), |
| 58 helper_.ControlTaskRunner()), | 58 helper_.ControlTaskRunner()), |
| 59 main_thread_only_(compositor_task_runner_, | 59 main_thread_only_(this, |
| 60 compositor_task_runner_, |
| 60 helper_.scheduler_tqm_delegate().get()), | 61 helper_.scheduler_tqm_delegate().get()), |
| 61 policy_may_need_update_(&any_thread_lock_), | 62 policy_may_need_update_(&any_thread_lock_), |
| 62 weak_factory_(this) { | 63 weak_factory_(this) { |
| 63 throttling_helper_.reset(new ThrottlingHelper(this, "renderer.scheduler")); | 64 throttling_helper_.reset(new ThrottlingHelper(this, "renderer.scheduler")); |
| 64 update_policy_closure_ = base::Bind(&RendererSchedulerImpl::UpdatePolicy, | 65 update_policy_closure_ = base::Bind(&RendererSchedulerImpl::UpdatePolicy, |
| 65 weak_factory_.GetWeakPtr()); | 66 weak_factory_.GetWeakPtr()); |
| 66 end_renderer_hidden_idle_period_closure_.Reset(base::Bind( | 67 end_renderer_hidden_idle_period_closure_.Reset(base::Bind( |
| 67 &RendererSchedulerImpl::EndIdlePeriod, weak_factory_.GetWeakPtr())); | 68 &RendererSchedulerImpl::EndIdlePeriod, weak_factory_.GetWeakPtr())); |
| 68 | 69 |
| 69 suspend_timers_when_backgrounded_closure_.Reset( | 70 suspend_timers_when_backgrounded_closure_.Reset( |
| 70 base::Bind(&RendererSchedulerImpl::SuspendTimerQueueWhenBackgrounded, | 71 base::Bind(&RendererSchedulerImpl::SuspendTimerQueueWhenBackgrounded, |
| 71 weak_factory_.GetWeakPtr())); | 72 weak_factory_.GetWeakPtr())); |
| 72 | 73 |
| 73 default_loading_task_runner_ = NewLoadingTaskRunner("default_loading_tq"); | 74 default_loading_task_runner_ = NewLoadingTaskRunner("default_loading_tq"); |
| 74 default_timer_task_runner_ = NewTimerTaskRunner("default_timer_tq"); | 75 default_timer_task_runner_ = NewTimerTaskRunner("default_timer_tq"); |
| 75 | 76 |
| 76 TRACE_EVENT_OBJECT_CREATED_WITH_ID( | 77 TRACE_EVENT_OBJECT_CREATED_WITH_ID( |
| 77 TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), "RendererScheduler", | 78 TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), "RendererScheduler", |
| 78 this); | 79 this); |
| 79 | 80 |
| 80 helper_.SetObserver(this); | 81 helper_.SetObserver(this); |
| 82 helper_.SetTaskTimeTracker(this); |
| 81 } | 83 } |
| 82 | 84 |
| 83 RendererSchedulerImpl::~RendererSchedulerImpl() { | 85 RendererSchedulerImpl::~RendererSchedulerImpl() { |
| 84 TRACE_EVENT_OBJECT_DELETED_WITH_ID( | 86 TRACE_EVENT_OBJECT_DELETED_WITH_ID( |
| 85 TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), "RendererScheduler", | 87 TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), "RendererScheduler", |
| 86 this); | 88 this); |
| 87 | 89 |
| 88 for (const scoped_refptr<TaskQueue>& loading_queue : loading_task_runners_) { | 90 for (const scoped_refptr<TaskQueue>& loading_queue : loading_task_runners_) { |
| 89 loading_queue->RemoveTaskObserver( | 91 loading_queue->RemoveTaskObserver( |
| 90 &MainThreadOnly().loading_task_cost_estimator); | 92 &MainThreadOnly().loading_task_cost_estimator); |
| 91 } | 93 } |
| 92 for (const scoped_refptr<TaskQueue>& timer_queue : timer_task_runners_) { | 94 for (const scoped_refptr<TaskQueue>& timer_queue : timer_task_runners_) { |
| 93 timer_queue->RemoveTaskObserver( | 95 timer_queue->RemoveTaskObserver( |
| 94 &MainThreadOnly().timer_task_cost_estimator); | 96 &MainThreadOnly().timer_task_cost_estimator); |
| 95 } | 97 } |
| 96 | 98 |
| 97 // Ensure the renderer scheduler was shut down explicitly, because otherwise | 99 // Ensure the renderer scheduler was shut down explicitly, because otherwise |
| 98 // we could end up having stale pointers to the Blink heap which has been | 100 // we could end up having stale pointers to the Blink heap which has been |
| 99 // terminated by this point. | 101 // terminated by this point. |
| 100 DCHECK(MainThreadOnly().was_shutdown); | 102 DCHECK(MainThreadOnly().was_shutdown); |
| 101 } | 103 } |
| 102 | 104 |
| 103 RendererSchedulerImpl::MainThreadOnly::MainThreadOnly( | 105 RendererSchedulerImpl::MainThreadOnly::MainThreadOnly( |
| 106 RendererSchedulerImpl* renderer_scheduler_impl, |
| 104 const scoped_refptr<TaskQueue>& compositor_task_runner, | 107 const scoped_refptr<TaskQueue>& compositor_task_runner, |
| 105 base::TickClock* time_source) | 108 base::TickClock* time_source) |
| 106 : loading_task_cost_estimator(time_source, | 109 : loading_task_cost_estimator(time_source, |
| 107 kLoadingTaskEstimationSampleCount, | 110 kLoadingTaskEstimationSampleCount, |
| 108 kLoadingTaskEstimationPercentile), | 111 kLoadingTaskEstimationPercentile), |
| 109 timer_task_cost_estimator(time_source, | 112 timer_task_cost_estimator(time_source, |
| 110 kTimerTaskEstimationSampleCount, | 113 kTimerTaskEstimationSampleCount, |
| 111 kTimerTaskEstimationPercentile), | 114 kTimerTaskEstimationPercentile), |
| 115 queueing_time_estimator(renderer_scheduler_impl, |
| 116 base::TimeDelta::FromSeconds(1)), |
| 112 idle_time_estimator(compositor_task_runner, | 117 idle_time_estimator(compositor_task_runner, |
| 113 time_source, | 118 time_source, |
| 114 kShortIdlePeriodDurationSampleCount, | 119 kShortIdlePeriodDurationSampleCount, |
| 115 kShortIdlePeriodDurationPercentile), | 120 kShortIdlePeriodDurationPercentile), |
| 116 current_use_case(UseCase::NONE), | 121 current_use_case(UseCase::NONE), |
| 117 timer_queue_suspend_count(0), | 122 timer_queue_suspend_count(0), |
| 118 navigation_task_expected_count(0), | 123 navigation_task_expected_count(0), |
| 119 expensive_task_policy(ExpensiveTaskPolicy::RUN), | 124 expensive_task_policy(ExpensiveTaskPolicy::RUN), |
| 120 renderer_hidden(false), | 125 renderer_hidden(false), |
| 121 renderer_backgrounded(false), | 126 renderer_backgrounded(false), |
| (...skipping 1254 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1376 true; | 1381 true; |
| 1377 BroadcastConsoleWarning( | 1382 BroadcastConsoleWarning( |
| 1378 "Blink deferred a task in order to make scrolling smoother. " | 1383 "Blink deferred a task in order to make scrolling smoother. " |
| 1379 "Your timer and network tasks should take less than 50ms to run " | 1384 "Your timer and network tasks should take less than 50ms to run " |
| 1380 "to avoid this. Please see " | 1385 "to avoid this. Please see " |
| 1381 "https://developers.google.com/web/tools/chrome-devtools/profile/evaluat
e-performance/rail" | 1386 "https://developers.google.com/web/tools/chrome-devtools/profile/evaluat
e-performance/rail" |
| 1382 " and https://crbug.com/574343#c40 for more information."); | 1387 " and https://crbug.com/574343#c40 for more information."); |
| 1383 } | 1388 } |
| 1384 } | 1389 } |
| 1385 | 1390 |
| 1391 void RendererSchedulerImpl::ReportTaskTime(base::TimeTicks start_time, |
| 1392 base::TimeTicks end_time) { |
| 1393 MainThreadOnly().queueing_time_estimator.OnToplevelTaskCompleted(start_time, |
| 1394 end_time); |
| 1395 } |
| 1396 |
| 1397 void RendererSchedulerImpl::OnQueueingTimeForWindowEstimated( |
| 1398 base::TimeDelta queueing_time) { |
| 1399 UMA_HISTOGRAM_TIMES("RendererScheduler.ExpectedTaskQueueingDuration", |
| 1400 queueing_time); |
| 1401 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), |
| 1402 "estimated_queueing_time_for_window", |
| 1403 queueing_time.InMillisecondsF()); |
| 1404 } |
| 1405 |
| 1386 // static | 1406 // static |
| 1387 const char* RendererSchedulerImpl::UseCaseToString(UseCase use_case) { | 1407 const char* RendererSchedulerImpl::UseCaseToString(UseCase use_case) { |
| 1388 switch (use_case) { | 1408 switch (use_case) { |
| 1389 case UseCase::NONE: | 1409 case UseCase::NONE: |
| 1390 return "none"; | 1410 return "none"; |
| 1391 case UseCase::COMPOSITOR_GESTURE: | 1411 case UseCase::COMPOSITOR_GESTURE: |
| 1392 return "compositor_gesture"; | 1412 return "compositor_gesture"; |
| 1393 case UseCase::MAIN_THREAD_CUSTOM_INPUT_HANDLING: | 1413 case UseCase::MAIN_THREAD_CUSTOM_INPUT_HANDLING: |
| 1394 return "main_thread_custom_input_handling"; | 1414 return "main_thread_custom_input_handling"; |
| 1395 case UseCase::SYNCHRONIZED_GESTURE: | 1415 case UseCase::SYNCHRONIZED_GESTURE: |
| (...skipping 21 matching lines...) Expand all Loading... |
| 1417 return "idle"; | 1437 return "idle"; |
| 1418 case v8::PERFORMANCE_LOAD: | 1438 case v8::PERFORMANCE_LOAD: |
| 1419 return "load"; | 1439 return "load"; |
| 1420 default: | 1440 default: |
| 1421 NOTREACHED(); | 1441 NOTREACHED(); |
| 1422 return nullptr; | 1442 return nullptr; |
| 1423 } | 1443 } |
| 1424 } | 1444 } |
| 1425 | 1445 |
| 1426 } // namespace scheduler | 1446 } // namespace scheduler |
| OLD | NEW |