Chromium Code Reviews| Index: third_party/WebKit/Source/platform/scheduler/renderer/renderer_scheduler_impl.cc |
| diff --git a/third_party/WebKit/Source/platform/scheduler/renderer/renderer_scheduler_impl.cc b/third_party/WebKit/Source/platform/scheduler/renderer/renderer_scheduler_impl.cc |
| index 339bf45dcff2daeeca6f62def37bf3a84587eb69..3354a119cb69085694b46378ae52b85f007b05dd 100644 |
| --- a/third_party/WebKit/Source/platform/scheduler/renderer/renderer_scheduler_impl.cc |
| +++ b/third_party/WebKit/Source/platform/scheduler/renderer/renderer_scheduler_impl.cc |
| @@ -42,6 +42,10 @@ constexpr base::TimeDelta kThreadLoadTrackerReportingInterval = |
| constexpr base::TimeDelta kThreadLoadTrackerWaitingPeriodBeforeReporting = |
| base::TimeDelta::FromMinutes(2); |
| +// Maximum task queueing time before the main thread is considered unresponsive. |
| +constexpr base::TimeDelta kMainThreadUnresponsiveQueueingTime = |
| + base::TimeDelta::FromMilliseconds(200); |
| + |
| void ReportForegroundRendererTaskLoad(base::TimeTicks time, double load) { |
| int load_percentage = static_cast<int>(load * 100); |
| UMA_HISTOGRAM_PERCENTAGE("RendererScheduler.ForegroundRendererMainThreadLoad", |
| @@ -90,6 +94,7 @@ RendererSchedulerImpl::RendererSchedulerImpl( |
| compositor_task_runner_, |
| helper_.scheduler_tqm_delegate().get(), |
| helper_.scheduler_tqm_delegate()->NowTicks()), |
| + any_thread_(this), |
| policy_may_need_update_(&any_thread_lock_), |
| weak_factory_(this) { |
| task_queue_throttler_.reset( |
| @@ -152,12 +157,12 @@ RendererSchedulerImpl::MainThreadOnly::MainThreadOnly( |
| timer_task_cost_estimator(time_source, |
| kTimerTaskEstimationSampleCount, |
| kTimerTaskEstimationPercentile), |
| - queueing_time_estimator(renderer_scheduler_impl, |
| - base::TimeDelta::FromSeconds(1)), |
| idle_time_estimator(compositor_task_runner, |
| time_source, |
| kShortIdlePeriodDurationSampleCount, |
| kShortIdlePeriodDurationPercentile), |
| + queueing_time_estimator(renderer_scheduler_impl, |
| + base::TimeDelta::FromSeconds(1)), |
| background_main_thread_load_tracker( |
| now, |
| base::Bind(&ReportBackgroundRendererTaskLoad), |
| @@ -192,7 +197,8 @@ RendererSchedulerImpl::MainThreadOnly::MainThreadOnly( |
| RendererSchedulerImpl::MainThreadOnly::~MainThreadOnly() {} |
| -RendererSchedulerImpl::AnyThread::AnyThread() |
| +RendererSchedulerImpl::AnyThread::AnyThread( |
| + RendererSchedulerImpl* renderer_scheduler_impl) |
| : awaiting_touch_start_response(false), |
| in_idle_period(false), |
| begin_main_frame_on_critical_path(false), |
| @@ -1437,6 +1443,36 @@ void RendererSchedulerImpl::SetRAILModeObserver(RAILModeObserver* observer) { |
| MainThreadOnly().rail_mode_observer = observer; |
| } |
| +bool RendererSchedulerImpl::MainThreadSeemsUnresponsive() const { |
| + base::TimeTicks now = base::TimeTicks::Now(); |
| + base::TimeDelta estimated_queueing_time; |
| + |
| + bool can_read = false; |
| + QueueingTimeEstimator::SerializedQueueingTimeEstimator |
| + serialized_queueing_time_estimator; |
| + |
| + base::subtle::Atomic32 version; |
| + seqlock_queueing_time_estimator_.seqlock.ReadOrFail(&can_read, &version); |
| + |
| + // If we fail to determine if the main thread is busy, assume it isn't. |
| + if (!can_read) |
| + 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
|
| + |
| + serialized_queueing_time_estimator = seqlock_queueing_time_estimator_.data; |
| + |
| + // If we fail to determine if the main thread is busy, assume it isn't. |
| + if (seqlock_queueing_time_estimator_.seqlock.ReadRetry(version)) |
| + return false; |
| + |
| + QueueingTimeEstimator queueing_time_estimator( |
| + serialized_queueing_time_estimator); |
| + |
| + estimated_queueing_time = |
| + queueing_time_estimator.EstimateQueueingTimeIncludingCurrentTask(now); |
| + |
| + return estimated_queueing_time > kMainThreadUnresponsiveQueueingTime; |
| +} |
| + |
| void RendererSchedulerImpl::RegisterTimeDomain(TimeDomain* time_domain) { |
| helper_.RegisterTimeDomain(time_domain); |
| } |
| @@ -1506,17 +1542,40 @@ void RendererSchedulerImpl::OnTriedToExecuteBlockedTask( |
| } |
| } |
| -void RendererSchedulerImpl::ReportTaskTime(TaskQueue* task_queue, |
| - double start_time, |
| - double end_time) { |
| +void RendererSchedulerImpl::ReportTaskStartTime(double start_time) { |
| + base::TimeTicks start_time_ticks = |
| + MonotonicTimeInSecondsToTimeTicks(start_time); |
| + MainThreadOnly().current_task_start_time = start_time_ticks; |
| + MainThreadOnly().queueing_time_estimator.OnTopLevelTaskStarted( |
| + start_time_ticks); |
| + |
| + QueueingTimeEstimator::SerializedQueueingTimeEstimator |
| + serialized_queueing_time_estimator = |
| + MainThreadOnly().queueing_time_estimator.Serialize(); |
| + |
| + seqlock_queueing_time_estimator_.seqlock.WriteBegin(); |
| + seqlock_queueing_time_estimator_.data = serialized_queueing_time_estimator; |
| + seqlock_queueing_time_estimator_.seqlock.WriteEnd(); |
| +} |
| + |
| +void RendererSchedulerImpl::ReportTaskEndTime(TaskQueue* task_queue, |
| + double start_time, |
| + double end_time) { |
| // TODO(scheduler-dev): Remove conversions when Blink starts using |
| // base::TimeTicks instead of doubles for time. |
| base::TimeTicks start_time_ticks = |
| MonotonicTimeInSecondsToTimeTicks(start_time); |
| base::TimeTicks end_time_ticks = MonotonicTimeInSecondsToTimeTicks(end_time); |
| + MainThreadOnly().queueing_time_estimator.OnTopLevelTaskCompleted( |
| + end_time_ticks); |
| - MainThreadOnly().queueing_time_estimator.OnToplevelTaskCompleted( |
| - start_time_ticks, end_time_ticks); |
| + QueueingTimeEstimator::SerializedQueueingTimeEstimator |
| + serialized_queueing_time_estimator = |
| + MainThreadOnly().queueing_time_estimator.Serialize(); |
| + |
| + 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
|
| + seqlock_queueing_time_estimator_.data = serialized_queueing_time_estimator; |
| + seqlock_queueing_time_estimator_.seqlock.WriteEnd(); |
| task_queue_throttler()->OnTaskRunTimeReported(task_queue, start_time_ticks, |
| end_time_ticks); |