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

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: 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()),
108 policy_may_need_update_(&any_thread_lock_), 113 policy_may_need_update_(&any_thread_lock_),
114 main_thread_responsiveness_threshold_(kMainThreadResponsivenessThreshold),
109 weak_factory_(this) { 115 weak_factory_(this) {
110 task_queue_throttler_.reset( 116 task_queue_throttler_.reset(
111 new TaskQueueThrottler(this, "renderer.scheduler")); 117 new TaskQueueThrottler(this, "renderer.scheduler"));
112 update_policy_closure_ = base::Bind(&RendererSchedulerImpl::UpdatePolicy, 118 update_policy_closure_ = base::Bind(&RendererSchedulerImpl::UpdatePolicy,
113 weak_factory_.GetWeakPtr()); 119 weak_factory_.GetWeakPtr());
114 end_renderer_hidden_idle_period_closure_.Reset(base::Bind( 120 end_renderer_hidden_idle_period_closure_.Reset(base::Bind(
115 &RendererSchedulerImpl::EndIdlePeriod, weak_factory_.GetWeakPtr())); 121 &RendererSchedulerImpl::EndIdlePeriod, weak_factory_.GetWeakPtr()));
116 122
117 suspend_timers_when_backgrounded_closure_.Reset( 123 suspend_timers_when_backgrounded_closure_.Reset(
118 base::Bind(&RendererSchedulerImpl::SuspendTimerQueueWhenBackgrounded, 124 base::Bind(&RendererSchedulerImpl::SuspendTimerQueueWhenBackgrounded,
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
169 RendererSchedulerImpl* renderer_scheduler_impl, 175 RendererSchedulerImpl* renderer_scheduler_impl,
170 const scoped_refptr<TaskQueue>& compositor_task_runner, 176 const scoped_refptr<TaskQueue>& compositor_task_runner,
171 base::TickClock* time_source, 177 base::TickClock* time_source,
172 base::TimeTicks now) 178 base::TimeTicks now)
173 : loading_task_cost_estimator(time_source, 179 : loading_task_cost_estimator(time_source,
174 kLoadingTaskEstimationSampleCount, 180 kLoadingTaskEstimationSampleCount,
175 kLoadingTaskEstimationPercentile), 181 kLoadingTaskEstimationPercentile),
176 timer_task_cost_estimator(time_source, 182 timer_task_cost_estimator(time_source,
177 kTimerTaskEstimationSampleCount, 183 kTimerTaskEstimationSampleCount,
178 kTimerTaskEstimationPercentile), 184 kTimerTaskEstimationPercentile),
179 queueing_time_estimator(renderer_scheduler_impl,
180 base::TimeDelta::FromSeconds(1)),
181 idle_time_estimator(compositor_task_runner, 185 idle_time_estimator(compositor_task_runner,
182 time_source, 186 time_source,
183 kShortIdlePeriodDurationSampleCount, 187 kShortIdlePeriodDurationSampleCount,
184 kShortIdlePeriodDurationPercentile), 188 kShortIdlePeriodDurationPercentile),
185 background_main_thread_load_tracker( 189 background_main_thread_load_tracker(
186 now, 190 now,
187 base::Bind(&ReportBackgroundRendererTaskLoad), 191 base::Bind(&ReportBackgroundRendererTaskLoad),
188 kThreadLoadTrackerReportingInterval, 192 kThreadLoadTrackerReportingInterval,
189 kThreadLoadTrackerWaitingPeriodBeforeReporting), 193 kThreadLoadTrackerWaitingPeriodBeforeReporting),
190 foreground_main_thread_load_tracker( 194 foreground_main_thread_load_tracker(
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
223 begin_main_frame_on_critical_path(false), 227 begin_main_frame_on_critical_path(false),
224 last_gesture_was_compositor_driven(false), 228 last_gesture_was_compositor_driven(false),
225 default_gesture_prevented(true), 229 default_gesture_prevented(true),
226 have_seen_touchstart(false), 230 have_seen_touchstart(false),
227 waiting_for_meaningful_paint(false), 231 waiting_for_meaningful_paint(false),
228 have_seen_input_since_navigation(false) {} 232 have_seen_input_since_navigation(false) {}
229 233
230 RendererSchedulerImpl::AnyThread::~AnyThread() {} 234 RendererSchedulerImpl::AnyThread::~AnyThread() {}
231 235
232 RendererSchedulerImpl::CompositorThreadOnly::CompositorThreadOnly() 236 RendererSchedulerImpl::CompositorThreadOnly::CompositorThreadOnly()
233 : last_input_type(blink::WebInputEvent::Undefined) {} 237 : last_input_type(blink::WebInputEvent::Undefined),
238 main_thread_seems_unresponsive(false) {}
234 239
235 RendererSchedulerImpl::CompositorThreadOnly::~CompositorThreadOnly() {} 240 RendererSchedulerImpl::CompositorThreadOnly::~CompositorThreadOnly() {}
236 241
237 void RendererSchedulerImpl::Shutdown() { 242 void RendererSchedulerImpl::Shutdown() {
238 base::TimeTicks now = tick_clock()->NowTicks(); 243 base::TimeTicks now = tick_clock()->NowTicks();
239 MainThreadOnly().background_main_thread_load_tracker.RecordIdle(now); 244 MainThreadOnly().background_main_thread_load_tracker.RecordIdle(now);
240 MainThreadOnly().foreground_main_thread_load_tracker.RecordIdle(now); 245 MainThreadOnly().foreground_main_thread_load_tracker.RecordIdle(now);
241 246
242 task_queue_throttler_.reset(); 247 task_queue_throttler_.reset();
243 helper_.Shutdown(); 248 helper_.Shutdown();
(...skipping 1350 matching lines...) Expand 10 before | Expand all | Expand 10 after
1594 default_loading_task_runner_->SetBlameContext(blame_context); 1599 default_loading_task_runner_->SetBlameContext(blame_context);
1595 default_timer_task_runner_->SetBlameContext(blame_context); 1600 default_timer_task_runner_->SetBlameContext(blame_context);
1596 compositor_task_runner_->SetBlameContext(blame_context); 1601 compositor_task_runner_->SetBlameContext(blame_context);
1597 idle_helper_.IdleTaskRunner()->SetBlameContext(blame_context); 1602 idle_helper_.IdleTaskRunner()->SetBlameContext(blame_context);
1598 } 1603 }
1599 1604
1600 void RendererSchedulerImpl::SetRAILModeObserver(RAILModeObserver* observer) { 1605 void RendererSchedulerImpl::SetRAILModeObserver(RAILModeObserver* observer) {
1601 MainThreadOnly().rail_mode_observer = observer; 1606 MainThreadOnly().rail_mode_observer = observer;
1602 } 1607 }
1603 1608
1609 bool RendererSchedulerImpl::MainThreadSeemsUnresponsive() {
1610 base::TimeTicks now = tick_clock()->NowTicks();
1611 base::TimeDelta estimated_queueing_time;
1612
1613 bool can_read = false;
1614 QueueingTimeEstimator::State queueing_time_estimator_state;
1615
1616 base::subtle::Atomic32 version;
1617 seqlock_queueing_time_estimator_.seqlock.ReadOrFail(&can_read, &version);
1618
1619 // If we fail to determine if the main thread is busy, assume whether or not
1620 // it's busy hasn't change since the last time we asked.
1621 if (!can_read)
1622 return CompositorThreadOnly().main_thread_seems_unresponsive;
1623
1624 queueing_time_estimator_state = seqlock_queueing_time_estimator_.data.state();
1625
1626 // If we fail to determine if the main thread is busy, assume whether or not
1627 // it's busy hasn't change since the last time we asked.
1628 if (seqlock_queueing_time_estimator_.seqlock.ReadRetry(version))
1629 return CompositorThreadOnly().main_thread_seems_unresponsive;
1630
1631 QueueingTimeEstimator queueing_time_estimator(queueing_time_estimator_state);
1632
1633 estimated_queueing_time =
1634 queueing_time_estimator.EstimateQueueingTimeIncludingCurrentTask(now);
1635
1636 bool main_thread_seems_unresponsive =
1637 estimated_queueing_time > main_thread_responsiveness_threshold_;
1638 CompositorThreadOnly().main_thread_seems_unresponsive =
1639 main_thread_seems_unresponsive;
1640
1641 return main_thread_seems_unresponsive;
1642 }
1643
1604 void RendererSchedulerImpl::RegisterTimeDomain(TimeDomain* time_domain) { 1644 void RendererSchedulerImpl::RegisterTimeDomain(TimeDomain* time_domain) {
1605 helper_.RegisterTimeDomain(time_domain); 1645 helper_.RegisterTimeDomain(time_domain);
1606 } 1646 }
1607 1647
1608 void RendererSchedulerImpl::UnregisterTimeDomain(TimeDomain* time_domain) { 1648 void RendererSchedulerImpl::UnregisterTimeDomain(TimeDomain* time_domain) {
1609 helper_.UnregisterTimeDomain(time_domain); 1649 helper_.UnregisterTimeDomain(time_domain);
1610 } 1650 }
1611 1651
1612 base::TickClock* RendererSchedulerImpl::tick_clock() const { 1652 base::TickClock* RendererSchedulerImpl::tick_clock() const {
1613 return helper_.scheduler_tqm_delegate().get(); 1653 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_); 1698 base::AutoLock lock(any_thread_lock_);
1659 if (!AnyThread().have_seen_touchstart) 1699 if (!AnyThread().have_seen_touchstart)
1660 return; 1700 return;
1661 } 1701 }
1662 MainThreadOnly().have_reported_blocking_intervention_since_navigation = 1702 MainThreadOnly().have_reported_blocking_intervention_since_navigation =
1663 true; 1703 true;
1664 BroadcastIntervention( 1704 BroadcastIntervention(
1665 "Blink deferred a task in order to make scrolling smoother. " 1705 "Blink deferred a task in order to make scrolling smoother. "
1666 "Your timer and network tasks should take less than 50ms to run " 1706 "Your timer and network tasks should take less than 50ms to run "
1667 "to avoid this. Please see " 1707 "to avoid this. Please see "
1668 "https://developers.google.com/web/tools/chrome-devtools/profile/evaluat e-performance/rail" 1708 "https://developers.google.com/web/tools/chrome-devtools/profile/"
1709 "evaluate-performance/rail"
1669 " and https://crbug.com/574343#c40 for more information."); 1710 " and https://crbug.com/574343#c40 for more information.");
1670 } 1711 }
1671 } 1712 }
1672 1713
1714 void RendererSchedulerImpl::willProcessTask(TaskQueue* task_queue,
1715 double start_time) {
1716 base::TimeTicks start_time_ticks =
1717 MonotonicTimeInSecondsToTimeTicks(start_time);
1718 MainThreadOnly().current_task_start_time = start_time_ticks;
1719 seqlock_queueing_time_estimator_.seqlock.WriteBegin();
1720 seqlock_queueing_time_estimator_.data.OnTopLevelTaskStarted(start_time_ticks);
1721 seqlock_queueing_time_estimator_.seqlock.WriteEnd();
1722 }
1723
1673 void RendererSchedulerImpl::didProcessTask(TaskQueue* task_queue, 1724 void RendererSchedulerImpl::didProcessTask(TaskQueue* task_queue,
1674 double start_time, 1725 double start_time,
1675 double end_time) { 1726 double end_time) {
1676 // TODO(scheduler-dev): Remove conversions when Blink starts using 1727 // TODO(scheduler-dev): Remove conversions when Blink starts using
1677 // base::TimeTicks instead of doubles for time. 1728 // base::TimeTicks instead of doubles for time.
1678 base::TimeTicks start_time_ticks = 1729 base::TimeTicks start_time_ticks =
1679 MonotonicTimeInSecondsToTimeTicks(start_time); 1730 MonotonicTimeInSecondsToTimeTicks(start_time);
1680 base::TimeTicks end_time_ticks = MonotonicTimeInSecondsToTimeTicks(end_time); 1731 base::TimeTicks end_time_ticks = MonotonicTimeInSecondsToTimeTicks(end_time);
1681 1732
1682 MainThreadOnly().queueing_time_estimator.OnToplevelTaskCompleted( 1733 seqlock_queueing_time_estimator_.seqlock.WriteBegin();
1683 start_time_ticks, end_time_ticks); 1734 seqlock_queueing_time_estimator_.data.OnTopLevelTaskCompleted(end_time_ticks);
1735 seqlock_queueing_time_estimator_.seqlock.WriteEnd();
1684 1736
1685 task_queue_throttler()->OnTaskRunTimeReported(task_queue, start_time_ticks, 1737 task_queue_throttler()->OnTaskRunTimeReported(task_queue, start_time_ticks,
1686 end_time_ticks); 1738 end_time_ticks);
1687 1739
1688 // We want to measure thread time here, but for efficiency reasons 1740 // We want to measure thread time here, but for efficiency reasons
1689 // we stick with wall time. 1741 // we stick with wall time.
1690 MainThreadOnly().foreground_main_thread_load_tracker.RecordTaskTime( 1742 MainThreadOnly().foreground_main_thread_load_tracker.RecordTaskTime(
1691 start_time_ticks, end_time_ticks); 1743 start_time_ticks, end_time_ticks);
1692 MainThreadOnly().background_main_thread_load_tracker.RecordTaskTime( 1744 MainThreadOnly().background_main_thread_load_tracker.RecordTaskTime(
1693 start_time_ticks, end_time_ticks); 1745 start_time_ticks, end_time_ticks);
1694 // TODO(altimin): Per-page metrics should also be considered. 1746 // TODO(altimin): Per-page metrics should also be considered.
1695 UMA_HISTOGRAM_CUSTOM_COUNTS("RendererScheduler.TaskTime", 1747 UMA_HISTOGRAM_CUSTOM_COUNTS(
1696 (end_time_ticks - start_time_ticks).InMicroseconds (), 1, 1748 "RendererScheduler.TaskTime",
1697 1000000, 50); 1749 (end_time_ticks - start_time_ticks).InMicroseconds(), 1, 1000000, 50);
1698 UMA_HISTOGRAM_ENUMERATION("RendererScheduler.NumberOfTasksPerQueueType", 1750 UMA_HISTOGRAM_ENUMERATION("RendererScheduler.NumberOfTasksPerQueueType",
1699 static_cast<int>(task_queue->GetQueueType()), 1751 static_cast<int>(task_queue->GetQueueType()),
1700 static_cast<int>(TaskQueue::QueueType::COUNT)); 1752 static_cast<int>(TaskQueue::QueueType::COUNT));
1701 } 1753 }
1702 1754
1703 void RendererSchedulerImpl::AddTaskTimeObserver( 1755 void RendererSchedulerImpl::AddTaskTimeObserver(
1704 TaskTimeObserver* task_time_observer) { 1756 TaskTimeObserver* task_time_observer) {
1705 helper_.AddTaskTimeObserver(task_time_observer); 1757 helper_.AddTaskTimeObserver(task_time_observer);
1706 } 1758 }
1707 1759
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after
1817 case TimeDomainType::VIRTUAL: 1869 case TimeDomainType::VIRTUAL:
1818 return "virtual"; 1870 return "virtual";
1819 default: 1871 default:
1820 NOTREACHED(); 1872 NOTREACHED();
1821 return nullptr; 1873 return nullptr;
1822 } 1874 }
1823 } 1875 }
1824 1876
1825 } // namespace scheduler 1877 } // namespace scheduler
1826 } // namespace blink 1878 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698