summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoralexclarke <alexclarke@chromium.org>2015-06-11 09:50:23 -0700
committerCommit bot <commit-bot@chromium.org>2015-06-11 16:51:04 +0000
commitc067e255c1e47962989bf411d403ca913d2caf9b (patch)
treefcf57522c0beba2b15a56a2ea7313b67dd83935b
parentd5cf758d16a434ebe0c77b817175bfcd7c8cf6fb (diff)
downloadchromium_src-c067e255c1e47962989bf411d403ca913d2caf9b.zip
chromium_src-c067e255c1e47962989bf411d403ca913d2caf9b.tar.gz
chromium_src-c067e255c1e47962989bf411d403ca913d2caf9b.tar.bz2
Introduce a loading policy to the renderer scheduler
The idea is to deprioritize compositing tasks for for 1s after a page load is detected. This has the side effect of prioritizing loading tasks. Note the signal is not wired up so this patch should have no effect by itself. BUG=497761 Review URL: https://codereview.chromium.org/1168473007 Cr-Commit-Position: refs/heads/master@{#333967}
-rw-r--r--components/scheduler/renderer/null_renderer_scheduler.cc3
-rw-r--r--components/scheduler/renderer/null_renderer_scheduler.h1
-rw-r--r--components/scheduler/renderer/renderer_scheduler.h5
-rw-r--r--components/scheduler/renderer/renderer_scheduler_impl.cc46
-rw-r--r--components/scheduler/renderer/renderer_scheduler_impl.h7
-rw-r--r--components/scheduler/renderer/renderer_scheduler_impl_unittest.cc26
-rw-r--r--content/test/fake_renderer_scheduler.cc3
-rw-r--r--content/test/fake_renderer_scheduler.h1
8 files changed, 85 insertions, 7 deletions
diff --git a/components/scheduler/renderer/null_renderer_scheduler.cc b/components/scheduler/renderer/null_renderer_scheduler.cc
index e33da0a..e5052ad 100644
--- a/components/scheduler/renderer/null_renderer_scheduler.cc
+++ b/components/scheduler/renderer/null_renderer_scheduler.cc
@@ -71,6 +71,9 @@ void NullRendererScheduler::OnRendererHidden() {
void NullRendererScheduler::OnRendererVisible() {
}
+void NullRendererScheduler::OnPageLoadStarted() {
+}
+
bool NullRendererScheduler::IsHighPriorityWorkAnticipated() {
return false;
}
diff --git a/components/scheduler/renderer/null_renderer_scheduler.h b/components/scheduler/renderer/null_renderer_scheduler.h
index 4267ffc..753bc9a 100644
--- a/components/scheduler/renderer/null_renderer_scheduler.h
+++ b/components/scheduler/renderer/null_renderer_scheduler.h
@@ -30,6 +30,7 @@ class NullRendererScheduler : public RendererScheduler {
const blink::WebInputEvent& web_input_event) override;
void OnRendererHidden() override;
void OnRendererVisible() override;
+ void OnPageLoadStarted() override;
void DidAnimateForInputOnCompositorThread() override;
bool IsHighPriorityWorkAnticipated() override;
bool ShouldYieldForHighPriorityWork() override;
diff --git a/components/scheduler/renderer/renderer_scheduler.h b/components/scheduler/renderer/renderer_scheduler.h
index 7bbe8c5..2348511 100644
--- a/components/scheduler/renderer/renderer_scheduler.h
+++ b/components/scheduler/renderer/renderer_scheduler.h
@@ -79,6 +79,11 @@ class SCHEDULER_EXPORT RendererScheduler : public ChildScheduler {
// Must be called on the main thread.
virtual void OnRendererVisible() = 0;
+ // Tells the scheduler that a page load has started. The scheduler will
+ // prioritize loading tasks for a short duration afterwards.
+ // Must be called from the main thread.
+ virtual void OnPageLoadStarted() = 0;
+
// Returns true if the scheduler has reason to believe that high priority work
// may soon arrive on the main thread, e.g., if gesture events were observed
// recently.
diff --git a/components/scheduler/renderer/renderer_scheduler_impl.cc b/components/scheduler/renderer/renderer_scheduler_impl.cc
index 1d49c3f..3b0eb9b 100644
--- a/components/scheduler/renderer/renderer_scheduler_impl.cc
+++ b/components/scheduler/renderer/renderer_scheduler_impl.cc
@@ -357,6 +357,9 @@ bool RendererSchedulerImpl::ShouldYieldForHighPriorityWork() {
case Policy::TOUCHSTART_PRIORITY:
return true;
+ case Policy::LOADING_PRIORITY:
+ return false;
+
default:
NOTREACHED();
return false;
@@ -421,6 +424,8 @@ void RendererSchedulerImpl::UpdatePolicyLocked(UpdateType update_type) {
return;
bool policy_disables_timers = false;
+ PrioritizingTaskQueueSelector::QueuePriority timer_priority =
+ PrioritizingTaskQueueSelector::NORMAL_PRIORITY;
switch (new_policy) {
case Policy::COMPOSITOR_PRIORITY:
@@ -444,6 +449,15 @@ void RendererSchedulerImpl::UpdatePolicyLocked(UpdateType update_type) {
helper_.SetQueuePriority(LOADING_TASK_QUEUE,
PrioritizingTaskQueueSelector::NORMAL_PRIORITY);
break;
+ case Policy::LOADING_PRIORITY:
+ // We prioritize loading tasks by deprioritizing compositing and timers.
+ helper_.SetQueuePriority(
+ COMPOSITOR_TASK_QUEUE,
+ PrioritizingTaskQueueSelector::BEST_EFFORT_PRIORITY);
+ timer_priority = PrioritizingTaskQueueSelector::BEST_EFFORT_PRIORITY;
+ // TODO(alexclarke): See if we can safely mark the loading task queue as
+ // high priority.
+ break;
default:
NOTREACHED();
}
@@ -451,8 +465,7 @@ void RendererSchedulerImpl::UpdatePolicyLocked(UpdateType update_type) {
policy_disables_timers) {
helper_.DisableQueue(TIMER_TASK_QUEUE);
} else {
- helper_.SetQueuePriority(TIMER_TASK_QUEUE,
- PrioritizingTaskQueueSelector::NORMAL_PRIORITY);
+ helper_.SetQueuePriority(TIMER_TASK_QUEUE, timer_priority);
}
DCHECK(helper_.IsQueueEnabled(COMPOSITOR_TASK_QUEUE));
if (new_policy != Policy::TOUCHSTART_PRIORITY)
@@ -485,14 +498,20 @@ RendererSchedulerImpl::Policy RendererSchedulerImpl::ComputeNewPolicy(
base::TimeTicks now,
base::TimeDelta* new_policy_duration) const {
any_thread_lock_.AssertAcquired();
+ // Above all else we want to be responsive to user input.
*new_policy_duration = TimeLeftInInputEscalatedPolicy(now);
+ if (*new_policy_duration > base::TimeDelta()) {
+ return AnyThread().awaiting_touch_start_response_
+ ? Policy::TOUCHSTART_PRIORITY
+ : Policy::COMPOSITOR_PRIORITY;
+ }
- if (*new_policy_duration == base::TimeDelta())
- return Policy::NORMAL;
+ if (AnyThread().rails_loading_priority_deadline_ > now) {
+ *new_policy_duration = AnyThread().rails_loading_priority_deadline_ - now;
+ return Policy::LOADING_PRIORITY;
+ }
- return AnyThread().awaiting_touch_start_response_
- ? Policy::TOUCHSTART_PRIORITY
- : Policy::COMPOSITOR_PRIORITY;
+ return Policy::NORMAL;
}
base::TimeDelta RendererSchedulerImpl::TimeLeftInInputEscalatedPolicy(
@@ -572,6 +591,8 @@ const char* RendererSchedulerImpl::PolicyToString(Policy policy) {
return "compositor";
case Policy::TOUCHSTART_PRIORITY:
return "touchstart";
+ case Policy::LOADING_PRIORITY:
+ return "loading";
default:
NOTREACHED();
return nullptr;
@@ -604,6 +625,9 @@ RendererSchedulerImpl::AsValueLocked(base::TimeTicks optional_now) const {
state->SetDouble("last_input_signal_time",
(AnyThread().last_input_signal_time_ - base::TimeTicks())
.InMillisecondsF());
+ state->SetDouble("rails_loading_priority_deadline",
+ (AnyThread().rails_loading_priority_deadline_ -
+ base::TimeTicks()).InMillisecondsF());
state->SetInteger("pending_main_thread_input_event_count",
AnyThread().pending_main_thread_input_event_count_);
state->SetBoolean("awaiting_touch_start_response",
@@ -628,4 +652,12 @@ void RendererSchedulerImpl::OnIdlePeriodEnded() {
// TODO(alexclarke): Force update the policy
}
+void RendererSchedulerImpl::OnPageLoadStarted() {
+ base::AutoLock lock(any_thread_lock_);
+ AnyThread().rails_loading_priority_deadline_ =
+ helper_.Now() + base::TimeDelta::FromMilliseconds(
+ kRailsInitialLoadingPrioritizationMillis);
+ UpdatePolicyLocked(UpdateType::MAY_EARLY_OUT_IF_POLICY_UNCHANGED);
+}
+
} // namespace scheduler
diff --git a/components/scheduler/renderer/renderer_scheduler_impl.h b/components/scheduler/renderer/renderer_scheduler_impl.h
index 7eb6ab6..42cdf11 100644
--- a/components/scheduler/renderer/renderer_scheduler_impl.h
+++ b/components/scheduler/renderer/renderer_scheduler_impl.h
@@ -46,6 +46,7 @@ class SCHEDULER_EXPORT RendererSchedulerImpl : public RendererScheduler,
void DidAnimateForInputOnCompositorThread() override;
void OnRendererHidden() override;
void OnRendererVisible() override;
+ void OnPageLoadStarted() override;
bool IsHighPriorityWorkAnticipated() override;
bool ShouldYieldForHighPriorityWork() override;
bool CanExceedIdleDeadlineIfRequired() const override;
@@ -79,6 +80,7 @@ class SCHEDULER_EXPORT RendererSchedulerImpl : public RendererScheduler,
NORMAL,
COMPOSITOR_PRIORITY,
TOUCHSTART_PRIORITY,
+ LOADING_PRIORITY,
// Must be the last entry.
POLICY_COUNT,
FIRST_POLICY = NORMAL,
@@ -130,6 +132,10 @@ class SCHEDULER_EXPORT RendererSchedulerImpl : public RendererScheduler,
// renderer has been hidden, before going to sleep for good.
static const int kEndIdleWhenHiddenDelayMillis = 10000;
+ // The amount of time for which loading tasks will be prioritized over
+ // other tasks during the initial page load.
+ static const int kRailsInitialLoadingPrioritizationMillis = 1000;
+
// Schedules an immediate PolicyUpdate, if there isn't one already pending and
// sets |policy_may_need_update_|. Note |any_thread_lock_| must be
// locked.
@@ -207,6 +213,7 @@ class SCHEDULER_EXPORT RendererSchedulerImpl : public RendererScheduler,
AnyThread();
base::TimeTicks last_input_signal_time_;
+ base::TimeTicks rails_loading_priority_deadline_;
int pending_main_thread_input_event_count_;
bool awaiting_touch_start_response_;
};
diff --git a/components/scheduler/renderer/renderer_scheduler_impl_unittest.cc b/components/scheduler/renderer/renderer_scheduler_impl_unittest.cc
index 3090cdf..e6c4b56 100644
--- a/components/scheduler/renderer/renderer_scheduler_impl_unittest.cc
+++ b/components/scheduler/renderer/renderer_scheduler_impl_unittest.cc
@@ -698,6 +698,32 @@ TEST_F(RendererSchedulerImplTest, TestTouchstartPolicy_MainThread) {
std::string("L1")));
}
+TEST_F(RendererSchedulerImplTest, LoadingPriorityPolicy) {
+ std::vector<std::string> run_order;
+ PostTestTasks(&run_order, "L1 I1 D1 C1 D2 C2");
+
+ scheduler_->OnPageLoadStarted();
+ EnableIdleTasks();
+ RunUntilIdle();
+ // In loading policy compositor tasks are best effort and should be run last.
+ EXPECT_THAT(run_order,
+ testing::ElementsAre(std::string("L1"), std::string("D1"),
+ std::string("D2"), std::string("I1"),
+ std::string("C1"), std::string("C2")));
+
+ // Advance 1.5s and try again, the loading policy should have ended and the
+ // task order should return to normal.
+ clock_->AdvanceNow(base::TimeDelta::FromMilliseconds(1500));
+ run_order.clear();
+ PostTestTasks(&run_order, "L1 I1 D1 C1 D2 C2");
+ EnableIdleTasks();
+ RunUntilIdle();
+ EXPECT_THAT(run_order,
+ testing::ElementsAre(std::string("L1"), std::string("D1"),
+ std::string("C1"), std::string("D2"),
+ std::string("C2"), std::string("I1")));
+}
+
TEST_F(RendererSchedulerImplTest,
EventConsumedOnCompositorThread_IgnoresMouseMove_WhenMouseUp) {
std::vector<std::string> run_order;
diff --git a/content/test/fake_renderer_scheduler.cc b/content/test/fake_renderer_scheduler.cc
index cc21750..2a3fe40 100644
--- a/content/test/fake_renderer_scheduler.cc
+++ b/content/test/fake_renderer_scheduler.cc
@@ -68,6 +68,9 @@ void FakeRendererScheduler::OnRendererHidden() {
void FakeRendererScheduler::OnRendererVisible() {
}
+void FakeRendererScheduler::OnPageLoadStarted() {
+}
+
bool FakeRendererScheduler::ShouldYieldForHighPriorityWork() {
return false;
}
diff --git a/content/test/fake_renderer_scheduler.h b/content/test/fake_renderer_scheduler.h
index a57e0f9..b408276 100644
--- a/content/test/fake_renderer_scheduler.h
+++ b/content/test/fake_renderer_scheduler.h
@@ -32,6 +32,7 @@ class FakeRendererScheduler : public scheduler::RendererScheduler {
void DidAnimateForInputOnCompositorThread() override;
void OnRendererHidden() override;
void OnRendererVisible() override;
+ void OnPageLoadStarted() override;
bool IsHighPriorityWorkAnticipated() override;
bool CanExceedIdleDeadlineIfRequired() const override;
bool ShouldYieldForHighPriorityWork() override;