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

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 nits. Created 4 years 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 29 matching lines...) Expand all
40 // Amount of idle time left in a frame (as a ratio of the vsync interval) above 40 // Amount of idle time left in a frame (as a ratio of the vsync interval) above
41 // which main thread compositing can be considered fast. 41 // which main thread compositing can be considered fast.
42 const double kFastCompositingIdleTimeThreshold = .2; 42 const double kFastCompositingIdleTimeThreshold = .2;
43 constexpr base::TimeDelta kThreadLoadTrackerReportingInterval = 43 constexpr base::TimeDelta kThreadLoadTrackerReportingInterval =
44 base::TimeDelta::FromMinutes(1); 44 base::TimeDelta::FromMinutes(1);
45 constexpr base::TimeDelta kThreadLoadTrackerWaitingPeriodBeforeReporting = 45 constexpr base::TimeDelta kThreadLoadTrackerWaitingPeriodBeforeReporting =
46 base::TimeDelta::FromMinutes(2); 46 base::TimeDelta::FromMinutes(2);
47 // We do not throttle anything while audio is played and shortly after that. 47 // We do not throttle anything while audio is played and shortly after that.
48 constexpr base::TimeDelta kThrottlingDelayAfterAudioIsPlayed = 48 constexpr base::TimeDelta kThrottlingDelayAfterAudioIsPlayed =
49 base::TimeDelta::FromSeconds(5); 49 base::TimeDelta::FromSeconds(5);
50 // Maximum task queueing time before the main thread is considered unresponsive.
51 constexpr base::TimeDelta kMainThreadResponsivenessThreshold =
52 base::TimeDelta::FromMilliseconds(200);
50 53
51 void ReportForegroundRendererTaskLoad(base::TimeTicks time, double load) { 54 void ReportForegroundRendererTaskLoad(base::TimeTicks time, double load) {
52 int load_percentage = static_cast<int>(load * 100); 55 int load_percentage = static_cast<int>(load * 100);
53 UMA_HISTOGRAM_PERCENTAGE("RendererScheduler.ForegroundRendererMainThreadLoad", 56 UMA_HISTOGRAM_PERCENTAGE("RendererScheduler.ForegroundRendererMainThreadLoad",
54 load_percentage); 57 load_percentage);
55 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), 58 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"),
56 "RendererScheduler.ForegroundRendererLoad", load_percentage); 59 "RendererScheduler.ForegroundRendererLoad", load_percentage);
57 } 60 }
58 61
59 void ReportBackgroundRendererTaskLoad(base::TimeTicks time, double load) { 62 void ReportBackgroundRendererTaskLoad(base::TimeTicks time, double load) {
60 int load_percentage = static_cast<int>(load * 100); 63 int load_percentage = static_cast<int>(load * 100);
61 UMA_HISTOGRAM_PERCENTAGE("RendererScheduler.BackgroundRendererMainThreadLoad", 64 UMA_HISTOGRAM_PERCENTAGE("RendererScheduler.BackgroundRendererMainThreadLoad",
62 load_percentage); 65 load_percentage);
63 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), 66 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"),
64 "RendererScheduler.BackgroundRendererLoad", load_percentage); 67 "RendererScheduler.BackgroundRendererLoad", load_percentage);
65 } 68 }
66 69
67 base::TimeTicks MonotonicTimeInSecondsToTimeTicks( 70 base::TimeTicks MonotonicTimeInSecondsToTimeTicks(
68 double monotonicTimeInSeconds) { 71 double monotonicTimeInSeconds) {
69 return base::TimeTicks() + base::TimeDelta::FromSecondsD( 72 return base::TimeTicks() +
70 monotonicTimeInSeconds); 73 base::TimeDelta::FromSecondsD(monotonicTimeInSeconds);
71 } 74 }
72 75
73 std::string PointerToId(void* pointer) { 76 std::string PointerToId(void* pointer) {
74 return base::StringPrintf( 77 return base::StringPrintf(
75 "0x%" PRIx64, 78 "0x%" PRIx64,
76 static_cast<uint64_t>(reinterpret_cast<uintptr_t>(pointer))); 79 static_cast<uint64_t>(reinterpret_cast<uintptr_t>(pointer)));
77 } 80 }
78 81
79 } // namespace 82 } // namespace
80 83
(...skipping 13 matching lines...) Expand all
94 control_task_runner_(helper_.ControlTaskRunner()), 97 control_task_runner_(helper_.ControlTaskRunner()),
95 compositor_task_runner_( 98 compositor_task_runner_(
96 helper_.NewTaskQueue(TaskQueue::Spec(TaskQueue::QueueType::COMPOSITOR) 99 helper_.NewTaskQueue(TaskQueue::Spec(TaskQueue::QueueType::COMPOSITOR)
97 .SetShouldMonitorQuiescence(true))), 100 .SetShouldMonitorQuiescence(true))),
98 compositor_task_runner_enabled_voter_( 101 compositor_task_runner_enabled_voter_(
99 compositor_task_runner_->CreateQueueEnabledVoter()), 102 compositor_task_runner_->CreateQueueEnabledVoter()),
100 delayed_update_policy_runner_( 103 delayed_update_policy_runner_(
101 base::Bind(&RendererSchedulerImpl::UpdatePolicy, 104 base::Bind(&RendererSchedulerImpl::UpdatePolicy,
102 base::Unretained(this)), 105 base::Unretained(this)),
103 helper_.ControlTaskRunner()), 106 helper_.ControlTaskRunner()),
107 seqlock_queueing_time_estimator_(
108 QueueingTimeEstimator(this, base::TimeDelta::FromSeconds(1))),
104 main_thread_only_(this, 109 main_thread_only_(this,
105 compositor_task_runner_, 110 compositor_task_runner_,
106 helper_.scheduler_tqm_delegate().get(), 111 helper_.scheduler_tqm_delegate().get(),
107 helper_.scheduler_tqm_delegate()->NowTicks()), 112 helper_.scheduler_tqm_delegate()->NowTicks()),
113 any_thread_(this),
108 policy_may_need_update_(&any_thread_lock_), 114 policy_may_need_update_(&any_thread_lock_),
115 main_thread_responsiveness_threshold_(kMainThreadResponsivenessThreshold),
109 weak_factory_(this) { 116 weak_factory_(this) {
110 task_queue_throttler_.reset( 117 task_queue_throttler_.reset(
111 new TaskQueueThrottler(this, "renderer.scheduler")); 118 new TaskQueueThrottler(this, "renderer.scheduler"));
112 update_policy_closure_ = base::Bind(&RendererSchedulerImpl::UpdatePolicy, 119 update_policy_closure_ = base::Bind(&RendererSchedulerImpl::UpdatePolicy,
113 weak_factory_.GetWeakPtr()); 120 weak_factory_.GetWeakPtr());
114 end_renderer_hidden_idle_period_closure_.Reset(base::Bind( 121 end_renderer_hidden_idle_period_closure_.Reset(base::Bind(
115 &RendererSchedulerImpl::EndIdlePeriod, weak_factory_.GetWeakPtr())); 122 &RendererSchedulerImpl::EndIdlePeriod, weak_factory_.GetWeakPtr()));
116 123
117 suspend_timers_when_backgrounded_closure_.Reset( 124 suspend_timers_when_backgrounded_closure_.Reset(
118 base::Bind(&RendererSchedulerImpl::SuspendTimerQueueWhenBackgrounded, 125 base::Bind(&RendererSchedulerImpl::SuspendTimerQueueWhenBackgrounded,
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
169 RendererSchedulerImpl* renderer_scheduler_impl, 176 RendererSchedulerImpl* renderer_scheduler_impl,
170 const scoped_refptr<TaskQueue>& compositor_task_runner, 177 const scoped_refptr<TaskQueue>& compositor_task_runner,
171 base::TickClock* time_source, 178 base::TickClock* time_source,
172 base::TimeTicks now) 179 base::TimeTicks now)
173 : loading_task_cost_estimator(time_source, 180 : loading_task_cost_estimator(time_source,
174 kLoadingTaskEstimationSampleCount, 181 kLoadingTaskEstimationSampleCount,
175 kLoadingTaskEstimationPercentile), 182 kLoadingTaskEstimationPercentile),
176 timer_task_cost_estimator(time_source, 183 timer_task_cost_estimator(time_source,
177 kTimerTaskEstimationSampleCount, 184 kTimerTaskEstimationSampleCount,
178 kTimerTaskEstimationPercentile), 185 kTimerTaskEstimationPercentile),
179 queueing_time_estimator(renderer_scheduler_impl,
180 base::TimeDelta::FromSeconds(1)),
181 idle_time_estimator(compositor_task_runner, 186 idle_time_estimator(compositor_task_runner,
182 time_source, 187 time_source,
183 kShortIdlePeriodDurationSampleCount, 188 kShortIdlePeriodDurationSampleCount,
184 kShortIdlePeriodDurationPercentile), 189 kShortIdlePeriodDurationPercentile),
185 background_main_thread_load_tracker( 190 background_main_thread_load_tracker(
186 now, 191 now,
187 base::Bind(&ReportBackgroundRendererTaskLoad), 192 base::Bind(&ReportBackgroundRendererTaskLoad),
188 kThreadLoadTrackerReportingInterval, 193 kThreadLoadTrackerReportingInterval,
189 kThreadLoadTrackerWaitingPeriodBeforeReporting), 194 kThreadLoadTrackerWaitingPeriodBeforeReporting),
190 foreground_main_thread_load_tracker( 195 foreground_main_thread_load_tracker(
(...skipping 19 matching lines...) Expand all
210 have_reported_blocking_intervention_since_navigation(false), 215 have_reported_blocking_intervention_since_navigation(false),
211 has_visible_render_widget_with_touch_handler(false), 216 has_visible_render_widget_with_touch_handler(false),
212 begin_frame_not_expected_soon(false), 217 begin_frame_not_expected_soon(false),
213 in_idle_period_for_testing(false), 218 in_idle_period_for_testing(false),
214 use_virtual_time(false), 219 use_virtual_time(false),
215 is_audio_playing(false), 220 is_audio_playing(false),
216 rail_mode_observer(nullptr) {} 221 rail_mode_observer(nullptr) {}
217 222
218 RendererSchedulerImpl::MainThreadOnly::~MainThreadOnly() {} 223 RendererSchedulerImpl::MainThreadOnly::~MainThreadOnly() {}
219 224
220 RendererSchedulerImpl::AnyThread::AnyThread() 225 RendererSchedulerImpl::AnyThread::AnyThread(
226 RendererSchedulerImpl* renderer_scheduler_impl)
alex clarke (OOO till 29th) 2016/12/15 14:24:37 nit: this seems unused - lets revert this change.
tdresser 2016/12/15 14:53:25 Done.
221 : awaiting_touch_start_response(false), 227 : awaiting_touch_start_response(false),
222 in_idle_period(false), 228 in_idle_period(false),
223 begin_main_frame_on_critical_path(false), 229 begin_main_frame_on_critical_path(false),
224 last_gesture_was_compositor_driven(false), 230 last_gesture_was_compositor_driven(false),
225 default_gesture_prevented(true), 231 default_gesture_prevented(true),
226 have_seen_touchstart(false), 232 have_seen_touchstart(false),
227 waiting_for_meaningful_paint(false), 233 waiting_for_meaningful_paint(false),
228 have_seen_input_since_navigation(false) {} 234 have_seen_input_since_navigation(false) {}
229 235
230 RendererSchedulerImpl::AnyThread::~AnyThread() {} 236 RendererSchedulerImpl::AnyThread::~AnyThread() {}
231 237
232 RendererSchedulerImpl::CompositorThreadOnly::CompositorThreadOnly() 238 RendererSchedulerImpl::CompositorThreadOnly::CompositorThreadOnly()
233 : last_input_type(blink::WebInputEvent::Undefined) {} 239 : last_input_type(blink::WebInputEvent::Undefined),
240 main_thread_seems_unresponsive(false) {}
234 241
235 RendererSchedulerImpl::CompositorThreadOnly::~CompositorThreadOnly() {} 242 RendererSchedulerImpl::CompositorThreadOnly::~CompositorThreadOnly() {}
236 243
237 void RendererSchedulerImpl::Shutdown() { 244 void RendererSchedulerImpl::Shutdown() {
238 base::TimeTicks now = tick_clock()->NowTicks(); 245 base::TimeTicks now = tick_clock()->NowTicks();
239 MainThreadOnly().background_main_thread_load_tracker.RecordIdle(now); 246 MainThreadOnly().background_main_thread_load_tracker.RecordIdle(now);
240 MainThreadOnly().foreground_main_thread_load_tracker.RecordIdle(now); 247 MainThreadOnly().foreground_main_thread_load_tracker.RecordIdle(now);
241 248
242 task_queue_throttler_.reset(); 249 task_queue_throttler_.reset();
243 helper_.Shutdown(); 250 helper_.Shutdown();
(...skipping 1350 matching lines...) Expand 10 before | Expand all | Expand 10 after
1594 default_loading_task_runner_->SetBlameContext(blame_context); 1601 default_loading_task_runner_->SetBlameContext(blame_context);
1595 default_timer_task_runner_->SetBlameContext(blame_context); 1602 default_timer_task_runner_->SetBlameContext(blame_context);
1596 compositor_task_runner_->SetBlameContext(blame_context); 1603 compositor_task_runner_->SetBlameContext(blame_context);
1597 idle_helper_.IdleTaskRunner()->SetBlameContext(blame_context); 1604 idle_helper_.IdleTaskRunner()->SetBlameContext(blame_context);
1598 } 1605 }
1599 1606
1600 void RendererSchedulerImpl::SetRAILModeObserver(RAILModeObserver* observer) { 1607 void RendererSchedulerImpl::SetRAILModeObserver(RAILModeObserver* observer) {
1601 MainThreadOnly().rail_mode_observer = observer; 1608 MainThreadOnly().rail_mode_observer = observer;
1602 } 1609 }
1603 1610
1611 bool RendererSchedulerImpl::MainThreadSeemsUnresponsive() {
1612 base::TimeTicks now = tick_clock()->NowTicks();
1613 base::TimeDelta estimated_queueing_time;
1614
1615 bool can_read = false;
1616 QueueingTimeEstimator::State queueing_time_estimator_state;
1617
1618 base::subtle::Atomic32 version;
1619 seqlock_queueing_time_estimator_.seqlock.ReadOrFail(&can_read, &version);
1620
1621 // If we fail to determine if the main thread is busy, assume whether or not
1622 // it's busy hasn't change since the last time we asked.
1623 if (!can_read)
1624 return CompositorThreadOnly().main_thread_seems_unresponsive;
1625
1626 queueing_time_estimator_state = seqlock_queueing_time_estimator_.data.state();
1627
1628 // If we fail to determine if the main thread is busy, assume whether or not
1629 // it's busy hasn't change since the last time we asked.
1630 if (seqlock_queueing_time_estimator_.seqlock.ReadRetry(version))
1631 return CompositorThreadOnly().main_thread_seems_unresponsive;
1632
1633 QueueingTimeEstimator queueing_time_estimator(queueing_time_estimator_state);
1634
1635 estimated_queueing_time =
1636 queueing_time_estimator.EstimateQueueingTimeIncludingCurrentTask(now);
1637
1638 bool main_thread_seems_unresponsive =
1639 estimated_queueing_time > main_thread_responsiveness_threshold_;
1640 CompositorThreadOnly().main_thread_seems_unresponsive =
1641 main_thread_seems_unresponsive;
1642
1643 return main_thread_seems_unresponsive;
1644 }
1645
1604 void RendererSchedulerImpl::RegisterTimeDomain(TimeDomain* time_domain) { 1646 void RendererSchedulerImpl::RegisterTimeDomain(TimeDomain* time_domain) {
1605 helper_.RegisterTimeDomain(time_domain); 1647 helper_.RegisterTimeDomain(time_domain);
1606 } 1648 }
1607 1649
1608 void RendererSchedulerImpl::UnregisterTimeDomain(TimeDomain* time_domain) { 1650 void RendererSchedulerImpl::UnregisterTimeDomain(TimeDomain* time_domain) {
1609 helper_.UnregisterTimeDomain(time_domain); 1651 helper_.UnregisterTimeDomain(time_domain);
1610 } 1652 }
1611 1653
1612 base::TickClock* RendererSchedulerImpl::tick_clock() const { 1654 base::TickClock* RendererSchedulerImpl::tick_clock() const {
1613 return helper_.scheduler_tqm_delegate().get(); 1655 return helper_.scheduler_tqm_delegate().get();
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
1658 base::AutoLock lock(any_thread_lock_); 1700 base::AutoLock lock(any_thread_lock_);
1659 if (!AnyThread().have_seen_touchstart) 1701 if (!AnyThread().have_seen_touchstart)
1660 return; 1702 return;
1661 } 1703 }
1662 MainThreadOnly().have_reported_blocking_intervention_since_navigation = 1704 MainThreadOnly().have_reported_blocking_intervention_since_navigation =
1663 true; 1705 true;
1664 BroadcastIntervention( 1706 BroadcastIntervention(
1665 "Blink deferred a task in order to make scrolling smoother. " 1707 "Blink deferred a task in order to make scrolling smoother. "
1666 "Your timer and network tasks should take less than 50ms to run " 1708 "Your timer and network tasks should take less than 50ms to run "
1667 "to avoid this. Please see " 1709 "to avoid this. Please see "
1668 "https://developers.google.com/web/tools/chrome-devtools/profile/evaluat e-performance/rail" 1710 "https://developers.google.com/web/tools/chrome-devtools/profile/"
1711 "evaluate-performance/rail"
1669 " and https://crbug.com/574343#c40 for more information."); 1712 " and https://crbug.com/574343#c40 for more information.");
1670 } 1713 }
1671 } 1714 }
1672 1715
1716 void RendererSchedulerImpl::willProcessTask(TaskQueue* task_queue,
1717 double start_time) {
1718 base::TimeTicks start_time_ticks =
1719 MonotonicTimeInSecondsToTimeTicks(start_time);
1720 MainThreadOnly().current_task_start_time = start_time_ticks;
1721 seqlock_queueing_time_estimator_.seqlock.WriteBegin();
1722 seqlock_queueing_time_estimator_.data.OnTopLevelTaskStarted(start_time_ticks);
1723 seqlock_queueing_time_estimator_.seqlock.WriteEnd();
1724 }
1725
1673 void RendererSchedulerImpl::didProcessTask(TaskQueue* task_queue, 1726 void RendererSchedulerImpl::didProcessTask(TaskQueue* task_queue,
1674 double start_time, 1727 double start_time,
1675 double end_time) { 1728 double end_time) {
1676 // TODO(scheduler-dev): Remove conversions when Blink starts using 1729 // TODO(scheduler-dev): Remove conversions when Blink starts using
1677 // base::TimeTicks instead of doubles for time. 1730 // base::TimeTicks instead of doubles for time.
1678 base::TimeTicks start_time_ticks = 1731 base::TimeTicks start_time_ticks =
1679 MonotonicTimeInSecondsToTimeTicks(start_time); 1732 MonotonicTimeInSecondsToTimeTicks(start_time);
1680 base::TimeTicks end_time_ticks = MonotonicTimeInSecondsToTimeTicks(end_time); 1733 base::TimeTicks end_time_ticks = MonotonicTimeInSecondsToTimeTicks(end_time);
1681 1734
1682 MainThreadOnly().queueing_time_estimator.OnToplevelTaskCompleted( 1735 seqlock_queueing_time_estimator_.seqlock.WriteBegin();
1683 start_time_ticks, end_time_ticks); 1736 seqlock_queueing_time_estimator_.data.OnTopLevelTaskCompleted(end_time_ticks);
1737 seqlock_queueing_time_estimator_.seqlock.WriteEnd();
1684 1738
1685 task_queue_throttler()->OnTaskRunTimeReported(task_queue, start_time_ticks, 1739 task_queue_throttler()->OnTaskRunTimeReported(task_queue, start_time_ticks,
1686 end_time_ticks); 1740 end_time_ticks);
1687 1741
1688 // We want to measure thread time here, but for efficiency reasons 1742 // We want to measure thread time here, but for efficiency reasons
1689 // we stick with wall time. 1743 // we stick with wall time.
1690 MainThreadOnly().foreground_main_thread_load_tracker.RecordTaskTime( 1744 MainThreadOnly().foreground_main_thread_load_tracker.RecordTaskTime(
1691 start_time_ticks, end_time_ticks); 1745 start_time_ticks, end_time_ticks);
1692 MainThreadOnly().background_main_thread_load_tracker.RecordTaskTime( 1746 MainThreadOnly().background_main_thread_load_tracker.RecordTaskTime(
1693 start_time_ticks, end_time_ticks); 1747 start_time_ticks, end_time_ticks);
1694 // TODO(altimin): Per-page metrics should also be considered. 1748 // TODO(altimin): Per-page metrics should also be considered.
1695 UMA_HISTOGRAM_CUSTOM_COUNTS("RendererScheduler.TaskTime", 1749 UMA_HISTOGRAM_CUSTOM_COUNTS(
1696 (end_time_ticks - start_time_ticks).InMicroseconds (), 1, 1750 "RendererScheduler.TaskTime",
1697 1000000, 50); 1751 (end_time_ticks - start_time_ticks).InMicroseconds(), 1, 1000000, 50);
1698 UMA_HISTOGRAM_ENUMERATION("RendererScheduler.NumberOfTasksPerQueueType", 1752 UMA_HISTOGRAM_ENUMERATION("RendererScheduler.NumberOfTasksPerQueueType",
1699 static_cast<int>(task_queue->GetQueueType()), 1753 static_cast<int>(task_queue->GetQueueType()),
1700 static_cast<int>(TaskQueue::QueueType::COUNT)); 1754 static_cast<int>(TaskQueue::QueueType::COUNT));
1701 } 1755 }
1702 1756
1703 void RendererSchedulerImpl::AddTaskTimeObserver( 1757 void RendererSchedulerImpl::AddTaskTimeObserver(
1704 TaskTimeObserver* task_time_observer) { 1758 TaskTimeObserver* task_time_observer) {
1705 helper_.AddTaskTimeObserver(task_time_observer); 1759 helper_.AddTaskTimeObserver(task_time_observer);
1706 } 1760 }
1707 1761
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after
1817 case TimeDomainType::VIRTUAL: 1871 case TimeDomainType::VIRTUAL:
1818 return "virtual"; 1872 return "virtual";
1819 default: 1873 default:
1820 NOTREACHED(); 1874 NOTREACHED();
1821 return nullptr; 1875 return nullptr;
1822 } 1876 }
1823 } 1877 }
1824 1878
1825 } // namespace scheduler 1879 } // namespace scheduler
1826 } // namespace blink 1880 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698