Prioritized Job Scheduling

1. Introduction This section is non-normative. Scheduling can be an important developer tool for improving website performance. Broadly speaking, there are two areas where scheduling can be impactful: user-percieved latency and responsiveness. Scheduling can improve user-perceived latency to the degree that lower priority work can be pushed off in favor of higher priority work that…


1. Introduction

This allotment is non-normative.

Scheduling would perchance perchance be a extremely vital developer diagram for making improvements to web put
performance. Broadly speaking, there are two areas the build scheduling would perchance perchance be
impactful: user-percieved latency and responsiveness. Scheduling can toughen
user-perceived latency to the diploma that decrease priority work would perchance perchance be pushed off
in prefer of greater priority work that at as soon as impacts quality of experience.
As an instance, pushing off execution of definite 3P library scripts all the scheme by page
load can earnings the user by getting pixels to the mask mask quicker. The same
applies to prioritizing work related to sigh material inside the viewport. For
script working on the vital thread, lengthy tasks can negatively have an effect on each and each enter
and visual responsiveness by blocking enter and UI updates from working.
Breaking apart these tasks into smaller pieces and scheduling the chunks or job continuations is a proven skill that applications and framework builders
exercise to toughen responsiveness.

Userspace schedulers typically work by providing the formula to agenda tasks and
controlling when those tasks fabricate. Duties typically cling an related
priority, which in enormous allotment determines when the duty will bustle, in relation to
other tasks the scheduler controls. The scheduler typically operates by
executing tasks for some duration of time (a scheduler quantum) earlier than yielding
administration relief to the browser. The scheduler resumes by scheduling a continuation
job, e.g. a name to setTimeout() or postMessage().

Whereas userspace schedulers cling been capable, the speak would perchance perchance simply be
improved with a centralized browser scheduler and greater scheduling primitives.
The priority machine of a scheduler extends simplest as a ways because the scheduler’s
reach. A kill consequence of this for userspace schedulers is that the UA in overall
has no data of userspace job priorities. The one exception is that if the
scheduler uses requestIdleCallback() for some of its work, but this
is puny to the bottom priority work. The same holds if there are a pair of schedulers on the page, which is increasingly more overall. As an instance, an app would perchance perchance
be built with a framework that has a schedueler (e.g. React), attain some
scheduling by itself, and even embed a aim that has a scheduler (e.g. an
embedded scheme). The browser is the supreme coordination point since the browser
has world data, and the match loop is in payment for working tasks.

Prioritization aside, the hot primitives that userspace schedulers rely on
are now not supreme for contemporary exercise circumstances. setTimeout(0) is the canonical formula to
agenda a non-delayed job, but there tend to be minimal extend values (e.g. for
nested tasks) that will consequence in unhappy performance ensuing from elevated latency. A successfully-acknowledged workaround is to
exercise postMessage() or a MessageChannel, but these APIs weren’t designed for scheduling, e.g. you
can not queue callbacks. requestIdleCallback() would perchance perchance be superb for
some exercise circumstances, but this simplest applies to idle tasks and does now not yarn for
tasks whose priority can commerce, e.g. re-prioritizing off-mask mask sigh material in
response to user enter, indulge in scrolling.

This file introduces a brand unique interface for builders to agenda and administration
prioritized tasks. The Scheduler interface exposes a postTask() skill to agenda tasks, and the specification
defines a chain of TaskPriorities that administration execution
enlighten. Moreover, a TaskController and its related TaskSignal would perchance perchance be dilapidated to abort scheduled tasks and administration their priorities.

2. Scheduling Duties

2.1. Job Priorities

This spec formalizes three priorities to make stronger scheduling tasks:

