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); |