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

Unified Diff: components/scheduler/renderer/renderer_scheduler_impl_unittest.cc

Issue 1320633002: Optimize for TouchStart responsiveness (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebase + remove some unwanted changes Created 5 years, 4 months 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: components/scheduler/renderer/renderer_scheduler_impl_unittest.cc
diff --git a/components/scheduler/renderer/renderer_scheduler_impl_unittest.cc b/components/scheduler/renderer/renderer_scheduler_impl_unittest.cc
index c651486d18c9315d3783c1992daac11d200eeaa6..8538896ba2ca06770780dbd6ef7fa6ab7ccfbe46 100644
--- a/components/scheduler/renderer/renderer_scheduler_impl_unittest.cc
+++ b/components/scheduler/renderer/renderer_scheduler_impl_unittest.cc
@@ -126,15 +126,28 @@ void PostingYieldingTestTask(RendererSchedulerImpl* scheduler,
*should_yield_after = scheduler->ShouldYieldForHighPriorityWork();
}
+enum class SimulateInputType { None, TouchStart, TouchEnd };
+
void AnticipationTestTask(RendererSchedulerImpl* scheduler,
- bool simulate_input,
+ SimulateInputType simulate_input,
bool* is_anticipated_before,
bool* is_anticipated_after) {
*is_anticipated_before = scheduler->IsHighPriorityWorkAnticipated();
- if (simulate_input) {
- scheduler->DidHandleInputEventOnCompositorThread(
- FakeInputEvent(blink::WebInputEvent::GestureFlingStart),
- RendererScheduler::InputEventState::EVENT_CONSUMED_BY_COMPOSITOR);
+ switch (simulate_input) {
+ case SimulateInputType::None:
+ break;
+
+ case SimulateInputType::TouchStart:
+ scheduler->DidHandleInputEventOnCompositorThread(
+ FakeInputEvent(blink::WebInputEvent::TouchStart),
+ RendererScheduler::InputEventState::EVENT_CONSUMED_BY_COMPOSITOR);
+ break;
+
+ case SimulateInputType::TouchEnd:
+ scheduler->DidHandleInputEventOnCompositorThread(
+ FakeInputEvent(blink::WebInputEvent::TouchEnd),
+ RendererScheduler::InputEventState::EVENT_CONSUMED_BY_COMPOSITOR);
+ break;
}
*is_anticipated_after = scheduler->IsHighPriorityWorkAnticipated();
}
@@ -145,8 +158,8 @@ class RendererSchedulerImplForTest : public RendererSchedulerImpl {
public:
using RendererSchedulerImpl::OnIdlePeriodEnded;
using RendererSchedulerImpl::OnIdlePeriodStarted;
- using RendererSchedulerImpl::Policy;
- using RendererSchedulerImpl::PolicyToString;
+ using RendererSchedulerImpl::UseCase;
+ using RendererSchedulerImpl::UseCaseToString;
RendererSchedulerImplForTest(
scoped_refptr<SchedulerTaskRunnerDelegate> main_task_runner)
@@ -155,6 +168,14 @@ class RendererSchedulerImplForTest : public RendererSchedulerImpl {
void UpdatePolicyLocked(UpdateType update_type) override {
update_policy_count_++;
RendererSchedulerImpl::UpdatePolicyLocked(update_type);
+
+ std::string use_case = RendererSchedulerImplForTest::UseCaseToString(
+ MainThreadOnly().current_use_case_);
+ if (MainThreadOnly().scroll_expected_soon_) {
+ use_cases_.push_back(use_case + " scroll expected");
+ } else {
+ use_cases_.push_back(use_case);
+ }
}
void EnsureUrgentPolicyUpdatePostedOnMainThread() {
@@ -173,17 +194,19 @@ class RendererSchedulerImplForTest : public RendererSchedulerImpl {
}
int update_policy_count_;
+ std::vector<std::string> use_cases_;
};
// Lets gtest print human readable Policy values.
-::std::ostream& operator<<(::std::ostream& os,
- const RendererSchedulerImplForTest::Policy& policy) {
- return os << RendererSchedulerImplForTest::PolicyToString(policy);
+::std::ostream& operator<<(
+ ::std::ostream& os,
+ const RendererSchedulerImplForTest::UseCase& use_case) {
+ return os << RendererSchedulerImplForTest::UseCaseToString(use_case);
}
class RendererSchedulerImplTest : public testing::Test {
public:
- using Policy = RendererSchedulerImpl::Policy;
+ using UseCase = RendererSchedulerImpl::UseCase;
RendererSchedulerImplTest() : clock_(new base::SimpleTestTickClock()) {
clock_->Advance(base::TimeDelta::FromMicroseconds(5000));
@@ -255,10 +278,27 @@ class RendererSchedulerImplTest : public testing::Test {
scheduler_->DidCommitFrameToCompositor();
}
+ void ForceMainthreadScrollingUseCase() {
+ cc::BeginFrameArgs begin_frame_args = cc::BeginFrameArgs::Create(
+ BEGINFRAME_FROM_HERE, clock_->NowTicks(), base::TimeTicks(),
+ base::TimeDelta::FromMilliseconds(1000), cc::BeginFrameArgs::NORMAL);
+ begin_frame_args.on_critical_path = true;
+ scheduler_->WillBeginFrame(begin_frame_args);
+ }
+
void EnableIdleTasks() { DoMainFrame(); }
- Policy CurrentPolicy() {
- return scheduler_->MainThreadOnly().current_policy_;
+ UseCase CurrentUseCase() {
+ return scheduler_->MainThreadOnly().current_use_case_;
+ }
+
+ UseCase ForceUpdatePolicyAndGetCurrentUseCase() {
+ scheduler_->ForceUpdatePolicy();
+ return scheduler_->MainThreadOnly().current_use_case_;
+ }
+
+ bool ScrollExpectedSoon() {
+ return scheduler_->MainThreadOnly().scroll_expected_soon_;
}
// Helper for posting several tasks of specific types. |task_descriptor| is a
@@ -309,6 +349,11 @@ class RendererSchedulerImplTest : public testing::Test {
RendererSchedulerImpl::kPriorityEscalationAfterInputMillis);
}
+ static base::TimeDelta subsequent_input_expected_after_input_duration() {
+ return base::TimeDelta::FromMilliseconds(
+ RendererSchedulerImpl::kExpectSubsequentInputMillis);
+ }
+
static base::TimeDelta maximum_idle_period_duration() {
return base::TimeDelta::FromMilliseconds(
IdleHelper::kMaximumIdlePeriodMillis);
@@ -334,11 +379,11 @@ class RendererSchedulerImplTest : public testing::Test {
}
}
- static void CheckAllPolicyToString() {
- CallForEachEnumValue<RendererSchedulerImpl::Policy>(
- RendererSchedulerImpl::Policy::FIRST_POLICY,
- RendererSchedulerImpl::Policy::POLICY_COUNT,
- &RendererSchedulerImpl::PolicyToString);
+ static void CheckAllUseCaseToString() {
+ CallForEachEnumValue<RendererSchedulerImpl::UseCase>(
+ RendererSchedulerImpl::UseCase::FIRST_USE_CASE,
+ RendererSchedulerImpl::UseCase::USE_CASE_COUNT,
+ &RendererSchedulerImpl::UseCaseToString);
}
scoped_ptr<base::SimpleTestTickClock> clock_;
@@ -637,9 +682,12 @@ TEST_F(
PostTestTasks(&run_order, "C1 T1");
scheduler_->DidAnimateForInputOnCompositorThread();
- scheduler_->WillBeginFrame(cc::BeginFrameArgs::Create(
+ cc::BeginFrameArgs begin_frame_args1 = cc::BeginFrameArgs::Create(
BEGINFRAME_FROM_HERE, clock_->NowTicks(), base::TimeTicks(),
- base::TimeDelta::FromMilliseconds(16), cc::BeginFrameArgs::NORMAL));
+ base::TimeDelta::FromMilliseconds(1000), cc::BeginFrameArgs::NORMAL);
+ begin_frame_args1.on_critical_path = true;
+ scheduler_->WillBeginFrame(begin_frame_args1);
+ scheduler_->DidCommitFrameToCompositor(); // Starts Idle Period
RunUntilIdle();
EXPECT_THAT(run_order, testing::ElementsAre(std::string("C1")));
@@ -793,28 +841,32 @@ TEST_F(RendererSchedulerImplTest, TestTouchstartPolicy_MainThread) {
TEST_F(RendererSchedulerImplTest, LoadingPriorityPolicy) {
std::vector<std::string> run_order;
- PostTestTasks(&run_order, "L1 I1 D1 C1 D2 C2");
+ PostTestTasks(&run_order, "I1 D1 C1 T1 L1 D2 C2 T2 L2");
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")));
+
+ // In loading policy, loading and timer tasks are prioritized other others.
+ std::string loading_policy_expected[] = {
+ std::string("T1"), std::string("L1"), std::string("T2"),
+ std::string("L2"), std::string("D1"), std::string("C1"),
+ std::string("D2"), std::string("C2"), std::string("I1")};
+ EXPECT_THAT(run_order, testing::ElementsAreArray(loading_policy_expected));
// Advance 1.5s and try again, the loading policy should have ended and the
- // task order should return to normal.
+ // task order should return to the NOT_SCROLLING use case where loading tasks
+ // are prioritized.
clock_->Advance(base::TimeDelta::FromMilliseconds(1500));
run_order.clear();
- PostTestTasks(&run_order, "L1 I1 D1 C1 D2 C2");
+ PostTestTasks(&run_order, "I1 D1 C1 T1 L1 D2 C2 T2 L2");
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")));
+ std::string default_order_expected[] = {
+ std::string("L1"), std::string("L2"), std::string("D1"),
+ std::string("C1"), std::string("T1"), std::string("D2"),
+ std::string("C2"), std::string("T2"), std::string("I1")};
+ EXPECT_THAT(run_order, testing::ElementsAreArray(default_order_expected));
}
TEST_F(RendererSchedulerImplTest,
@@ -962,7 +1014,9 @@ TEST_F(RendererSchedulerImplTest,
}
TEST_F(RendererSchedulerImplTest,
- TestCompositorPolicyDoesNotStarveDefaultTasks) {
+ TestMainthreadScrollingUseCaseDoesNotStarveDefaultTasks) {
+ ForceMainthreadScrollingUseCase();
+
std::vector<std::string> run_order;
PostTestTasks(&run_order, "D1 C1");
@@ -984,52 +1038,28 @@ TEST_F(RendererSchedulerImplTest,
TEST_F(RendererSchedulerImplTest,
TestCompositorPolicyEnds_CompositorHandlesInput) {
- std::vector<std::string> run_order;
- PostTestTasks(&run_order, "D1 C1 D2 C2");
-
scheduler_->DidHandleInputEventOnCompositorThread(
FakeInputEvent(blink::WebInputEvent::GestureFlingStart),
RendererScheduler::InputEventState::EVENT_CONSUMED_BY_COMPOSITOR);
- RunUntilIdle();
- EXPECT_THAT(run_order,
- testing::ElementsAre(std::string("C1"), std::string("C2"),
- std::string("D1"), std::string("D2")));
+ EXPECT_EQ(UseCase::COMPOSITOR_SCROLLING,
+ ForceUpdatePolicyAndGetCurrentUseCase());
- run_order.clear();
clock_->Advance(base::TimeDelta::FromMilliseconds(1000));
- PostTestTasks(&run_order, "D1 C1 D2 C2");
-
- // Compositor policy mode should have ended now that the clock has advanced.
- RunUntilIdle();
- EXPECT_THAT(run_order,
- testing::ElementsAre(std::string("D1"), std::string("C1"),
- std::string("D2"), std::string("C2")));
+ EXPECT_EQ(UseCase::NOT_SCROLLING, ForceUpdatePolicyAndGetCurrentUseCase());
}
TEST_F(RendererSchedulerImplTest,
TestCompositorPolicyEnds_MainThreadHandlesInput) {
- std::vector<std::string> run_order;
- PostTestTasks(&run_order, "D1 C1 D2 C2");
-
scheduler_->DidHandleInputEventOnCompositorThread(
FakeInputEvent(blink::WebInputEvent::GestureFlingStart),
RendererScheduler::InputEventState::EVENT_FORWARDED_TO_MAIN_THREAD);
scheduler_->DidHandleInputEventOnMainThread(
FakeInputEvent(blink::WebInputEvent::GestureFlingStart));
- RunUntilIdle();
- EXPECT_THAT(run_order,
- testing::ElementsAre(std::string("C1"), std::string("C2"),
- std::string("D1"), std::string("D2")));
+ EXPECT_EQ(UseCase::COMPOSITOR_SCROLLING,
+ ForceUpdatePolicyAndGetCurrentUseCase());
- run_order.clear();
clock_->Advance(base::TimeDelta::FromMilliseconds(1000));
- PostTestTasks(&run_order, "D1 C1 D2 C2");
-
- // Compositor policy mode should have ended now that the clock has advanced.
- RunUntilIdle();
- EXPECT_THAT(run_order,
- testing::ElementsAre(std::string("D1"), std::string("C1"),
- std::string("D2"), std::string("C2")));
+ EXPECT_EQ(UseCase::NOT_SCROLLING, ForceUpdatePolicyAndGetCurrentUseCase());
}
TEST_F(RendererSchedulerImplTest, TestTouchstartPolicyEndsAfterTimeout) {
@@ -1093,22 +1123,25 @@ TEST_F(RendererSchedulerImplTest, TestIsHighPriorityWorkAnticipated) {
bool is_anticipated_before = false;
bool is_anticipated_after = false;
- bool simulate_input = false;
default_task_runner_->PostTask(
- FROM_HERE,
- base::Bind(&AnticipationTestTask, scheduler_.get(), simulate_input,
- &is_anticipated_before, &is_anticipated_after));
+ FROM_HERE, base::Bind(&AnticipationTestTask, scheduler_.get(),
+ SimulateInputType::None, &is_anticipated_before,
+ &is_anticipated_after));
RunUntilIdle();
// In its default state, without input receipt, the scheduler should indicate
// that no high-priority is anticipated.
EXPECT_FALSE(is_anticipated_before);
EXPECT_FALSE(is_anticipated_after);
- simulate_input = true;
default_task_runner_->PostTask(
- FROM_HERE,
- base::Bind(&AnticipationTestTask, scheduler_.get(), simulate_input,
- &is_anticipated_before, &is_anticipated_after));
+ FROM_HERE, base::Bind(&AnticipationTestTask, scheduler_.get(),
+ SimulateInputType::TouchStart,
+ &is_anticipated_before, &is_anticipated_after));
+ bool dummy;
+ default_task_runner_->PostTask(
+ FROM_HERE, base::Bind(&AnticipationTestTask, scheduler_.get(),
+ SimulateInputType::TouchEnd, &dummy, &dummy));
+
RunUntilIdle();
// When input is received, the scheduler should indicate that high-priority
// work is anticipated.
@@ -1116,14 +1149,29 @@ TEST_F(RendererSchedulerImplTest, TestIsHighPriorityWorkAnticipated) {
EXPECT_TRUE(is_anticipated_after);
clock_->Advance(priority_escalation_after_input_duration() * 2);
- simulate_input = false;
default_task_runner_->PostTask(
- FROM_HERE,
- base::Bind(&AnticipationTestTask, scheduler_.get(), simulate_input,
- &is_anticipated_before, &is_anticipated_after));
- RunUntilIdle();
- // Without additional input, the scheduler should indicate that high-priority
- // work is no longer anticipated.
+ FROM_HERE, base::Bind(&AnticipationTestTask, scheduler_.get(),
+ SimulateInputType::None, &is_anticipated_before,
+ &is_anticipated_after));
+ RunUntilIdle();
+ // Without additional input, the scheduler should go into NOT_SCROLLING
+ // use case but with scrolling expected where high-priority work is still
+ // anticipated.
+ EXPECT_EQ(UseCase::NOT_SCROLLING, CurrentUseCase());
+ EXPECT_TRUE(ScrollExpectedSoon());
+ EXPECT_TRUE(is_anticipated_before);
+ EXPECT_TRUE(is_anticipated_after);
+
+ clock_->Advance(subsequent_input_expected_after_input_duration() * 2);
+ default_task_runner_->PostTask(
+ FROM_HERE, base::Bind(&AnticipationTestTask, scheduler_.get(),
+ SimulateInputType::None, &is_anticipated_before,
+ &is_anticipated_after));
+ RunUntilIdle();
+ // Eventually the scheduler should go into the default use case where
+ // high-priority work is no longer anticipated.
+ EXPECT_EQ(UseCase::NOT_SCROLLING, CurrentUseCase());
+ EXPECT_FALSE(ScrollExpectedSoon());
EXPECT_FALSE(is_anticipated_before);
EXPECT_FALSE(is_anticipated_after);
}
@@ -1132,6 +1180,8 @@ TEST_F(RendererSchedulerImplTest, TestShouldYield) {
bool should_yield_before = false;
bool should_yield_after = false;
+ ForceMainthreadScrollingUseCase();
+
default_task_runner_->PostTask(
FROM_HERE, base::Bind(&PostingYieldingTestTask, scheduler_.get(),
default_task_runner_, false, &should_yield_before,
@@ -1146,7 +1196,7 @@ TEST_F(RendererSchedulerImplTest, TestShouldYield) {
compositor_task_runner_, false,
&should_yield_before, &should_yield_after));
RunUntilIdle();
- // Posting while not in compositor priority shouldn't cause yielding.
+ // Posting while not mainthread scrolling shouldn't cause yielding.
EXPECT_FALSE(should_yield_before);
EXPECT_FALSE(should_yield_after);
@@ -1170,14 +1220,14 @@ TEST_F(RendererSchedulerImplTest, TestShouldYield) {
}
TEST_F(RendererSchedulerImplTest, SlowMainThreadInputEvent) {
- EXPECT_EQ(Policy::NORMAL, CurrentPolicy());
+ EXPECT_EQ(UseCase::NOT_SCROLLING, CurrentUseCase());
// An input event should bump us into input priority.
scheduler_->DidHandleInputEventOnCompositorThread(
FakeInputEvent(blink::WebInputEvent::GestureFlingStart),
RendererScheduler::InputEventState::EVENT_FORWARDED_TO_MAIN_THREAD);
RunUntilIdle();
- EXPECT_EQ(Policy::COMPOSITOR_PRIORITY, CurrentPolicy());
+ EXPECT_EQ(UseCase::COMPOSITOR_SCROLLING, CurrentUseCase());
// Simulate the input event being queued for a very long time. The compositor
// task we post here represents the enqueued input task.
@@ -1188,12 +1238,12 @@ TEST_F(RendererSchedulerImplTest, SlowMainThreadInputEvent) {
// Even though we exceeded the input priority escalation period, we should
// still be in compositor priority since the input remains queued.
- EXPECT_EQ(Policy::COMPOSITOR_PRIORITY, CurrentPolicy());
+ EXPECT_EQ(UseCase::COMPOSITOR_SCROLLING, CurrentUseCase());
// After the escalation period ends we should go back into normal mode.
clock_->Advance(priority_escalation_after_input_duration() * 2);
RunUntilIdle();
- EXPECT_EQ(Policy::NORMAL, CurrentPolicy());
+ EXPECT_EQ(UseCase::NOT_SCROLLING, CurrentUseCase());
}
class RendererSchedulerImplWithMockSchedulerTest
@@ -1396,10 +1446,15 @@ TEST_F(RendererSchedulerImplWithMockSchedulerTest,
EXPECT_EQ(1, mock_scheduler_->update_policy_count_);
- RunUntilIdle();
// We expect both the urgent and the delayed updates to run in addition to the
- // earlier updated cause by IsHighPriorityWorkAnticipated.
- EXPECT_EQ(3, mock_scheduler_->update_policy_count_);
+ // earlier updated cause by IsHighPriorityWorkAnticipated, a final update
+ // transitions from 'not_scrolling scroll expected' to 'not_scrolling'.
+ RunUntilIdle();
+ EXPECT_THAT(
+ mock_scheduler_->use_cases_,
+ testing::ElementsAre(std::string("touchstart"), std::string("touchstart"),
+ std::string("not_scrolling scroll expected"),
+ std::string("not_scrolling")));
}
class RendererSchedulerImplWithMessageLoopTest
@@ -1754,8 +1809,8 @@ TEST_F(RendererSchedulerImplTest, MultipleSuspendsNeedMultipleResumes) {
testing::ElementsAre(std::string("T1"), std::string("T2")));
}
-TEST_F(RendererSchedulerImplTest, PolicyToString) {
- CheckAllPolicyToString();
+TEST_F(RendererSchedulerImplTest, UseCaseToString) {
+ CheckAllUseCaseToString();
}
TEST_F(RendererSchedulerImplTest, MismatchedDidHandleInputEventOnMainThread) {

Powered by Google App Engine
This is Rietveld 408576698