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 "platform/scheduler/renderer/renderer_scheduler_impl.h" | 5 #include "platform/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" |
(...skipping 24 matching lines...) Expand all Loading... | |
35 const int kShortIdlePeriodDurationSampleCount = 10; | 35 const int kShortIdlePeriodDurationSampleCount = 10; |
36 const double kShortIdlePeriodDurationPercentile = 50; | 36 const double kShortIdlePeriodDurationPercentile = 50; |
37 // Amount of idle time left in a frame (as a ratio of the vsync interval) above | 37 // Amount of idle time left in a frame (as a ratio of the vsync interval) above |
38 // which main thread compositing can be considered fast. | 38 // which main thread compositing can be considered fast. |
39 const double kFastCompositingIdleTimeThreshold = .2; | 39 const double kFastCompositingIdleTimeThreshold = .2; |
40 constexpr base::TimeDelta kThreadLoadTrackerReportingInterval = | 40 constexpr base::TimeDelta kThreadLoadTrackerReportingInterval = |
41 base::TimeDelta::FromMinutes(1); | 41 base::TimeDelta::FromMinutes(1); |
42 constexpr base::TimeDelta kThreadLoadTrackerWaitingPeriodBeforeReporting = | 42 constexpr base::TimeDelta kThreadLoadTrackerWaitingPeriodBeforeReporting = |
43 base::TimeDelta::FromMinutes(2); | 43 base::TimeDelta::FromMinutes(2); |
44 | 44 |
45 // Maximum task queueing time before the main thread is considered unresponsive. | |
46 constexpr base::TimeDelta kMainThreadUnresponsiveQueueingTime = | |
47 base::TimeDelta::FromMilliseconds(200); | |
48 | |
45 void ReportForegroundRendererTaskLoad(base::TimeTicks time, double load) { | 49 void ReportForegroundRendererTaskLoad(base::TimeTicks time, double load) { |
46 int load_percentage = static_cast<int>(load * 100); | 50 int load_percentage = static_cast<int>(load * 100); |
47 UMA_HISTOGRAM_PERCENTAGE("RendererScheduler.ForegroundRendererMainThreadLoad", | 51 UMA_HISTOGRAM_PERCENTAGE("RendererScheduler.ForegroundRendererMainThreadLoad", |
48 load_percentage); | 52 load_percentage); |
49 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), | 53 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), |
50 "RendererScheduler.ForegroundRendererLoad", load_percentage); | 54 "RendererScheduler.ForegroundRendererLoad", load_percentage); |
51 } | 55 } |
52 | 56 |
53 void ReportBackgroundRendererTaskLoad(base::TimeTicks time, double load) { | 57 void ReportBackgroundRendererTaskLoad(base::TimeTicks time, double load) { |
54 int load_percentage = static_cast<int>(load * 100); | 58 int load_percentage = static_cast<int>(load * 100); |
(...skipping 28 matching lines...) Expand all Loading... | |
83 helper_.NewTaskQueue(TaskQueue::Spec(TaskQueue::QueueType::COMPOSITOR) | 87 helper_.NewTaskQueue(TaskQueue::Spec(TaskQueue::QueueType::COMPOSITOR) |
84 .SetShouldMonitorQuiescence(true))), | 88 .SetShouldMonitorQuiescence(true))), |
85 delayed_update_policy_runner_( | 89 delayed_update_policy_runner_( |
86 base::Bind(&RendererSchedulerImpl::UpdatePolicy, | 90 base::Bind(&RendererSchedulerImpl::UpdatePolicy, |
87 base::Unretained(this)), | 91 base::Unretained(this)), |
88 helper_.ControlTaskRunner()), | 92 helper_.ControlTaskRunner()), |
89 main_thread_only_(this, | 93 main_thread_only_(this, |
90 compositor_task_runner_, | 94 compositor_task_runner_, |
91 helper_.scheduler_tqm_delegate().get(), | 95 helper_.scheduler_tqm_delegate().get(), |
92 helper_.scheduler_tqm_delegate()->NowTicks()), | 96 helper_.scheduler_tqm_delegate()->NowTicks()), |
97 any_thread_(this), | |
93 policy_may_need_update_(&any_thread_lock_), | 98 policy_may_need_update_(&any_thread_lock_), |
94 weak_factory_(this) { | 99 weak_factory_(this) { |
95 task_queue_throttler_.reset( | 100 task_queue_throttler_.reset( |
96 new TaskQueueThrottler(this, "renderer.scheduler")); | 101 new TaskQueueThrottler(this, "renderer.scheduler")); |
97 update_policy_closure_ = base::Bind(&RendererSchedulerImpl::UpdatePolicy, | 102 update_policy_closure_ = base::Bind(&RendererSchedulerImpl::UpdatePolicy, |
98 weak_factory_.GetWeakPtr()); | 103 weak_factory_.GetWeakPtr()); |
99 end_renderer_hidden_idle_period_closure_.Reset(base::Bind( | 104 end_renderer_hidden_idle_period_closure_.Reset(base::Bind( |
100 &RendererSchedulerImpl::EndIdlePeriod, weak_factory_.GetWeakPtr())); | 105 &RendererSchedulerImpl::EndIdlePeriod, weak_factory_.GetWeakPtr())); |
101 | 106 |
102 suspend_timers_when_backgrounded_closure_.Reset( | 107 suspend_timers_when_backgrounded_closure_.Reset( |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
145 RendererSchedulerImpl* renderer_scheduler_impl, | 150 RendererSchedulerImpl* renderer_scheduler_impl, |
146 const scoped_refptr<TaskQueue>& compositor_task_runner, | 151 const scoped_refptr<TaskQueue>& compositor_task_runner, |
147 base::TickClock* time_source, | 152 base::TickClock* time_source, |
148 base::TimeTicks now) | 153 base::TimeTicks now) |
149 : loading_task_cost_estimator(time_source, | 154 : loading_task_cost_estimator(time_source, |
150 kLoadingTaskEstimationSampleCount, | 155 kLoadingTaskEstimationSampleCount, |
151 kLoadingTaskEstimationPercentile), | 156 kLoadingTaskEstimationPercentile), |
152 timer_task_cost_estimator(time_source, | 157 timer_task_cost_estimator(time_source, |
153 kTimerTaskEstimationSampleCount, | 158 kTimerTaskEstimationSampleCount, |
154 kTimerTaskEstimationPercentile), | 159 kTimerTaskEstimationPercentile), |
155 queueing_time_estimator(renderer_scheduler_impl, | |
156 base::TimeDelta::FromSeconds(1)), | |
157 idle_time_estimator(compositor_task_runner, | 160 idle_time_estimator(compositor_task_runner, |
158 time_source, | 161 time_source, |
159 kShortIdlePeriodDurationSampleCount, | 162 kShortIdlePeriodDurationSampleCount, |
160 kShortIdlePeriodDurationPercentile), | 163 kShortIdlePeriodDurationPercentile), |
164 queueing_time_estimator(renderer_scheduler_impl, | |
165 base::TimeDelta::FromSeconds(1)), | |
161 background_main_thread_load_tracker( | 166 background_main_thread_load_tracker( |
162 now, | 167 now, |
163 base::Bind(&ReportBackgroundRendererTaskLoad), | 168 base::Bind(&ReportBackgroundRendererTaskLoad), |
164 kThreadLoadTrackerReportingInterval, | 169 kThreadLoadTrackerReportingInterval, |
165 kThreadLoadTrackerWaitingPeriodBeforeReporting), | 170 kThreadLoadTrackerWaitingPeriodBeforeReporting), |
166 foreground_main_thread_load_tracker( | 171 foreground_main_thread_load_tracker( |
167 now, | 172 now, |
168 base::Bind(&ReportForegroundRendererTaskLoad), | 173 base::Bind(&ReportForegroundRendererTaskLoad), |
169 kThreadLoadTrackerReportingInterval, | 174 kThreadLoadTrackerReportingInterval, |
170 kThreadLoadTrackerWaitingPeriodBeforeReporting), | 175 kThreadLoadTrackerWaitingPeriodBeforeReporting), |
(...skipping 14 matching lines...) Expand all Loading... | |
185 have_reported_blocking_intervention_in_current_policy(false), | 190 have_reported_blocking_intervention_in_current_policy(false), |
186 have_reported_blocking_intervention_since_navigation(false), | 191 have_reported_blocking_intervention_since_navigation(false), |
187 has_visible_render_widget_with_touch_handler(false), | 192 has_visible_render_widget_with_touch_handler(false), |
188 begin_frame_not_expected_soon(false), | 193 begin_frame_not_expected_soon(false), |
189 in_idle_period_for_testing(false), | 194 in_idle_period_for_testing(false), |
190 use_virtual_time(false), | 195 use_virtual_time(false), |
191 rail_mode_observer(nullptr) {} | 196 rail_mode_observer(nullptr) {} |
192 | 197 |
193 RendererSchedulerImpl::MainThreadOnly::~MainThreadOnly() {} | 198 RendererSchedulerImpl::MainThreadOnly::~MainThreadOnly() {} |
194 | 199 |
195 RendererSchedulerImpl::AnyThread::AnyThread() | 200 RendererSchedulerImpl::AnyThread::AnyThread( |
201 RendererSchedulerImpl* renderer_scheduler_impl) | |
196 : awaiting_touch_start_response(false), | 202 : awaiting_touch_start_response(false), |
197 in_idle_period(false), | 203 in_idle_period(false), |
198 begin_main_frame_on_critical_path(false), | 204 begin_main_frame_on_critical_path(false), |
199 last_gesture_was_compositor_driven(false), | 205 last_gesture_was_compositor_driven(false), |
200 default_gesture_prevented(true), | 206 default_gesture_prevented(true), |
201 have_seen_touchstart(false) {} | 207 have_seen_touchstart(false) {} |
202 | 208 |
203 RendererSchedulerImpl::AnyThread::~AnyThread() {} | 209 RendererSchedulerImpl::AnyThread::~AnyThread() {} |
204 | 210 |
205 RendererSchedulerImpl::CompositorThreadOnly::CompositorThreadOnly() | 211 RendererSchedulerImpl::CompositorThreadOnly::CompositorThreadOnly() |
(...skipping 1224 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1430 default_loading_task_runner_->SetBlameContext(blame_context); | 1436 default_loading_task_runner_->SetBlameContext(blame_context); |
1431 default_timer_task_runner_->SetBlameContext(blame_context); | 1437 default_timer_task_runner_->SetBlameContext(blame_context); |
1432 compositor_task_runner_->SetBlameContext(blame_context); | 1438 compositor_task_runner_->SetBlameContext(blame_context); |
1433 idle_helper_.IdleTaskRunner()->SetBlameContext(blame_context); | 1439 idle_helper_.IdleTaskRunner()->SetBlameContext(blame_context); |
1434 } | 1440 } |
1435 | 1441 |
1436 void RendererSchedulerImpl::SetRAILModeObserver(RAILModeObserver* observer) { | 1442 void RendererSchedulerImpl::SetRAILModeObserver(RAILModeObserver* observer) { |
1437 MainThreadOnly().rail_mode_observer = observer; | 1443 MainThreadOnly().rail_mode_observer = observer; |
1438 } | 1444 } |
1439 | 1445 |
1446 bool RendererSchedulerImpl::MainThreadSeemsUnresponsive() const { | |
1447 base::TimeTicks now = base::TimeTicks::Now(); | |
1448 base::TimeDelta estimated_queueing_time; | |
1449 | |
1450 bool can_read = false; | |
1451 QueueingTimeEstimator::SerializedQueueingTimeEstimator | |
1452 serialized_queueing_time_estimator; | |
1453 | |
1454 base::subtle::Atomic32 version; | |
1455 seqlock_queueing_time_estimator_.seqlock.ReadOrFail(&can_read, &version); | |
1456 | |
1457 // If we fail to determine if the main thread is busy, assume it isn't. | |
1458 if (!can_read) | |
1459 return false; | |
Sami
2016/11/03 16:43:15
Could we instead cache the previous result and ret
tdresser
2016/11/03 18:23:54
I'd prefer we err on the side of not intervening,
Sami
2016/11/03 18:34:50
I'm thinking consistency is worth the one extra bo
| |
1460 | |
1461 serialized_queueing_time_estimator = seqlock_queueing_time_estimator_.data; | |
1462 | |
1463 // If we fail to determine if the main thread is busy, assume it isn't. | |
1464 if (seqlock_queueing_time_estimator_.seqlock.ReadRetry(version)) | |
1465 return false; | |
1466 | |
1467 QueueingTimeEstimator queueing_time_estimator( | |
1468 serialized_queueing_time_estimator); | |
1469 | |
1470 estimated_queueing_time = | |
1471 queueing_time_estimator.EstimateQueueingTimeIncludingCurrentTask(now); | |
1472 | |
1473 return estimated_queueing_time > kMainThreadUnresponsiveQueueingTime; | |
1474 } | |
1475 | |
1440 void RendererSchedulerImpl::RegisterTimeDomain(TimeDomain* time_domain) { | 1476 void RendererSchedulerImpl::RegisterTimeDomain(TimeDomain* time_domain) { |
1441 helper_.RegisterTimeDomain(time_domain); | 1477 helper_.RegisterTimeDomain(time_domain); |
1442 } | 1478 } |
1443 | 1479 |
1444 void RendererSchedulerImpl::UnregisterTimeDomain(TimeDomain* time_domain) { | 1480 void RendererSchedulerImpl::UnregisterTimeDomain(TimeDomain* time_domain) { |
1445 helper_.UnregisterTimeDomain(time_domain); | 1481 helper_.UnregisterTimeDomain(time_domain); |
1446 } | 1482 } |
1447 | 1483 |
1448 base::TickClock* RendererSchedulerImpl::tick_clock() const { | 1484 base::TickClock* RendererSchedulerImpl::tick_clock() const { |
1449 return helper_.scheduler_tqm_delegate().get(); | 1485 return helper_.scheduler_tqm_delegate().get(); |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1499 true; | 1535 true; |
1500 BroadcastIntervention( | 1536 BroadcastIntervention( |
1501 "Blink deferred a task in order to make scrolling smoother. " | 1537 "Blink deferred a task in order to make scrolling smoother. " |
1502 "Your timer and network tasks should take less than 50ms to run " | 1538 "Your timer and network tasks should take less than 50ms to run " |
1503 "to avoid this. Please see " | 1539 "to avoid this. Please see " |
1504 "https://developers.google.com/web/tools/chrome-devtools/profile/evaluat e-performance/rail" | 1540 "https://developers.google.com/web/tools/chrome-devtools/profile/evaluat e-performance/rail" |
1505 " and https://crbug.com/574343#c40 for more information."); | 1541 " and https://crbug.com/574343#c40 for more information."); |
1506 } | 1542 } |
1507 } | 1543 } |
1508 | 1544 |
1509 void RendererSchedulerImpl::ReportTaskTime(TaskQueue* task_queue, | 1545 void RendererSchedulerImpl::ReportTaskStartTime(double start_time) { |
1510 double start_time, | 1546 base::TimeTicks start_time_ticks = |
1511 double end_time) { | 1547 MonotonicTimeInSecondsToTimeTicks(start_time); |
1548 MainThreadOnly().current_task_start_time = start_time_ticks; | |
1549 MainThreadOnly().queueing_time_estimator.OnTopLevelTaskStarted( | |
1550 start_time_ticks); | |
1551 | |
1552 QueueingTimeEstimator::SerializedQueueingTimeEstimator | |
1553 serialized_queueing_time_estimator = | |
1554 MainThreadOnly().queueing_time_estimator.Serialize(); | |
1555 | |
1556 seqlock_queueing_time_estimator_.seqlock.WriteBegin(); | |
1557 seqlock_queueing_time_estimator_.data = serialized_queueing_time_estimator; | |
1558 seqlock_queueing_time_estimator_.seqlock.WriteEnd(); | |
1559 } | |
1560 | |
1561 void RendererSchedulerImpl::ReportTaskEndTime(TaskQueue* task_queue, | |
1562 double start_time, | |
1563 double end_time) { | |
1512 // TODO(scheduler-dev): Remove conversions when Blink starts using | 1564 // TODO(scheduler-dev): Remove conversions when Blink starts using |
1513 // base::TimeTicks instead of doubles for time. | 1565 // base::TimeTicks instead of doubles for time. |
1514 base::TimeTicks start_time_ticks = | 1566 base::TimeTicks start_time_ticks = |
1515 MonotonicTimeInSecondsToTimeTicks(start_time); | 1567 MonotonicTimeInSecondsToTimeTicks(start_time); |
1516 base::TimeTicks end_time_ticks = MonotonicTimeInSecondsToTimeTicks(end_time); | 1568 base::TimeTicks end_time_ticks = MonotonicTimeInSecondsToTimeTicks(end_time); |
1569 MainThreadOnly().queueing_time_estimator.OnTopLevelTaskCompleted( | |
1570 end_time_ticks); | |
1517 | 1571 |
1518 MainThreadOnly().queueing_time_estimator.OnToplevelTaskCompleted( | 1572 QueueingTimeEstimator::SerializedQueueingTimeEstimator |
1519 start_time_ticks, end_time_ticks); | 1573 serialized_queueing_time_estimator = |
1574 MainThreadOnly().queueing_time_estimator.Serialize(); | |
1575 | |
1576 seqlock_queueing_time_estimator_.seqlock.WriteBegin(); | |
Sami
2016/11/03 16:43:15
Is there a way to do this write less often, e.g.,
tdresser
2016/11/03 18:23:54
What do you mean by "the answer"? The most recent
Sami
2016/11/03 18:34:50
Yeah, I just realized after I wrote that that this
| |
1577 seqlock_queueing_time_estimator_.data = serialized_queueing_time_estimator; | |
1578 seqlock_queueing_time_estimator_.seqlock.WriteEnd(); | |
1520 | 1579 |
1521 task_queue_throttler()->OnTaskRunTimeReported(task_queue, start_time_ticks, | 1580 task_queue_throttler()->OnTaskRunTimeReported(task_queue, start_time_ticks, |
1522 end_time_ticks); | 1581 end_time_ticks); |
1523 | 1582 |
1524 // We want to measure thread time here, but for efficiency reasons | 1583 // We want to measure thread time here, but for efficiency reasons |
1525 // we stick with wall time. | 1584 // we stick with wall time. |
1526 MainThreadOnly().foreground_main_thread_load_tracker.RecordTaskTime( | 1585 MainThreadOnly().foreground_main_thread_load_tracker.RecordTaskTime( |
1527 start_time_ticks, end_time_ticks); | 1586 start_time_ticks, end_time_ticks); |
1528 MainThreadOnly().background_main_thread_load_tracker.RecordTaskTime( | 1587 MainThreadOnly().background_main_thread_load_tracker.RecordTaskTime( |
1529 start_time_ticks, end_time_ticks); | 1588 start_time_ticks, end_time_ticks); |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1612 case v8::PERFORMANCE_LOAD: | 1671 case v8::PERFORMANCE_LOAD: |
1613 return "load"; | 1672 return "load"; |
1614 default: | 1673 default: |
1615 NOTREACHED(); | 1674 NOTREACHED(); |
1616 return nullptr; | 1675 return nullptr; |
1617 } | 1676 } |
1618 } | 1677 } |
1619 | 1678 |
1620 } // namespace scheduler | 1679 } // namespace scheduler |
1621 } // namespace blink | 1680 } // namespace blink |
OLD | NEW |