enum TaskPriority {

user-blocking is the absolute top priority,
and is intended to be dilapidated for tasks that are blocking the user’s skill to
work in conjunction with the page, equivalent to rendering the core experience or responding to
user enter.

user-visible is the second absolute top
priority, and is intended to be dilapidated for tasks that visible to the user but now not
necessarily blocking user actions, equivalent to rendering secondary parts of the
page. Here is the default priority.

background is the bottom priority, and
is intended to be dilapidated for tasks that are now not time-serious, equivalent to background
log processing or initializing definite third party libraries.

Demonstrate: Duties scheduled by a given Scheduler bustle in strict priority
, that skill the scheduler will all the time bustle “user-blocking
tasks earlier than “user-visible” tasks, which in flip all the time bustle
earlier than “background” tasks.

2.2. The Scheduler Interface

dictionary SchedulerPostTaskOptions {
  AbortSignal signal;
  TaskPriority priority;
  [EnforceRange] unsigned lengthy lengthy extend=0;

callback SchedulerPostTaskCallback=any ();

[Exposed=(Window, Worker)]
interface Scheduler {
  Promiseany> postTask(SchedulerPostTaskCallback callback,
                        optional SchedulerPostTaskOptions choices={});

Demonstrate: The signal likelihood would perchance perchance be both an AbortSignal or a TaskSignal, but is printed as an AbortSignal since
it is a superclass of TaskSignal. For circumstances the build the priority would perchance perchance
commerce, a TaskSignal is required. Nonetheless for circumstances the build simplest cancellation is
wanted, an AbortSignal would suffice, perchance making it more uncomplicated to
integrate the API into existing code that uses AbortSignals.

consequence=scheduler . postTask( callback, choices )

Returns a promise that is fulfilled with the return payment of callback,
or rejected with the AbortSignal‘s abort reason if the
job is aborted. If callback throws an error all the scheme by execution, the promise
returned by postTask() will doubtless be rejected with that error.

The job’s priority is definite by the combination of likelihood’s priority and signal:

  • If likelihood’s priority is specified, then
    that TaskPriority will doubtless be dilapidated to agenda the duty, and the duty’s
    priority is immutable.
  • Otherwise, if likelihood’s signal is
    specified and is a TaskSignal object, then the duty’s priority is
    definite by likelihood’s signal‘s priority. In this case the duty’s priority is dynamic,
    and would perchance perchance be modified by calling controller.setPriority() for the related TaskController.
  • Otherwise, the duty’s priority defaults to “user-visible“.

If likelihood’s signal is specified, then the signal is dilapidated by the Scheduler to
resolve if the duty is aborted.

If likelihood’s extend is specified and elevated
than 0, then the execution of the duty will doubtless be delayed for a minimal of extend milliseconds.

A Scheduler object has an related static priority
job queue scheme
, which is a scheme from TaskPriority to scheduler
job queue
. This scheme is initialized to a brand unique empty scheme.

A Scheduler object has an related dynamic priority
job queue scheme
, which is a scheme from TaskSignal to scheduler
job queue
. This scheme is initialized to a brand unique empty scheme.

A Scheduler object has a numeric subsequent enqueue
which is initialized to 1.

Demonstrate: The subsequent enqueue enlighten is a strictly rising quantity that
is dilapidated to search out out job execution enlighten across scheduler job queues of the
identical TaskPriority inside the comparable Scheduler. A logically comparable
different would be to area the subsequent enqueue enlighten on the match loop, since the top possible necessities are that the volume be strictly
rising and now not be repeated inside a Scheduler.

Would or now not it be more superb to easily exercise a timestamp right here?

The postTask(callback, choices) skill steps are to return the cease consequence of scheduling a postTask job for this given callback and choices.

2.3. Definitions

A scheduler job is a job with an additional numeric enqueue enlighten item, before everything situation to 0.

A scheduler job t1 is older than scheduler job t2 if t1’s enqueue enlighten decrease than t2’s enqueue enlighten.

The following job sources are outlined as scheduler job sources,
and must simplest be dilapidated for scheduler tasks.

The posted job job source

This job source is dilapidated for tasks scheduled by postTask().

A scheduler job queue is a struct with the following items:


A TaskPriority.


A situation of scheduler tasks.

A scheduler job queue queue’s first runnable job is the vital scheduler job in queue’s tasks that is runnable.

2.4. Processing Model

2.4.1. Queueing and Casting off Scheduler Duties

2.4.2. Scheduling Duties

To agenda a postTask job for Scheduler scheduler given a SchedulerPostTaskCallback callback and SchedulerPostTaskOptions choices, bustle the following steps:

  1. Let consequence be a brand unique promise.

  2. Let signal be choices[“signal“] if choices[“signal“] exists, or
    otherwise null.

  3. If signal is now not null and it is aborted, then reject consequence with signal’s abort reason and return consequence.

  4. Let priority be choices[“priority“] if choices[“priority“] exists, or
    otherwise null.

  5. Let queue be the cease consequence of selecting the scheduler job queue for scheduler given signal and priority.

  6. Let extend be choices[“delay“].

  7. If extend is elevated than 0, then bustle steps after a timeout given scheduler’s related world object, “scheduler-postTask“, extend, and the following steps:

    1. Schedule a role to invoke a callback for scheduler given queue, signal, callback, and consequence.

  8. Otherwise, agenda a role to invoke a callback for scheduler given queue, signal, callback, and consequence.

  9. Return consequence.

Flee steps after a timeout doesn’t necessarily yarn for suspension;
locate whatwg/html#5925.

To agenda a role to invoke a callback for Scheduler scheduler given a scheduler job queue queue, an AbortSignal or
null signal, a SchedulerPostTaskCallback callback, and a promise consequence:

  1. Let world be the related world object for scheduler.

  2. Let file be world’s related Doc if world is a Window object; otherwise null.

  3. Let enqueue enlighten be scheduler’s subsequent enqueue enlighten.

  4. Increment scheduler’s subsequent enqueue enlighten by 1.

  5. Let job be the cease consequence of queuing a scheduler job on queue given enqueue enlighten, the posted job job source, and file, and that
    performs the following steps:

    1. Let callback consequence be the cease consequence of invoking callback. If that
      threw an exception, then reject consequence with that, otherwise unravel consequence with callback consequence.

  6. If signal is now not null, then add the following abort
    steps to it:

    1. Fetch away job from queue.

    2. Reject consequence with signal’s abort reason.

Because this algorithm would perchance perchance be known as from in parallel steps, parts
of this and other algorithms are keen. Namely, the subsequent enqueue enlighten would perchance perchance simply soundless be updated atomically, and accessing
the scheduler job queues would perchance perchance simply soundless happen atomically. The latter furthermore impacts
the match loop job queues (locate this field).

2.4.3. Deciding on the Subsequent Job to Flee

2.5. Examples

TODO(shaseley): Add examples.

3. Controlling Duties

Duties scheduled by the Scheduler interface would perchance perchance be managed with a TaskController by passing the TaskSignal supplied by controller.signal because the likelihood when calling postTask().
The TaskController interface supports aborting and changing the priority of
a role or crew of tasks.

3.1. The TaskPriorityChangeEvent Interface

[Exposed=(Window, Worker)]
interface TaskPriorityChangeEvent : Occasion {
  constructor(DOMString form, TaskPriorityChangeEventInit priorityChangeEventInitDict);

  readonly attribute TaskPriority previousPriority;

dictionary TaskPriorityChangeEventInit : EventInit {
  required TaskPriority previousPriority;
match . previousPriority

Returns the TaskPriority of the corresponding TaskSignal sooner than
this prioritychange match.

The unique TaskPriority would perchance perchance be read with match.aim.priority.

The previousPriority getter
steps are to return the payment that the corresponding attribute modified into as soon as initialized

3.2. The TaskController Interface

dictionary TaskControllerInit {
  TaskPriority priority="user-visible";

interface TaskController : AbortController {
  constructor(optional TaskControllerInit init={});

  undefined setPriority(TaskPriority priority);

Demonstrate: TaskController‘s signal getter, which is
inherited from AbortController, returns a TaskSignal object.

controller=unique TaskController( init )

Returns a brand unique TaskController whose signal is
situation to a newly created TaskSignal with its priority initialized to init’s priority.

controller . setPriority( priority )

Invoking this suggests will commerce the related TaskSignal‘s priority, signal the priority commerce to any observers, and
situation off prioritychange occasions to be dispatched.

The setPriority(priority) skill steps are to signal priority commerce on this‘s signal given priority.

3.3. The TaskSignal Interface

[Exposed=(Window, Worker)]
interface TaskSignal : AbortSignal {
  readonly attribute TaskPriority priority;

  attribute EventHandler onprioritychange;

Demonstrate: TaskSignal inherits from AbortSignal and would perchance perchance be dilapidated in APIs that
acquire an AbortSignal. Moreover, postTask() accepts an AbortSignal, that will doubtless be vital if dynamic prioritization is now not wanted.

signal . priority

Returns the TaskPriority of the signal.

A TaskSignal object has an related TaskPriority priority.

A TaskSignal object has an related priority changing boolean, intially situation to pretend.

A TaskSignal object has related priority commerce algorithms,
which is a situation of algorithms, initialized to a brand unique empty situation. These
algorithms are to be executed when its priority changing payment
is real.

The priority getter steps are to return this‘s priority.

The onprioritychange attribute
is an match handler IDL attribute for the onprioritychange match handler, whose match handler match form is prioritychange.

To add a priority commerce algorithm algorithm to a TaskSignal object signal, append algorithm to signal’s priority commerce algorithms.

3.4. Examples

TODO(shaseley): Add examples.

4. Changes to Diversified Standards

4.1. The HTML Normal

4.1.1. WindowOrWorkerGlobalScope

Each and each object implementing the WindowOrWorkerGlobalScope mixin has a
corresponding scheduler, which
is initialized as a brand unique Scheduler.

partial interface mixin WindowOrWorkerGlobalScope {
  [Replaceable] readonly attribute Scheduler scheduler;

The scheduler attribute’s
getter steps are to return this‘s scheduler.

4.1.2. Occasion loop: definitions

Change: For each and each match loop, every job source would perchance perchance simply soundless be related to
a divulge job queue.

With: For each and each match loop, every job source that is now not a scheduler job source would perchance perchance simply soundless be related to a divulge job queue.

4.1.3. Occasion loop: processing mannequin

Add the following steps to the match loop processing steps, earlier than step 1:

  1. Let queues be the situation of the match loop‘s job queues that
    maintain now not decrease than one runnable job.

  2. Let schedulers be the situation of all Scheduler objects whose related agent’s match loop is that this match loop and that cling a runnable job.

  3. If schedulers and queues are each and each empty, skip to the microtasks step below.

Modify step 1 to read:

  1. Let taskQueue be undoubtedly one of many following, chosen in an implementation-outlined formula:

The taskQueue on this step will both be a situation of tasks or a situation of scheduler tasks. The steps that modify to simplest elevate away an item, in speak that they’re roughly successfully matched. Ideally, there would be a
overall job queue interface that supports a pop() skill that would perchance perchance return a
undeniable job, but that would perchance perchance invlove an even quantity of refactoring.

5. Security Concerns

This allotment is non-normative.

The vital security consideration for the APIs outlined on this specification is
whether or now not any data is perchance leaked between origins by
timing-basically basically based facet-channel assaults.

5.1. postTask as a High-Resolution Timing Source

This API can not be dilapidated as a excessive-resolution timing source. Esteem setTimeout()‘s timeout payment, postTask()‘s extend is expressed in
entire milliseconds (the minimal non-zero extend being 1 ms), so callers can not
divulge any timing more proper than 1 ms. Additional, since tasks are queued when
their extend expires and now not bustle straight, the precision accessible to callers
is extra reduced.

5.2. Monitoring One other Origin’s Duties

The second consideration is whether postTask() leaks any
facts about other origins’ tasks. We elevate into consideration an attacker working on one
starting up looking out to operate facts about code executing in a single other starting up (and
therefore in a separate match loop) that is scheduled within the comparable thread in a

Because a thread inside a UA can simplest bustle tasks from one match loop at a time,
an attacker would perchance perchance simply secure a scheme to manufacture facts about tasks working in a single other
match loop by monitoring when their tasks bustle. As an instance, an attacker would perchance perchance
flood the machine with tasks and demand them to bustle consecutively; if there are
enormous gaps in between, then the attacker would perchance perchance infer that one other job ran,
perchance in a special match loop. The working out uncovered in such a case
would rely on implementation dinky print, and implementations can minimize the
quantity of data as described below.

What Files May well perchance Be Won?
Concretely, an attacker would secure a scheme to detect when other tasks are executed
by the browser by both flooding the machine with tasks or by recursively
scheduling tasks. Here is a acknowledged attack that would perchance perchance be executed with existing APIs indulge in postMessage(). The tasks that bustle quite than the attacker’s would perchance perchance be
tasks in other match loops as successfully as other tasks within the attacker’s match loop,
in conjunction with inside UA tasks (e.g. garbage sequence).

Assuming the attacker can resolve with a excessive diploma of likelihood that the
job executing is in a single other match loop, then the request becomes what
extra data can the attacker learn? Since inter-match-loop job
choice is now not specified, this data will doubtless be implementation-dependent
and depends on how U.s.a.enlighten tasks between match loops. Nonetheless U.s.a.that exercise a
prioritization procedure that treats match loops sharing a thread as a single
match loop are inclined to exposing more data.

It is vital to deem the situation of doable tasks that a UA would perchance perchance
elevate quite than the attacker’s, which corresponds to the straightforward job received.
When an attacker floods the machine with tasks, the placement of that chances are high you’ll perchance agree with tasks would
be the rest the UA deems to be greater priority at that second. This would perchance perchance be
the cease consequence of a static prioritization procedure, e.g. enter is all the time absolute top
priority, network is second absolute top, and so forth., or this is also more dynamic, e.g.
the UA typically chooses to bustle tasks from other job sources relying on
how lengthy they’ve been starved. The utilization of a dynamic procedure increases the placement of doable
job which in flip decreases the fidelity of the straightforward job.

postTask() supports prioritization for tasks scheduled with it.
How these tasks are interleaved with other job sources is furthermore
implementation-dependent, but it completely would perchance perchance simply be that chances are high you’ll perchance agree with for an attacker to
extra minimize the placement of doable tasks that can bustle quite than its have by
leveraging this priority. As an instance, if a UA uses a straightforward static
prioritization procedure spanning all match loops in a thread, then the utilization of user-blocking postTask() tasks quite than postMessage() tasks would perchance perchance decrease
this situation, relying on their relative prioritization and what’s between.

What Mitigations are Doable?
There are mitigations that implementers can elevate into consideration to slit back the wretchedness:

  • The build that chances are high you’ll perchance agree with, isolate cross-starting up match loops by working them in different
    threads. This type of attack depends on the match loops sharing a thread.

  • Use an inter-match-loop scheduling protection that is now not strictly in accordance to
    priority. As an instance, an implementation would perchance perchance exercise spherical-robin or
    honest-scheduling between match loops to cease leaking facts about
    job priority. One other likelihood is to execute definite decrease priority tasks are
    periodically cycled in to cease inferring priority data.

6. Privateness Concerns

This allotment is non-normative.

Now we cling evaluated the APIs outlined on this specification from a privacy
perspective and attain now not agree with there to be any privacy concerns.


Doc conventions

Conformance necessities are expressed
with a combination of descriptive assertions
and RFC 2119 terminology.
within the normative parts of this file
are to be interpreted as described in RFC 2119.
Nonetheless, for readability,
these words attain now not seem in all uppercase letters on this specification.

All of the textual sigh material of this specification is normative
except for sections explicitly marked as non-normative, examples, and notes. [RFC2119]

Examples on this specification are introduced with the words “as an illustration”
or are situation except for the normative textual sigh material
with class="instance",
indulge in this:

Here is an instance of an informative instance.

Informative notes begin with the note “Demonstrate”
and are situation except for the normative textual sigh material
with class="repeat",
indulge in this:

Demonstrate, right here is an informative repeat.

Conformant Algorithms

Necessities phrased within the imperative as allotment of algorithms
(equivalent to “strip any main area characters”
or “return pretend and abort these steps”)
are to be interpreted with the that skill of the principle note
(“must”, “would perchance perchance simply soundless”, “would perchance perchance simply”, and so forth)
dilapidated in introducing the algorithm.

Conformance necessities phrased as algorithms or divulge steps
would perchance perchance be implemented in any formula,
so lengthy because the cease consequence’s comparable.
In divulge, the algorithms outlined on this specification
are supposed to be straightforward to label
and are now not supposed to be performant.
Implementers are impressed to optimize.

Read More

Ava Chan

Ava Chan

I'm a researcher at Utokyo :) and a big fan of Ava MaxBio: About: