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

Side by Side Diff: third_party/WebKit/Source/platform/scheduler/renderer/renderer_scheduler_impl.cc

Issue 2273703002: Force events to be non blocking if main thread is unresponsive. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Address feedback. Created 4 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
OLDNEW
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
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
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698