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

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: Fix build. 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 const base::TimeDelta kMainThreadUnresponsiveQueueingTime =
Sami 2016/11/02 19:01:42 constexpr to avoid a global static initializer.
tdresser 2016/11/03 13:56:10 Done.
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 24 matching lines...) Expand all
79 base::TimeDelta()), 83 base::TimeDelta()),
80 render_widget_scheduler_signals_(this), 84 render_widget_scheduler_signals_(this),
81 control_task_runner_(helper_.ControlTaskRunner()), 85 control_task_runner_(helper_.ControlTaskRunner()),
82 compositor_task_runner_( 86 compositor_task_runner_(
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()),
93 seqlock_queueing_time_estimator_(
94 QueueingTimeEstimator(this, base::TimeDelta::FromSeconds(1))),
89 main_thread_only_(this, 95 main_thread_only_(this,
90 compositor_task_runner_, 96 compositor_task_runner_,
91 helper_.scheduler_tqm_delegate().get(), 97 helper_.scheduler_tqm_delegate().get(),
92 helper_.scheduler_tqm_delegate()->NowTicks()), 98 helper_.scheduler_tqm_delegate()->NowTicks()),
99 any_thread_(this),
93 policy_may_need_update_(&any_thread_lock_), 100 policy_may_need_update_(&any_thread_lock_),
94 weak_factory_(this) { 101 weak_factory_(this) {
95 task_queue_throttler_.reset( 102 task_queue_throttler_.reset(
96 new TaskQueueThrottler(this, "renderer.scheduler")); 103 new TaskQueueThrottler(this, "renderer.scheduler"));
97 update_policy_closure_ = base::Bind(&RendererSchedulerImpl::UpdatePolicy, 104 update_policy_closure_ = base::Bind(&RendererSchedulerImpl::UpdatePolicy,
98 weak_factory_.GetWeakPtr()); 105 weak_factory_.GetWeakPtr());
99 end_renderer_hidden_idle_period_closure_.Reset(base::Bind( 106 end_renderer_hidden_idle_period_closure_.Reset(base::Bind(
100 &RendererSchedulerImpl::EndIdlePeriod, weak_factory_.GetWeakPtr())); 107 &RendererSchedulerImpl::EndIdlePeriod, weak_factory_.GetWeakPtr()));
101 108
102 suspend_timers_when_backgrounded_closure_.Reset( 109 suspend_timers_when_backgrounded_closure_.Reset(
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
145 RendererSchedulerImpl* renderer_scheduler_impl, 152 RendererSchedulerImpl* renderer_scheduler_impl,
146 const scoped_refptr<TaskQueue>& compositor_task_runner, 153 const scoped_refptr<TaskQueue>& compositor_task_runner,
147 base::TickClock* time_source, 154 base::TickClock* time_source,
148 base::TimeTicks now) 155 base::TimeTicks now)
149 : loading_task_cost_estimator(time_source, 156 : loading_task_cost_estimator(time_source,
150 kLoadingTaskEstimationSampleCount, 157 kLoadingTaskEstimationSampleCount,
151 kLoadingTaskEstimationPercentile), 158 kLoadingTaskEstimationPercentile),
152 timer_task_cost_estimator(time_source, 159 timer_task_cost_estimator(time_source,
153 kTimerTaskEstimationSampleCount, 160 kTimerTaskEstimationSampleCount,
154 kTimerTaskEstimationPercentile), 161 kTimerTaskEstimationPercentile),
155 queueing_time_estimator(renderer_scheduler_impl,
156 base::TimeDelta::FromSeconds(1)),
157 idle_time_estimator(compositor_task_runner, 162 idle_time_estimator(compositor_task_runner,
158 time_source, 163 time_source,
159 kShortIdlePeriodDurationSampleCount, 164 kShortIdlePeriodDurationSampleCount,
160 kShortIdlePeriodDurationPercentile), 165 kShortIdlePeriodDurationPercentile),
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(
(...skipping 18 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::
1447 ShouldForceEventsNonBlockingForUnresponsiveMainThread() const {
1448 base::TimeTicks now = base::TimeTicks::Now();
1449 base::TimeDelta estimated_queueing_time;
1450
1451 std::unique_ptr<QueueingTimeEstimator> queueing_time_estimator;
1452 {
1453 bool can_read = false;
1454 base::subtle::Atomic32 version;
1455 seqlock_queueing_time_estimator_.seqlock.ReadOrFail(&can_read, &version);
1456
1457 if (can_read) {
1458 // TODO - is this copy okay? Use memcpy?
Sami 2016/11/02 19:01:42 I'd need to think about this a bit more, but I thi
tdresser 2016/11/03 13:56:10 Done, though it's a bit ugly. This is probably a b
alex clarke (OOO till 29th) 2016/11/03 15:20:53 I'm not sure what we gain by /not/ copying the bas
1459 queueing_time_estimator.reset(
1460 new QueueingTimeEstimator(seqlock_queueing_time_estimator_.data));
1461 }
1462
1463 // If we didn't successfully read the first time, assume we aren't busy.
1464 if (seqlock_queueing_time_estimator_.seqlock.ReadRetry(version))
1465 queueing_time_estimator.reset();
1466 }
1467
1468 if (queueing_time_estimator) {
1469 estimated_queueing_time =
1470 queueing_time_estimator->EstimateQueueingTimeIncludingCurrentTask(now);
1471 }
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
1550 seqlock_queueing_time_estimator_.seqlock.WriteBegin();
1551 seqlock_queueing_time_estimator_.data.OnTopLevelTaskStarted(start_time_ticks);
1552 seqlock_queueing_time_estimator_.seqlock.WriteEnd();
1553 }
1554
1555 void RendererSchedulerImpl::ReportTaskEndTime(TaskQueue* task_queue,
1556 double start_time,
1557 double end_time) {
1512 // TODO(scheduler-dev): Remove conversions when Blink starts using 1558 // TODO(scheduler-dev): Remove conversions when Blink starts using
1513 // base::TimeTicks instead of doubles for time. 1559 // base::TimeTicks instead of doubles for time.
1514 base::TimeTicks start_time_ticks = 1560 base::TimeTicks start_time_ticks =
1515 MonotonicTimeInSecondsToTimeTicks(start_time); 1561 MonotonicTimeInSecondsToTimeTicks(start_time);
1516 base::TimeTicks end_time_ticks = MonotonicTimeInSecondsToTimeTicks(end_time); 1562 base::TimeTicks end_time_ticks = MonotonicTimeInSecondsToTimeTicks(end_time);
1517 1563
1518 MainThreadOnly().queueing_time_estimator.OnToplevelTaskCompleted( 1564 seqlock_queueing_time_estimator_.seqlock.WriteBegin();
1519 start_time_ticks, end_time_ticks); 1565 seqlock_queueing_time_estimator_.data.OnTopLevelTaskCompleted(end_time_ticks);
1566 seqlock_queueing_time_estimator_.seqlock.WriteEnd();
1520 1567
1521 task_queue_throttler()->OnTaskRunTimeReported(task_queue, start_time_ticks, 1568 task_queue_throttler()->OnTaskRunTimeReported(task_queue, start_time_ticks,
1522 end_time_ticks); 1569 end_time_ticks);
1523 1570
1524 // We want to measure thread time here, but for efficiency reasons 1571 // We want to measure thread time here, but for efficiency reasons
1525 // we stick with wall time. 1572 // we stick with wall time.
1526 MainThreadOnly().foreground_main_thread_load_tracker.RecordTaskTime( 1573 MainThreadOnly().foreground_main_thread_load_tracker.RecordTaskTime(
1527 start_time_ticks, end_time_ticks); 1574 start_time_ticks, end_time_ticks);
1528 MainThreadOnly().background_main_thread_load_tracker.RecordTaskTime( 1575 MainThreadOnly().background_main_thread_load_tracker.RecordTaskTime(
1529 start_time_ticks, end_time_ticks); 1576 start_time_ticks, end_time_ticks);
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
1612 case v8::PERFORMANCE_LOAD: 1659 case v8::PERFORMANCE_LOAD:
1613 return "load"; 1660 return "load";
1614 default: 1661 default:
1615 NOTREACHED(); 1662 NOTREACHED();
1616 return nullptr; 1663 return nullptr;
1617 } 1664 }
1618 } 1665 }
1619 1666
1620 } // namespace scheduler 1667 } // namespace scheduler
1621 } // namespace blink 1668 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698