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 25376e87f14eab36a4df8cfeac668a9928540ad9..9430977554e611ef4bdb6568464884859c6415fa 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 |
@@ -45,6 +45,9 @@ constexpr base::TimeDelta kThreadLoadTrackerWaitingPeriodBeforeReporting = |
// We do not throttle anything while audio is played and shortly after that. |
constexpr base::TimeDelta kThrottlingDelayAfterAudioIsPlayed = |
base::TimeDelta::FromSeconds(5); |
+// Maximum task queueing time before the main thread is considered unresponsive. |
+constexpr base::TimeDelta kMainThreadResponsivenessThreshold = |
+ base::TimeDelta::FromMilliseconds(200); |
void ReportForegroundRendererTaskLoad(base::TimeTicks time, double load) { |
int load_percentage = static_cast<int>(load * 100); |
@@ -64,8 +67,8 @@ void ReportBackgroundRendererTaskLoad(base::TimeTicks time, double load) { |
base::TimeTicks MonotonicTimeInSecondsToTimeTicks( |
double monotonicTimeInSeconds) { |
- return base::TimeTicks() + base::TimeDelta::FromSecondsD( |
- monotonicTimeInSeconds); |
+ return base::TimeTicks() + |
+ base::TimeDelta::FromSecondsD(monotonicTimeInSeconds); |
} |
} // namespace |
@@ -90,11 +93,15 @@ RendererSchedulerImpl::RendererSchedulerImpl( |
base::Bind(&RendererSchedulerImpl::UpdatePolicy, |
base::Unretained(this)), |
helper_.ControlTaskRunner()), |
+ seqlock_queueing_time_estimator_( |
+ QueueingTimeEstimator(this, base::TimeDelta::FromSeconds(1))), |
main_thread_only_(this, |
compositor_task_runner_, |
helper_.scheduler_tqm_delegate().get(), |
helper_.scheduler_tqm_delegate()->NowTicks()), |
+ any_thread_(this), |
policy_may_need_update_(&any_thread_lock_), |
+ main_thread_responsiveness_threshold_(kMainThreadResponsivenessThreshold), |
weak_factory_(this) { |
task_queue_throttler_.reset( |
new TaskQueueThrottler(this, "renderer.scheduler")); |
@@ -156,8 +163,6 @@ 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, |
@@ -197,7 +202,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), |
@@ -208,7 +214,8 @@ RendererSchedulerImpl::AnyThread::AnyThread() |
RendererSchedulerImpl::AnyThread::~AnyThread() {} |
RendererSchedulerImpl::CompositorThreadOnly::CompositorThreadOnly() |
- : last_input_type(blink::WebInputEvent::Undefined) {} |
+ : last_input_type(blink::WebInputEvent::Undefined), |
+ main_thread_seems_unresponsive(false) {} |
RendererSchedulerImpl::CompositorThreadOnly::~CompositorThreadOnly() {} |
@@ -1510,6 +1517,43 @@ void RendererSchedulerImpl::SetRAILModeObserver(RAILModeObserver* observer) { |
MainThreadOnly().rail_mode_observer = observer; |
} |
+bool RendererSchedulerImpl::MainThreadSeemsUnresponsive() { |
+ base::TimeTicks now = tick_clock()->NowTicks(); |
alex clarke (OOO till 29th)
2016/11/14 17:00:17
Is it worth adding a TRACE_EVENT here?
tdresser
2016/12/15 13:17:00
For when we're checking if the main thread is unre
|
+ base::TimeDelta estimated_queueing_time; |
+ |
+ bool can_read = false; |
+ QueueingTimeEstimator::Data queueing_time_estimator_data; |
+ |
+ 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 whether or not |
+ // it's busy hasn't change since the last time we asked. |
+ if (!can_read) |
+ return CompositorThreadOnly().main_thread_seems_unresponsive; |
+ |
+ queueing_time_estimator_data = seqlock_queueing_time_estimator_.data.data(); |
+ |
+ // If we fail to determine if the main thread is busy, assume whether or not |
+ // it's busy hasn't change since the last time we asked. |
+ if (seqlock_queueing_time_estimator_.seqlock.ReadRetry(version)) |
+ return CompositorThreadOnly().main_thread_seems_unresponsive; |
+ |
+ QueueingTimeEstimator queueing_time_estimator(queueing_time_estimator_data); |
+ |
+ estimated_queueing_time = |
+ queueing_time_estimator.EstimateQueueingTimeIncludingCurrentTask(now); |
+ |
+ bool main_thread_seems_unresponsive = |
+ estimated_queueing_time > main_thread_responsiveness_threshold_; |
+ { |
Sami
2016/11/14 21:16:45
nit: any reason for these braces? We're not grabbi
tdresser
2016/12/15 13:17:00
Done.
|
+ CompositorThreadOnly().main_thread_seems_unresponsive = |
+ main_thread_seems_unresponsive; |
+ } |
+ |
+ return main_thread_seems_unresponsive; |
+} |
+ |
void RendererSchedulerImpl::RegisterTimeDomain(TimeDomain* time_domain) { |
helper_.RegisterTimeDomain(time_domain); |
} |
@@ -1574,22 +1618,33 @@ void RendererSchedulerImpl::OnTriedToExecuteBlockedTask( |
"Blink deferred a task in order to make scrolling smoother. " |
"Your timer and network tasks should take less than 50ms to run " |
"to avoid this. Please see " |
- "https://developers.google.com/web/tools/chrome-devtools/profile/evaluate-performance/rail" |
+ "https://developers.google.com/web/tools/chrome-devtools/profile/" |
+ "evaluate-performance/rail" |
" and https://crbug.com/574343#c40 for more information."); |
} |
} |
-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; |
+ seqlock_queueing_time_estimator_.seqlock.WriteBegin(); |
+ seqlock_queueing_time_estimator_.data.OnTopLevelTaskStarted(start_time_ticks); |
+ 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( |
- start_time_ticks, end_time_ticks); |
+ seqlock_queueing_time_estimator_.seqlock.WriteBegin(); |
+ seqlock_queueing_time_estimator_.data.OnTopLevelTaskCompleted(end_time_ticks); |
+ seqlock_queueing_time_estimator_.seqlock.WriteEnd(); |
task_queue_throttler()->OnTaskRunTimeReported(task_queue, start_time_ticks, |
end_time_ticks); |
@@ -1601,9 +1656,9 @@ void RendererSchedulerImpl::ReportTaskTime(TaskQueue* task_queue, |
MainThreadOnly().background_main_thread_load_tracker.RecordTaskTime( |
start_time_ticks, end_time_ticks); |
// TODO(altimin): Per-page metrics should also be considered. |
- UMA_HISTOGRAM_CUSTOM_COUNTS("RendererScheduler.TaskTime", |
- (end_time_ticks - start_time_ticks).InMicroseconds(), 1, |
- 1000000, 50); |
+ UMA_HISTOGRAM_CUSTOM_COUNTS( |
+ "RendererScheduler.TaskTime", |
+ (end_time_ticks - start_time_ticks).InMicroseconds(), 1, 1000000, 50); |
UMA_HISTOGRAM_ENUMERATION("RendererScheduler.NumberOfTasksPerQueueType", |
static_cast<int>(task_queue->GetQueueType()), |
static_cast<int>(TaskQueue::QueueType::COUNT)); |