Commit 6b0a2ec9 authored by Scott Haseley's avatar Scott Haseley Committed by Commit Bot

[scheduling APIs] Less priorities and semantic priority names

This changes the postTask prototype to use semantically meaningful names
and reduces the number of priorities. The priorities now match the
updated explainer:
https://github.com/WICG/main-thread-scheduling/blob/master/PrioritizedPostTask.md

The changes are:
  "immediate" --> removed. We may reconsider if we have use cases.
  "high"      --> "user-blocking"
  "default"   --> "user-visible"
  "low"       --> "background"
  "idle"      --> removed. We may also reconsider this if we have use
                  cases that can be differentiated from "background",
                  but we currently don't. This also avoids conflict w/
                  requestIdleCallback.

Bug: 979017
Change-Id: I58fb68e8bed38d8463d080bb3ff028049a69667b
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2008426
Commit-Queue: Scott Haseley <shaseley@chromium.org>
Reviewed-by: default avatarAlexander Timin <altimin@chromium.org>
Reviewed-by: default avatarSami Kyöstilä <skyostil@chromium.org>
Reviewed-by: default avatarNate Chapin <japhet@chromium.org>
Cr-Commit-Position: refs/heads/master@{#734318}
parent bdcbd022
......@@ -93,7 +93,7 @@ ScriptPromise DOMScheduler::postTask(ScriptState* script_state,
if (!task_runner)
return RejectPromiseImmediately(exception_state);
} else {
task_runner = GetTaskRunnerFor(WebSchedulingPriority::kDefaultPriority);
task_runner = GetTaskRunnerFor(WebSchedulingPriority::kUserVisiblePriority);
}
// TODO(shaseley): We need to figure out the behavior we want for delay. For
......
......@@ -5,11 +5,9 @@
// Experimental Scheduling API Proposal:
// https://docs.google.com/document/d/1xU7HyNsEsbXhTgt0ZnXDbeSXm5-m5FzkLJAT6LTizEI/edit#
enum TaskPriority {
"immediate",
"high",
"default",
"low",
"idle"
"user-blocking",
"user-visible",
"background"
};
dictionary SchedulerPostTaskOptions {
......
......@@ -9,7 +9,7 @@
ImplementedAs=DOMTaskController,
RuntimeEnabled=WebScheduler
] interface TaskController : AbortController {
[CallWith=Document] constructor(optional TaskPriority priority = "default");
[CallWith=Document] constructor(optional TaskPriority priority = "user-visible");
void setPriority(TaskPriority priority);
};
......@@ -958,16 +958,12 @@ TaskQueue::QueuePriority FrameSchedulerImpl::ComputePriority(
// and add a range of new priorities less than low.
if (task_queue->web_scheduling_priority()) {
switch (task_queue->web_scheduling_priority().value()) {
case WebSchedulingPriority::kImmediatePriority:
return TaskQueue::QueuePriority::kHighestPriority;
case WebSchedulingPriority::kHighPriority:
case WebSchedulingPriority::kUserBlockingPriority:
return TaskQueue::QueuePriority::kHighPriority;
case WebSchedulingPriority::kDefaultPriority:
case WebSchedulingPriority::kUserVisiblePriority:
return TaskQueue::QueuePriority::kNormalPriority;
case WebSchedulingPriority::kLowPriority:
case WebSchedulingPriority::kBackgroundPriority:
return TaskQueue::QueuePriority::kLowPriority;
case WebSchedulingPriority::kIdlePriority:
return TaskQueue::QueuePriority::kBestEffortPriority;
}
}
......
......@@ -2314,11 +2314,9 @@ class WebSchedulingTaskQueueTest : public FrameSchedulerImplTest {
// Helper for posting tasks to a WebSchedulingTaskQueue. |task_descriptor| is
// a string with space delimited task identifiers. The first letter of each
// task identifier specifies the task queue priority:
// - 'I': Immediate
// - 'H': High
// - 'D': Default
// - 'L': Low
// - 'E': Idle
// - 'U': UserBlocking
// - 'V': UserVisible
// - 'B': Background
void PostWebSchedulingTestTasks(Vector<String>* run_order,
const String& task_descriptor) {
std::istringstream stream(task_descriptor.Utf8());
......@@ -2327,20 +2325,14 @@ class WebSchedulingTaskQueueTest : public FrameSchedulerImplTest {
stream >> task;
WebSchedulingPriority priority;
switch (task[0]) {
case 'I':
priority = WebSchedulingPriority::kImmediatePriority;
case 'U':
priority = WebSchedulingPriority::kUserBlockingPriority;
break;
case 'H':
priority = WebSchedulingPriority::kHighPriority;
case 'V':
priority = WebSchedulingPriority::kUserVisiblePriority;
break;
case 'D':
priority = WebSchedulingPriority::kDefaultPriority;
break;
case 'L':
priority = WebSchedulingPriority::kLowPriority;
break;
case 'E':
priority = WebSchedulingPriority::kIdlePriority;
case 'B':
priority = WebSchedulingPriority::kBackgroundPriority;
break;
default:
EXPECT_FALSE(true);
......@@ -2361,23 +2353,23 @@ class WebSchedulingTaskQueueTest : public FrameSchedulerImplTest {
TEST_F(WebSchedulingTaskQueueTest, TasksRunInPriorityOrder) {
Vector<String> run_order;
PostWebSchedulingTestTasks(&run_order, "E1 E2 L1 L2 D1 D2 H1 H2 I1 I2");
PostWebSchedulingTestTasks(&run_order, "B1 B2 V1 V2 U1 U2");
base::RunLoop().RunUntilIdle();
EXPECT_THAT(run_order, testing::ElementsAre("I1", "I2", "H1", "H2", "D1",
"D2", "L1", "L2", "E1", "E2"));
EXPECT_THAT(run_order,
testing::ElementsAre("U1", "U2", "V1", "V2", "B1", "B2"));
}
TEST_F(WebSchedulingTaskQueueTest, DynamicTaskPriorityOrder) {
Vector<String> run_order;
PostWebSchedulingTestTasks(&run_order, "E1 E2 D1 D2 I1 I2");
task_queues_[static_cast<int>(WebSchedulingPriority::kImmediatePriority)]
->SetPriority(WebSchedulingPriority::kLowPriority);
PostWebSchedulingTestTasks(&run_order, "B1 B2 V1 V2 U1 U2");
task_queues_[static_cast<int>(WebSchedulingPriority::kUserBlockingPriority)]
->SetPriority(WebSchedulingPriority::kBackgroundPriority);
base::RunLoop().RunUntilIdle();
EXPECT_THAT(run_order,
testing::ElementsAre("D1", "D2", "I1", "I2", "E1", "E2"));
testing::ElementsAre("V1", "V2", "B1", "B2", "U1", "U2"));
}
} // namespace frame_scheduler_impl_unittest
......
......@@ -260,38 +260,24 @@ TEST_F(FrameTaskQueueControllerTest,
TEST_F(FrameTaskQueueControllerTest, AddWebSchedulingTaskQueues) {
scoped_refptr<MainThreadTaskQueue> task_queue =
frame_task_queue_controller_->NewWebSchedulingTaskQueue(
QueueTraits(), WebSchedulingPriority::kImmediatePriority);
QueueTraits(), WebSchedulingPriority::kUserBlockingPriority);
EXPECT_EQ(1u,
frame_task_queue_controller_->GetAllTaskQueuesAndVoters().size());
EXPECT_EQ(WebSchedulingPriority::kImmediatePriority,
EXPECT_EQ(WebSchedulingPriority::kUserBlockingPriority,
task_queue->web_scheduling_priority().value());
task_queue = frame_task_queue_controller_->NewWebSchedulingTaskQueue(
QueueTraits(), WebSchedulingPriority::kHighPriority);
QueueTraits(), WebSchedulingPriority::kUserVisiblePriority);
EXPECT_EQ(2u,
frame_task_queue_controller_->GetAllTaskQueuesAndVoters().size());
EXPECT_EQ(WebSchedulingPriority::kHighPriority,
EXPECT_EQ(WebSchedulingPriority::kUserVisiblePriority,
task_queue->web_scheduling_priority().value());
task_queue = frame_task_queue_controller_->NewWebSchedulingTaskQueue(
QueueTraits(), WebSchedulingPriority::kDefaultPriority);
QueueTraits(), WebSchedulingPriority::kBackgroundPriority);
EXPECT_EQ(3u,
frame_task_queue_controller_->GetAllTaskQueuesAndVoters().size());
EXPECT_EQ(WebSchedulingPriority::kDefaultPriority,
task_queue->web_scheduling_priority().value());
task_queue = frame_task_queue_controller_->NewWebSchedulingTaskQueue(
QueueTraits(), WebSchedulingPriority::kLowPriority);
EXPECT_EQ(4u,
frame_task_queue_controller_->GetAllTaskQueuesAndVoters().size());
EXPECT_EQ(WebSchedulingPriority::kLowPriority,
task_queue->web_scheduling_priority().value());
task_queue = frame_task_queue_controller_->NewWebSchedulingTaskQueue(
QueueTraits(), WebSchedulingPriority::kIdlePriority);
EXPECT_EQ(5u,
frame_task_queue_controller_->GetAllTaskQueuesAndVoters().size());
EXPECT_EQ(WebSchedulingPriority::kIdlePriority,
EXPECT_EQ(WebSchedulingPriority::kBackgroundPriority,
task_queue->web_scheduling_priority().value());
}
......@@ -299,18 +285,18 @@ TEST_F(FrameTaskQueueControllerTest,
AddMultipleSamePriorityWebSchedulingTaskQueues) {
scoped_refptr<MainThreadTaskQueue> task_queue1 =
frame_task_queue_controller_->NewWebSchedulingTaskQueue(
QueueTraits(), WebSchedulingPriority::kImmediatePriority);
QueueTraits(), WebSchedulingPriority::kUserBlockingPriority);
EXPECT_EQ(1u,
frame_task_queue_controller_->GetAllTaskQueuesAndVoters().size());
EXPECT_EQ(WebSchedulingPriority::kImmediatePriority,
EXPECT_EQ(WebSchedulingPriority::kUserBlockingPriority,
task_queue1->web_scheduling_priority().value());
scoped_refptr<MainThreadTaskQueue> task_queue2 =
frame_task_queue_controller_->NewWebSchedulingTaskQueue(
QueueTraits(), WebSchedulingPriority::kImmediatePriority);
QueueTraits(), WebSchedulingPriority::kUserBlockingPriority);
EXPECT_EQ(2u,
frame_task_queue_controller_->GetAllTaskQueuesAndVoters().size());
EXPECT_EQ(WebSchedulingPriority::kImmediatePriority,
EXPECT_EQ(WebSchedulingPriority::kUserBlockingPriority,
task_queue2->web_scheduling_priority().value());
EXPECT_NE(task_queue1.get(), task_queue2.get());
......
......@@ -8,45 +8,33 @@ namespace blink {
namespace {
const AtomicString& ImmediatePriorityKeyword() {
DEFINE_STATIC_LOCAL(const AtomicString, immediate_priority, ("immediate"));
return immediate_priority;
const AtomicString& UserBlockingPriorityKeyword() {
DEFINE_STATIC_LOCAL(const AtomicString, user_blocking_priority,
("user-blocking"));
return user_blocking_priority;
}
const AtomicString& HighPriorityKeyword() {
DEFINE_STATIC_LOCAL(const AtomicString, high_priority, ("high"));
return high_priority;
const AtomicString& UserVisiblePriorityKeyword() {
DEFINE_STATIC_LOCAL(const AtomicString, user_visible_priority,
("user-visible"));
return user_visible_priority;
}
const AtomicString& DefaultPriorityKeyword() {
DEFINE_STATIC_LOCAL(const AtomicString, default_priority, ("default"));
return default_priority;
}
const AtomicString& LowPriorityKeyword() {
DEFINE_STATIC_LOCAL(const AtomicString, low_priority, ("low"));
return low_priority;
}
const AtomicString& IdlePriorityKeyword() {
DEFINE_STATIC_LOCAL(const AtomicString, idle_priority, ("idle"));
return idle_priority;
const AtomicString& BackgroundPriorityKeyword() {
DEFINE_STATIC_LOCAL(const AtomicString, background_priority, ("background"));
return background_priority;
}
} // namespace
AtomicString WebSchedulingPriorityToString(WebSchedulingPriority priority) {
switch (priority) {
case WebSchedulingPriority::kImmediatePriority:
return ImmediatePriorityKeyword();
case WebSchedulingPriority::kHighPriority:
return HighPriorityKeyword();
case WebSchedulingPriority::kDefaultPriority:
return DefaultPriorityKeyword();
case WebSchedulingPriority::kLowPriority:
return LowPriorityKeyword();
case WebSchedulingPriority::kIdlePriority:
return IdlePriorityKeyword();
case WebSchedulingPriority::kUserBlockingPriority:
return UserBlockingPriorityKeyword();
case WebSchedulingPriority::kUserVisiblePriority:
return UserVisiblePriorityKeyword();
case WebSchedulingPriority::kBackgroundPriority:
return BackgroundPriorityKeyword();
}
NOTREACHED();
......@@ -55,19 +43,14 @@ AtomicString WebSchedulingPriorityToString(WebSchedulingPriority priority) {
WebSchedulingPriority WebSchedulingPriorityFromString(
const AtomicString& priority) {
if (priority == ImmediatePriorityKeyword())
return WebSchedulingPriority::kImmediatePriority;
if (priority == HighPriorityKeyword())
return WebSchedulingPriority::kHighPriority;
if (priority == DefaultPriorityKeyword())
return WebSchedulingPriority::kDefaultPriority;
if (priority == LowPriorityKeyword())
return WebSchedulingPriority::kLowPriority;
if (priority == IdlePriorityKeyword())
return WebSchedulingPriority::kIdlePriority;
if (priority == UserBlockingPriorityKeyword())
return WebSchedulingPriority::kUserBlockingPriority;
if (priority == UserVisiblePriorityKeyword())
return WebSchedulingPriority::kUserVisiblePriority;
if (priority == BackgroundPriorityKeyword())
return WebSchedulingPriority::kBackgroundPriority;
NOTREACHED();
return WebSchedulingPriority::kDefaultPriority;
return WebSchedulingPriority::kUserVisiblePriority;
}
} // namespace blink
......@@ -13,13 +13,11 @@ namespace blink {
// Priorities for the experimental scheduling API (see
// https://github.com/WICG/main-thread-scheduling).
enum class WebSchedulingPriority {
kImmediatePriority = 0,
kHighPriority = 1,
kDefaultPriority = 2,
kLowPriority = 3,
kIdlePriority = 4,
kUserBlockingPriority = 0,
kUserVisiblePriority = 1,
kBackgroundPriority = 2,
kLastPriority = kIdlePriority
kLastPriority = kBackgroundPriority
};
PLATFORM_EXPORT AtomicString
......
......@@ -14,12 +14,12 @@ let taskToMove;
async_test(t => {
let now = performance.now();
let tc = new TaskController('low');
let tc = new TaskController('background');
scheduler.postTask(t.step_func(() => {
assert_equals(++taskCount, 1);
tc.setPriority('immediate');
}), { priority: 'immediate', delay: 10 });
tc.setPriority('user-blocking');
}), { priority: 'user-blocking', delay: 10 });
scheduler.postTask(t.step_func_done(() => {
assert_equals(++taskCount, 2);
......@@ -28,6 +28,6 @@ async_test(t => {
assert_greater_than_equal(elapsed, 20);
}), { signal: tc.signal, delay: 20 });
}, 'Tests delay when moving a delayed task');
}, "Tests delay when changing a delayed task's priority");
</script>
......@@ -13,19 +13,19 @@ async_test(t => {
let task_controllers = [];
for (let i = 0; i < 5; i++) {
let tc = new TaskController('idle');
let tc = new TaskController('background');
scheduler.postTask(() => {
result += i.toString();
}, { signal: tc.signal });
task_controllers.push(tc);
}
task_controllers[2].setPriority('high');
assert_equals(task_controllers[2].signal.priority, 'high');
task_controllers[2].setPriority('user-blocking');
assert_equals(task_controllers[2].signal.priority, 'user-blocking');
scheduler.postTask(t.step_func_done(() => {
assert_equals('20134', result);
}), { priority: 'idle' });
}), { priority: 'background' });
}, 'Test modifying TaskController priority');
......
......@@ -13,7 +13,7 @@ async_test(t => {
scheduler.postTask(t.step_func_done(() => {
let elapsed = performance.now() - now;
assert_greater_than_equal(elapsed, 10);
}), { priority: 'immediate', delay: 10 });
}), { priority: 'user-blocking', delay: 10 });
}, 'Tests basic scheduler.postTask with a delay');
</script>
......@@ -13,7 +13,7 @@ onmessage = () => { assert_unreached("task should not have run"); };
async_test(t => {
// Give the task time to run if it hadn't been detached.
scheduler.postTask(t.step_func_done(() => {}), { priority: "idle" });
scheduler.postTask(t.step_func_done(() => {}), { priority: "background" });
}, 'Test scheduler.postTask() from an iframe that is removed before the task runs');
</script>
......@@ -10,11 +10,11 @@
async_test(t => {
var result = "fail";
let tc = new TaskController("low");
scheduler.postTask(() => { result = "pass"; }, { priority : "high", signal: tc.signal });
let tc = new TaskController("background");
scheduler.postTask(() => { result = "pass"; }, { priority : "user-blocking", signal: tc.signal });
// Since the above task should be run at high priority, it should execute
// before this default priority task.
// Since the above task should be run at user-blocking priority, it should execute
// before this user-visible priority task.
scheduler.postTask(t.step_func_done(() => {
assert_equals(result, "pass");
}));
......
......@@ -11,7 +11,7 @@
async_test(t => {
function* priorityGenerator() {
let priorities = [
"immediate", "high", "default", "low", "idle"
"user-blocking", "user-visible", "background"
];
for (let i = 0; i < priorities.length; i++)
yield priorities[i];
......
......@@ -12,7 +12,7 @@ async_test(t => {
scheduler.postTask(t.step_func_done((arg1, arg2) => {
assert_equals(arg1, 'foo');
assert_equals(arg2, 10);
}), { priority: 'default' }, 'foo', 10);
}), { priority: 'user-visible' }, 'foo', 10);
}, 'Test scheduler.postTask correctly passes arguments');
</script>
......@@ -13,7 +13,7 @@ async_test(t => {
let task_controllers = [];
for (let i = 0; i < 5; i++) {
let tc = new TaskController("default");
let tc = new TaskController();
let task = scheduler.postTask(() => {
result += i.toString();
}, { signal: tc.signal });
......@@ -34,7 +34,7 @@ async_test(t => {
assert_equals(result, '0134');
}));
let final_task_tc = new TaskController("default");
let final_task_tc = new TaskController();
// Check that canceling running, completed, or canceled tasks is a no-op.
scheduler.postTask(t.step_func_done(() => {
final_task_tc.abort();
......
......@@ -10,19 +10,19 @@
async_test(t => {
let result = 0;
let tc = new TaskController("default");
let tc = new TaskController();
scheduler.postTask(() => {}, { signal: tc.signal }).then(
() => { assert_unreached('This task should have been aborted'); },
() => { result++; });
scheduler.postTask(() => {}, { priority: "idle", signal: tc.signal }).then(
scheduler.postTask(() => {}, { priority: "background", signal: tc.signal }).then(
() => { assert_unreached('This task should have been aborted'); },
() => { result++; });
tc.abort();
scheduler.postTask(t.step_func_done(() => {
assert_equals(result, 2);
}), { priority: "idle" });
}), { priority: "background" });
}, 'Test that when scheduler.postTask() is given both a signal and priority. the signal abort is honored');
......
......@@ -10,7 +10,7 @@
async_test(t => {
let result = '';
let tc = new TaskController("default");
let tc = new TaskController("user-visible");
for (let i = 0; i < 5; i++) {
let task = scheduler.postTask(() => {
......@@ -18,15 +18,14 @@ async_test(t => {
}, { signal: tc.signal });
}
scheduler.postTask(() => { result += "5"; }, { priority : "high" });
scheduler.postTask(() => { result += "6"; }, { priority : "default" });
scheduler.postTask(() => { result += "7"; }, { priority : "low" });
scheduler.postTask(() => { result += "5"; }, { priority : "user-blocking" });
scheduler.postTask(() => { result += "6"; }, { priority : "user-visible" });
tc.setPriority("idle");
tc.setPriority("background");
scheduler.postTask(t.step_func_done(() => {
assert_equals(result, '56701234');
}), { priority: "idle" });
assert_equals(result, '5601234');
}), { priority: "background" });
}, 'Test that TaskController.setPriority() changes the priority of all associated tasks');
......
......@@ -23,20 +23,16 @@ async_test(t => {
// Post tasks in reverse priority order and expect they are run from highest
// to lowest priority.
scheduleReportTask('E1', 'idle');
scheduleReportTask('E2', 'idle');
scheduleReportTask('L1', 'low');
scheduleReportTask('L2', 'low');
scheduleReportTask('D1', 'default');
scheduleReportTask('D2', 'default');
scheduleReportTask('H1', 'high');
scheduleReportTask('H2', 'high');
scheduleReportTask('I1', 'immediate');
scheduleReportTask('I2', 'immediate');
scheduleReportTask('B1', 'background');
scheduleReportTask('B2', 'background');
scheduleReportTask('UV1', 'user-visible');
scheduleReportTask('UV2', 'user-visible');
scheduleReportTask('UB1', 'user-blocking');
scheduleReportTask('UB2', 'user-blocking');
scheduler.postTask(t.step_func_done(() => {
assert_equals(result, 'I1 I2 H1 H2 D1 D2 L1 L2 E1 E2');
}), { priority: 'idle' });
assert_equals(result, 'UB1 UB2 UV1 UV2 B1 B2');
}), { priority: 'background' });
}, 'Test scheduler.postTask task run in priority order');
</script>
......@@ -10,7 +10,7 @@
async_test(t => {
(function() {
let tc = new TaskController("default");
let tc = new TaskController();
let task_promise = scheduler.postTask(() => 1234, { signal: tc.signal });
task_promise.then(t.step_func((res) => {
assert_true(false, 'task promise should not be fulfilled when the task is canceled.');
......
......@@ -10,7 +10,7 @@
async_test(t => {
(function() {
let tc = new TaskController("default");
let tc = new TaskController();
let task_promise = scheduler.postTask(() => 1234, { signal: tc.signal });
tc.abort();
task_promise.then(t.step_func((res) => {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment