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

Unified 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 feedback. Created 4 years, 1 month 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 side-by-side diff with in-line comments
Download patch
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);

Powered by Google App Engine
This is Rietveld 408576698