Copyright © 2024 World Wide Web Consortium . W3C ® liability , trademark and permissive document license rules apply.
The Compute Pressure API provides a way for websites to react to changes in the CPU pressure of the target device, such that websites can trade off resources for an improved user experience.
This section describes the status of this document at the time of its publication. A list of current W3C publications and the latest revision of this technical report can be found in the W3C technical reports index at https://www.w3.org/TR/.
This document was published by the Devices and Sensors Working Group as an Editor's Draft.
Publication as an Editor's Draft does not imply endorsement by W3C and its Members.
This is a draft document and may be updated, replaced or obsoleted by other documents at any time. It is inappropriate to cite this document as other than work in progress.
This document was produced by a group operating under the W3C Patent Policy . W3C maintains a public list of any patent disclosures made in connection with the deliverables of the group; that page also includes instructions for disclosing a patent. An individual who has actual knowledge of a patent which the individual believes contains Essential Claim(s) must disclose the information in accordance with section 6 of the W3C Patent Policy .
This document is governed by the 03 November 2023 W3C Process Document .
This section is non-normative.
Modern applications often need to balance the trade offs and advantages of fully utilizing the system's computing resources, in order to provide a modern and delightful user experience.
As an example, many applications can render video effects with varying degrees of sophistication. These applications aim to provide the best user experience, while avoiding driving the user's device into a high pressure regime.
Utilization of processing units close to and often reaching 100% can lead to a bad user experience, as different tasks are fighting for the processing time. This can lead to slowless, which is especially noticeable with input delay. Further, a prolonged utilization close 100% can cause the processing units to heat up due to prolonged boosting, which can lead to throttling, resulting in an even worse user experience.
As a result of thermal limits, many smartphones, tablets and laptops can become uncomfortably hot to the touch. The fans in laptops and desktops can become so loud that they disrupt conversations or the users’ ability to focus.
In many cases, a device under high pressure appears to be unresponsive, as the operating system may fail to schedule the threads advancing the task that the user is waiting for. See also Use Cases .
This section is non-normative.
Feature detection is an established web development best practice. Resources on the topic are plentiful on- and offline and the purpose of this section is not to discuss it further, but rather to put it in the context of detecting hardware-dependent features.
Consider the below feature detection examples:
This specification defines the following concepts:
Computing devices consist of a multitude of different processing units such as the Central Processing Unit (CPU), the Graphics Processing Unit (GPU) and many specialized processing units. The latter are becoming popular such as ones designed to accelerate specific tasks like machine learning or computer vision.
The specification currently defines the valid source types as global system thermals and the central processing unit , also known as the CPU. Future levels of this specification MAY introduce additional source types .
WebIDL
enum
PressureSource
{
"
thermals
"
,
"
cpu
"
};
The
PressureSource
enum
represents
the
valid
source
types
:
thermals
"
represents
the
global
thermal
state
of
the
system.
cpu
"
represents
the
average
pressure
of
the
central
processing
unit
across
all
its
cores.
The requested sampling interval represents the desired interval between samples to be obtained from the hardware, expressed in milliseconds.
Interval and frequency are inverses of each other, so the requested sampling interval can also be expressed as a requested sampling rate in Hertz (cycles per second) by dividing 1000 by the requested sampling interval value.
The sampling rate for a platform collector is defined as a rate at which the user agent obtains telemetry readings from the underlying platform, and it might differ from the pressure observers' requested sampling rates . The rate is measured in Hertz (cycles per second).
The
reporting
rate
for
a
pressure
observer
is
the
rate
at
which
it
runs
the
data
delivery
collection
steps,
and
it
will
never
exceed
the
sampling
rate
.
The sampling rate differs from the requested sampling rate when the requested sampling rate exceeds upper or lower sampling rate bounds supported or accepted by the underlying platform and user agent † .
† It is recommended that the user agent limits the reporting rate as outlined in 11.2.2 Rate-limiting change notifications .
In case the user didn't request a sampling rate , the sampling rate is implementation-defined .
The
platform
collector
A
pressure
source
is
an
abstract,
implementation-defined
refers
interface
to
hardware
counters
or
an
underlying
framework
that
provides
telemetry
data
about
a
platform
interface,
source
type
defined
by
PressureSource
.
A
pressure
source
can
make
use
of
data
fusion
with
which
data
from
additional
sources
if
that
provides
more
precise
results.
The
telemetry
data
provided
by
a
pressure
source
is
represented
in
this
specification
as
a
pressure
source
sample
,
a
struct
consisting
of
the
user
agent
following
items
:
PressureState
.
A
platform
collector
pressure
source
can
be
defined
by
the
underlying
platform
(e.g.
in
has
an
associated
latest
sample
,
a
native
telemetry
framework)
pressure
source
sample
or
by
null.
It
is
initially
null.
A
platform
collector
is
an
abstract
interface
responsible
for
obtaining
telemetry
samples
from
a
pressure
source
,
transforming
them
into
pressure
states
and
providing
them
to
the
user
agent
,
if
it
has
a
direct
access
to
hardware
counters.
.
A
platform
collector
can
support
telemetry
for
different
has
the
following
associated
data:
The
format
of
computing
devices
defined
the
telemetry
data
provided
by
PressureSource
a
pressure
source
and
stored
in
its
latest
sample
's
data
is
implementation-defined
,
or
there
can
be
multiple
and
so
is
the
process
through
which
a
platform
collectors
collector
transforms
it
into
a
pressure
state
.
From
the
implementation
perspective
For
this
specification's
purposes,
platform
collector
collectors
can
be
treated
as
a
software
proxy
for
the
corresponding
hardware
counters.
It
is
possible
are
scoped
to
have
multiple
platform
collector
a
global
object
simultaneously
interacting
with
the
same
underlying
hardware
if
via
the
underlying
platform
supports
it.
collector
mapping
.
In
simple
cases,
For
automation
purposes,
a
platform
collector
represents
individual
hardware
counters,
but
if
must
have
the
provided
counter
readings
are
a
product
of
ability
to
connect
to
virtual
pressure
sources
and
use
their
simulated
data
fusion
performed
in
software,
the
platform
collector
represents
the
results
of
the
as
pressure
states
rather
than
raw
platform
data
fusion
process.
This
may
happen
in
user
space
or
in
kernel
space.
that
must
be
transformed
into
an
adjusted
pressure
state
.
As collecting telemetry data often means polling hardware counters, it is not a free operation and thus, it should not happen if there are no one observing the data. See 10.5 Life-cycle and garbage collection for more information.
A platform collector samples data at a specific rate. A user agent may modify this rate (if possible) for privacy reasons, or ignore and fuse certain readings.
It is RECOMMENDED that a user agent show some form of user-visible notification that informs the user when a pressure observer is active, as well as provides the user with the means to block the ongoing operation, or simply dismiss the notification.
The
Compute
Pressure
API
defines
a
policy-controlled
feature
identified
by
the
token
"compute-pressure".
Its
default
allowlist
is
'self'
.
Workers (dedicated and shared) adhere to the permission policy set by their owning document(s).
Shared workers often have multiple owning documents as they can be obtained by other documents with the same origin . In this case, all owning documents must be allowed to use the policy-controlled feature defined by this specification.
Dedicated workers can be created from other workers, in which case the permission policy of the first owning document (or owning documents, in case of a shared worker) up the owner chain will be used.
Each global object has:
PressureObserver
object).
The user agent has:
PressureSource
values.
A
constructed
PressureObserver
object
has
the
following
internal
slots:
PressureUpdateCallback
set
on
creation.
PressureSource
string
and
promise
holds
a
Promise
object.
PressureRecord
objects,
which
is
initially
empty.
PressureSource
to
the
latest
PressureRecord
.
PressureSource
to
positive
numbers.
It
represents
the
sample
interval
given
source
type.
For
the
rate
obfuscation
mitigation
the
constructed
PressureObserver
object
additionally
has
the
following
internal
slots:
PressureSource
,
representing
the
source
type
that
triggered
transition
to
the
current
pressure
state
.
The
ordered
map
's
value
is
an
integer
representing
the
number
of
state
changes
in
the
current
observation
window
timeframe.
PressureSource
,
representing
the
source
type
of
the
last
PressureRecord
.
The
ordered
map
's
value
is
a
PressureRecord
.
Pressure states represents the minimal set of useful states that allows websites to react to changes in compute and system pressure with minimal degration in quality or service, or user experience.
WebIDL
enum
PressureState
{
"
nominal
"
,
"
fair
"
,
"
serious
"
,
"
critical
"
};
The
PressureState
enum
represents
the
pressure
state
with
the
following
states:
nominal
":
The
conditions
of
the
target
device
are
at
an
acceptable
level
with
no
noticeable
adverse
effects
on
the
user.
fair
":
Target
device
pressure,
temperature
and/or
energy
usage
are
slightly
elevated,
potentially
resulting
in
reduced
battery-life,
as
well
as
fans
(or
systems
with
fans)
becoming
active
and
audible.
Apart
from
that
the
target
device
is
running
flawlessly
and
can
take
on
additional
work.
serious
":
Target
device
pressure,
temperature
and/or
energy
usage
is
consistently
highly
elevated.
The
system
may
be
throttling
as
a
countermeasure
to
reduce
thermals.
critical
":
The
temperature
of
the
target
device
or
system
is
significantly
elevated
and
it
requires
cooling
down
to
avoid
any
potential
issues.
Contributing factors represent the underlying hardware metrics contributing to the current pressure state and can be implementation-defined .
The adjusted pressure state is a pressure state determined by an implementation-defined algorithm that takes as input source type and any other implementation-defined data from contributing factors . This algorithm MUST not be deterministic to ensure break calibration mitigation effectiveness.
The change in contributing factors is substantial steps are as follows:
PressureUpdateCallback
callback
WebIDLcallback PressureUpdateCallback
= undefined (
sequence<PressureRecord
> changes,
PressureObserver
observer
);
This
callback
will
be
invoked
when
the
pressure
state
changes.
PressureObserver
object
The
PressureObserver
can
be
used
to
observe
changes
in
the
pressure
states
.
WebIDL[Exposed=(DedicatedWorker,SharedWorker,Window), SecureContext]
interface PressureObserver
{
constructor
(PressureUpdateCallback
callback);
Promise<undefined> observe
(PressureSource
source, optional PressureObserverOptions
options = {});
undefined unobserve
(PressureSource
source);
undefined disconnect
();
sequence<PressureRecord
> takeRecords
();
[SameObject] static readonly attribute FrozenArray<PressureSource
> knownSources
;
};
The
PressureObserver
interface
represents
a
PressureObserver
.
The
new
PressureObserver
(
callback
)
constructor
steps
are:
[[Callback]]
to
callback
.
The
observe
(
source
,
options
)
method
steps
are:
NotAllowedError
.
[[SampleIntervalMap]]
[
source
]
to
options
's
sampleInterval
.
[[PendingObservePromises]]
.
[[PendingObservePromises]]
.
NotSupportedError
and
abort
these
steps.
The
unobserve
(
source
)
method
steps
are:
NotSupportedError
".
[[QueuedRecords]]
all
records
associated
with
source
.
[[SampleIntervalMap]]
[
source
].
[[LastRecordMap]]
[
source
].
[[AfterPenaltyRecordMap]]
[
source
].
[[PendingObservePromises]]
,
if
source
is
equal
to
promiseSource
,
reject
pendingPromise
with
an
AbortError
.
The
disconnect
()
method
steps
are:
[[QueuedRecords]]
.
[[SampleIntervalMap]]
.
[[LastRecordMap]]
.
[[AfterPenaltyRecordMap]]
.
[[PendingObservePromises]]
,
reject
pendingPromise
with
an
AbortError
.
The
takeRecords
()
method
steps
are:
[[QueuedRecords]]
.
[[QueuedRecords]]
.
The
knownSources
getter
steps
are:
WebIDL[Exposed=(DedicatedWorker,SharedWorker,Window), SecureContext]
interface PressureRecord
{
readonly attribute PressureSource
source
;
readonly attribute
readonly attribute PressureState
state
;
readonly attribute DOMHighResTimeStamp time
;
[Default] object toJSON
();
};
A
constructed
PressureRecord
object
has
the
following
internal
slots:
PressureSource
,
which
represents
the
current
source
type
.
PressureState
,
which
represents
the
current
pressure
state
.
DOMHighResTimeStamp
,
which
corresponds
to
the
time
the
data
was
obtained
from
the
system,
relative
to
the
time
origin
of
the
global
object
associated
with
the
PressureObserver
instance
that
generated
the
notification.
The
source
getter
steps
are
to
return
its
[[Source]]
internal
slot.
The
state
getter
steps
are
to
return
its
[[State]]
internal
slot.
The
time
getter
steps
are
to
return
its
[[Time]]
internal
slot.
When
PressureRecord
.
toJSON
is
called,
run
Web
IDL
Standard
's
default
toJSON
steps
.
WebIDLdictionary PressureObserverOptions
{
[EnforceRange] unsigned long sampleInterval
= 0;
};
The
sampleInterval
member
represents
the
requested
sampling
interval
expressed
in
milliseconds.
Each global object has a strong reference to registered observers in their registered observer list (one per source).
This section outlines the steps the user agent must take when implementing the specification.
The reset observation window steps given the argument observer , are as follows:
[[ObservationWindow]]
to
an
implementation-defined
randomized
integer
value
in
milliseconds
within
an
implementation-defined
range.
[[MaxChangesThreshold]]
to
an
implementation-defined
randomized
integer
value
of
maximum
allowed
changes
within
the
observationWindow
within
an
implementation-defined
range.
[[PenaltyDuration]]
to
an
implementation-defined
randomized
integer
value
in
milliseconds,
within
an
implementation-defined
range.
[[ChangesCountMap]]
map.
[[ObservationWindow]]
time
has
passed,
using
different
randomized
values.
To determine the owning document set for a relevant global object relevantGlobal :
Window
,
then
append
relevantGlobal
's
associated
document
to
owningDocumentSet
.
WorkerGlobalScope
relevantGlobal
's
owner
set
:
Document
,
then
append
owner
to
owningDocumentSet
.
WorkerGlobalScope
,
set
owningDocumentSet
to
the
union
of
owningDocumentSet
and
owner
's
owning
document
set
.
The document has implicit focus steps given the argument document , are as follows:
The may receive data steps given the argument observer are as follows:
Window
object:
WorkerGlobalScope
object:
The passes rate test steps given the argument observer , source and timestamp , are as follows:
[[LastRecordMap]]
[
source
]
does
not
exist
,
return
true.
[[LastRecordMap]]
[
source
].
[[SampleIntervalMap]]
[
source
].
[[Time]]
.
[[LastRecordMap]]
[
source
]
does
not
exist
,
return
true.
[[LastRecordMap]]
[
source
].
[[State]]
is
not
equal
to
state
and
change
in
contributing
factors
is
substantial
returns
true,
return
true.
[[ChangesCountMap]]
[
source
].
[[ChangesCountMap]]
[
source
]
≤
observer.
[[MaxChangesThreshold]]
.
To get a virtual pressure source , given a source type source and relevantGlobal , perform the following steps. They return a virtual pressure source or null.
Window
object:
DedicatedWorkerGlobalScope
object:
Data
delivery
from
To
activate
data
collection
given
a
source
type
source
and
relevantGlobal
,
perform
the
following
steps:
The
To
deactivate
data
delivery
collection
steps
that
are
run
when
an
implementation-defined
given
a
source
type
data
source
sample
of
and
relevantGlobal
,
perform
the
following
steps:
The data collection steps given relevantGlobal , source and platformCollector are as follows:
PressureRecord
object
with
its
[[Source]]
set
to
source
,
[[State]]
set
to
state
and
[[Time]]
set
to
timeValue
.
[[AfterPenaltyRecordMap]]
[source]
exists
:
[[AfterPenaltyRecordMap]]
[
source
]
to
record
.
[[AfterPenaltyRecordMap]]
[
source
]
to
record
.
[[ChangesCountMap]]
[
source
]
to
0.
[[PenaltyDuration]]
duration
with
the
following
callback:
[[AfterPenaltyRecordMap]]
[source]
exists
:
[[AfterPenaltyRecordMap]]
[
source
].
[[AfterPenaltyRecordMap]]
[
source
].
To queue a record given the arguments observer , source , record , run these steps:
[[QueuedRecords]]
is
greater
than
max
queued
records
,
then
remove
the
first
item
.
[[QueuedRecords]]
.
[[LastRecordMap]]
[
source
]
to
record
.
The PressureObserver task source is a task source used for scheduling tasks to 10.6.5 Notify Pressure Observers .
To queue a pressure observer task given relevantGlobal as input, run these steps:
To notify pressure observers given relevantGlobal as input, run these steps:
[[QueuedRecords]]
.
[[QueuedRecords]]
.
[[Callback]]
with
records
and
observer
.
If
this
throws
an
exception,
catch
it,
and
report
the
exception
.
This
specification
defines
the
following
unloading
document
cleanup
steps
given
a
Document
document
:
This
specification
previously
included
steps
covering
the
case
of
a
Document
becoming
fully
active
again
(i.e.
integration
with
Document
's
reactivate
steps).
Those
steps
have
been
removed
while
the
intended
behavior
is
discussed.
Whenever
a
WorkerGlobalScope
relevantGlobal
's
closing
flag
is
set
to
true,
perform
the
following
steps:
It may be possible to identify users across non- same origin sites if unique or very precise values can be accessed at the same time by sites not sharing origin. This attack is mitigated by 11.2.1 Data minimization , 11.2.2 Rate-limiting change notifications , and 11.2.8 Same-origin restriction .
In computer security a covert channel creates a capability to transfer information between processes that are not supposed to be allowed to communicate. In modern multi-process web engines in the generic case each window or tab resides in its own process (documents that have the same origin or sites that have the same site typically share the same process). Using this API it may be possible to create a cross-site covert channel C where a site A on one tab first broadcasts to the channel C after having manipulated the state of the CPU. Next a site B (that is not same site with site A) on another tab reads the broadcasted data from the channel C by using this API to learn when the state of the CPU has changed. This process is repeated as long as the scripts run on both the sites A and B.
This attack is mitigated by 11.2.2 Rate-limiting change notifications , 11.2.3 Rate obfuscation and 11.2.6 Break calibration . Implementers are advised to consider all these mitigations for long-running scripts.
Targeted de-anonymization attacks constitute a critical class of threats that jeopardize a user's anonymity. These attacks allow a malicious or partially compromised website (referred to as the “malicious site”) to ascertain whether a website visitor possesses a specific public identifier, such as an email address or a social media handle.
While anonymity may be a luxury for some, for certain individuals, it is far more than that—it is a matter of survival. Consider for instance those who engage in political protests, work as journalists covering sensitive topics, etc.
As an example, an attacker can privately share a resource with the target for instance using a public resource sharing service (“victim site”), and then measure side-effects (indicating successful access) on loading the resource via side-channels. If the logged in visitor can access the embedded resource successfully, that indicates that the current visit is indeed the intended target.
Specifically, exposing reliable information about the total CPU pressure can let an attacking site understand if a target of a cross-origin navigation (e.g. an iframe or pop-up window from another site) performed a CPU-intensive operation.
Techniques such as pop-under and tab-under can be used to hide the loading from the user.
One possible attack is that the malicious website opens e.g., a popup to a resource on a victim site to which the user is logged in (e.g. a video streaming site or online document editor) pointing to a resource shared with specific users.
Assuming that loading the resource puts increased pressure on the CPU, this would create a side-channel reveals to the attacking site if the user is logged into an account with access to the resource, deanonymizing the user.
Given that modern CPUs recover quickly from high pressure, one possible mitigation strategy could be to temporarily disable readings for a few seconds after loading popup and iframe content.
This specification adheres to the generic data minimization principles to limit exposure of data related to low-level details of the underlying platform to the minimum required to address its high-value use cases. This includes consideration for limiting exposure of identifying information about devices .
The specific application of data minimization principles in the context of this specification are discussed in 11.2.2 Rate-limiting change notifications and 11.2.8 Same-origin restriction .
By rate-limiting the delivery of the pressure state information we remove the attacker's ability to observe the precise time when a value transitions between two states.
More precisely, once the pressure observer is activated, it will be called once with initial values, and then is called when the values change. The subsequent calls will be rate-limited. When the callback is called, the most recent value is reported.
The specification will recommend a rate limit of at most one call per second for the active window, and one call per 10 seconds for all other windows. We will also recommend that the call timings are jittered across origins.
These measures benefit the user's privacy, by reducing the risk of identifying a device across multiple origins. The rate-limiting also benefits the user's security, by making it difficult to use this API for timing attacks. Last, rate-limiting change callbacks places an upper bound on the performance overhead of this API.
Rate limiting can be implemented in the user agent, but it might also be possible to simply change the polling/sampling rate of the underlying hardware counters, if not accessed via a higher level framework.
The specification requires implementing the rate obfuscation mitigation to keep track of the number of pressure changes over an implementation-defined sliding observation window and set a flag if an implementation-defined threshold for the number of pressure changes is exceeded. Similarly, it is also recommended for the implementation to observe any abnormal activity such as a high number of pressure state changes spanning across multiple states, and set this flag similarly.
If this flag is set, the implementation is recommended to give the pressure observer a penalty during which it will not be able to inform scripts of changes in its pressure state as it normally would. The duration of this penalty is implementation-defined and it is recommended to be randomized. When notify pressure observers resumes operation after the penalty, it only reports the latest pressure state and disregards any interim state information received from the platform collector during this penalty.
Based on implementation experience, implementers must use:
[[MaxChangesThreshold]]
internal
slot.
[[PenaltyDuration]]
internal
slot.
This section is non-normative.
Based on implementation experience, implementers are advised to use:
[[ObservationWindow]]
internal
slot.
In a calibration process an attacker tries to manipulate the CPU so that this API would report a transition into a certain pressure state with the highest probability in response to the pressure exerted by the fabricated workload. This break calibration mitigation solution can slow down or prevent this calibration process from succeeding by slightly changing at runtime the implementation-defined low-level hardware metrics that contribute to these pressure state transitions. Even if the initial calibration would succeed, its results will be invalidated at runtime when this mitigation is running continuously. Any attempts to recalibrate will similarly be mitigated against.
This section is non-normative.
Based on implementation experience, implementers are advised to apply the mitigation to a randomized time value within a range between 120000 milliseconds (2 minutes) and 240000 milliseconds (4 minutes).
By default data delivery is restricted to documents served from the same-origin as an initiator of an active picture-in-picture-session , documents capturing or the document with system focus , if any.
The documents qualifying for data delivery, under the above rules, can delegate it to documents in child navigables .
The feature can be extended to third-party contexts such as iframes only by a declared policy .
Shared workers can be shared across documents, such as top level document and those associated iframes. If one of the documents in the owner set passes the above data delivery requirements, the shared worker will qualify for data delivery. This means that the embedded iframe is able to pass along the data to the embedding document.
The Compute Pressure API is focused on improving the user experience. There are two ways in which applications that build on the API can positively impact accessibility.
As a consumer of the API, it's important to consider both of these opportunities. Here are some examples:
The Compute Pressure API poses a challenge to test authors, as fully exercising interface requires physical hardware devices that respond in predictable ways.
To address this challenge this document defines a [ WEBDRIVER2 ] extension commands that allows defining and controlling virtual pressure sources that behave like real ones and which can have particular properties and whose readings can be entirely defined by users.
A virtual pressure source is a pressure source that simulates the behavior of a real one in controlled ways. It reports pressure changes to zero or more platform collectors connected to it.
Contrary
to
a
real
pressure
source
,
however,
it
reports
pressure
state
values
directly
instead
of
implementation-defined
values
that
must
be
processed
into
pressure
states
by
a
platform
collector
.
In
other
words,
a
virtual
pressure
source
's
pressure
source
sample
's
data
is
a
PressureState
.
In addition to the data associated with all pressure sources (such as pressure source sample ), each virtual pressure source has:
Each top-level traversable has a virtual pressure source mapping , which is an ordered map of source types to virtual pressure source .
HTTP Method | URI Template |
---|---|
POST | /session/{session id}/pressuresource |
This
extension
command
creates
a
new
virtual
pressure
source
of
a
specified
source
type
.
Calls
to
observe
()
from
PressureObserver
instances
of
the
same
source
type
will
cause
this
virtual
pressure
source
to
be
used
as
their
backing
pressure
source
until
13.1.1.2
Delete
virtual
pressure
source
is
run.
Parameter name | Value type | Required |
---|---|---|
type | String | yes |
supported | Boolean | no |
The remote end steps given session , URL variables and parameters are:
HTTP Method | URI Template |
---|---|
DELETE | /session/{session id}/pressuresource/{type} |
This extension command deletes a given virtual pressure source , meaning that, if available, data for the given source type will be delivered the regular way, by non-virtual means.
The remote end steps given session , URL variables and parameters are:
HTTP Method | URI Template |
---|---|
POST | /session/{session id}/pressuresource/{type} |
This extension command allows updating the state of a virtual pressure source by pushing a new pressure source sample .
Parameter name | Value type | Required |
---|---|---|
sample |
PressureState
| yes |
The remote end steps given session , URL variables and parameters are:
PressureState
,
return
error
with
WebDriver
error
code
invalid
argument
.This section is non-normative.
const samples = [];
function pressureChange(records, observer) {
for (const record of records) {
samples.push(record.state);
// We only want 20 samples.
if (samples.length == 20) {
observer.disconnect();
return;
}
}
}
const observer = new PressureObserver(pressureChange);
observer.observe(
"cpu"
);
In the following example we want to lower the number of concurrent video streams when the pressure becomes critical. For the sake of simplicity we only consider this one state.
As lowering the amount of streams might not result in exiting the critical state, or at least not immediately, we use a strategy where we lower one stream at the time every 30 seconds while still in the critical state.
We accomplish this by making sure the callback is called at least once every 30 seconds, or when the state actually changes. When the state changes we reset the interval timer.
let timerId = -1;
function pressureChange(records) {
// Clear timer every time we are called, either by an actual state change,
// or when called by setTimeout (see below).
if (timerId > 0) {
clearTimeout(timerId);
}
// When entering critical state, we want to recheck every 30sec if we are
// still in critical state and if so, further reduce our concurrent streams.
// For this reason we create a timer for 30 seconds that will call us back
// with the last result in there were no change.
const lastRecordArray = [records.at(records.length - 1)];
timerId = setTimeout(pressureChange.bind(this, lastRecordArray), 30_000);
for (const record of records) {
if (record.state == "critical") {
let streamsCount = getStreamsCount();
setStreamsCount(streamsCount--);
}
}
}
const observer = new PressureObserver(pressureChange);
observer.observe(
"cpu"
);
In
the
following
example,
we
want
to
demonstrate
the
usage
of
takeRecords
()
,
by
retrieving
the
remaining
records
accumulated
since
the
the
callback
was
last
invoked.
It
is
recommended
to
do
so
before
disconnect
()
,
otherwise
disconnect
()
will
clear
them
and
they
will
be
lost
forever.
For example, we might want to measure the pressure during a benchmarking workload, and thus want pressure telemetry for the exact duration of the workload. This means disconnecting all observers immediately when the task is completed, and manually requesting any pending pressure telemetry up to this point that might not have been delivered yet as part of the event loop cycle.
function logWorkloadStatistics(records) {
// do something with records.
}
const observer = new PressureObserver(logWorkloadStatistics);
observer.observe("cpu");
// Read pending state change records, otherwise they will be cleared
// when we disconnect.
const records = observer.takeRecords();
logWorkloadStatistics(records);
observer.disconnect();
In
the
following
example,
we
show
how
to
tell
the
observer
to
stop
watching
a
specific
source
by
invoking
unobserve
()
with
source
.
const observer = new PressureObserver(records => { /* do something with records. */ });
observer.observe("cpu");
observer.observe("gpu");
// Callback now gets called whenever the pressure state changes for 'cpu' or 'gpu'.
observer.unobserve("gpu");
//
Callback
now
only
gets
called
whenever
the
pressure
state
changes
for
'cpu'.
In
the
following
example,
we
show
how
to
tell
the
observer
to
stop
watching
for
any
state
changes
by
calling
disconnect
()
.
Calling
disconnect
()
will
stop
observing
all
sources
observed
by
previous
observe
()
calls.
Additionally it will clear all pending records collected since the last callback was invoked.
const observer = new PressureObserver(records => { // do something with records. });
observer.observe("cpu");
observer.observe("gpu");
// some time later...
observer.disconnect();
// records will be an empty array, because of the previous disconnect().
const
records
=
observer.takeRecords();
As well as sections marked as non-normative, all authoring guidelines, diagrams, examples, and notes in this specification are non-normative. Everything else in this specification is normative.
The key words MAY , MUST , and RECOMMENDED in this document are to be interpreted as described in BCP 14 [ RFC2119 ] [ RFC8174 ] when, and only when, they appear in all capitals, as shown here.
This specification defines conformance criteria for a single product: a user agent that implements the interfaces that it contains.
This section is non-normative.
Many thanks for valuable feedback and advice from Anssi Kostiainen, Asaf Yaffe, Chen Xing, Evan Shrubsole, Florian Scholz, François Beaufort, Jan Gora, Jesse Barnes, Joshua Bell, Kamila Hasanbega, Matt Menke, Moh Haghighat, Nicolás Peña Moreno, Opal Voravootivat, Paul Jensen, Peter Djeu, Raphael Kubo da Costa, Reilly Grant, Ulan Degenbaev, Victor Miura, Wei Wang, and Zhenyao Mo
Thanks to the W3C Privacy Interest Group (PING) and especially Peter Snyder for the privacy review, feedback and the proposed cross-site covert channel attack and its mitigations. Similarly thanks to Ehsan Toreini for his work on the privacy of private browsing and related contributions to this specification.
Special thanks to Amanda Zhao, Fidel Tian, Zhiliang Wang and others from the Zoom engineering team for the feedback and hands-on experiments that have helped improve this API in real-world scenarios.
[[AfterPenaltyRecordMap]]
internal
slot
for
PressureObserver
§7.
[[Callback]]
internal
slot
for
PressureObserver
§7.
[[ChangesCountMap]]
internal
slot
for
PressureObserver
§7.
constructor()
for
PressureObserver
§10.2.1
"cpu"
enum
value
for
PressureSource
§3.2
"critical"
enum
value
for
PressureState
§8.
disconnect()
method
for
PressureObserver
§10.2.4
"fair"
enum
value
for
PressureState
§8.
knownSources
attribute
for
PressureObserver
§10.2.6
[[LastRecordMap]]
internal
slot
for
PressureObserver
§7.
[[MaxChangesThreshold]]
internal
slot
for
PressureObserver
§7.
"nominal"
enum
value
for
PressureState
§8.
[[ObservationWindow]]
internal
slot
for
PressureObserver
§7.
observe()
method
for
PressureObserver
§10.2.2
[[PenaltyDuration]]
internal
slot
for
PressureObserver
§7.
[[PendingObservePromises]]
internal
slot
for
PressureObserver
§7.
PressureObserver
interface
§10.2
PressureObserverOptions
dictionary
§10.4
PressureRecord
interface
§10.3
PressureSource
enum
§3.2
PressureState
enum
§8.
PressureUpdateCallback
§10.1
[[QueuedRecords]]
internal
slot
for
PressureObserver
§7.
sampleInterval
member
for
PressureObserverOptions
§10.4.1
[[SampleIntervalMap]]
internal
slot
for
PressureObserver
§7.
"serious"
enum
value
for
PressureState
§8.
source
attribute
for
PressureRecord
§10.3.1
[[Source]]
internal
slot
for
PressureRecord
§10.3
state
attribute
for
PressureRecord
§10.3.2
[[State]]
internal
slot
for
PressureRecord
§10.3
takeRecords()
method
for
PressureObserver
§10.2.5
"thermals"
enum
value
for
PressureSource
§3.2
time
attribute
for
PressureRecord
§10.3.3
[[Time]]
internal
slot
for
PressureRecord
§10.3
toJSON
method
for
PressureRecord
§10.3.4
unobserve()
method
for
PressureObserver
§10.2.3
Document
interface
Node
)
ECMAScript
)
globalThis
attribute
(for
globalThis
)
DOMHighResTimeStamp
WorkerGlobalScope
)
DedicatedWorkerGlobalScope
interface
Document
)
iframes
element
WorkerGlobalScope
)
Document
)
Window
interface
WorkerGlobalScope
interface
set
list
)
list
set
)
map
)
list
)
iteration
list
)
list
map
)
map
iteration
)
list
)
list
)
map
)
list
)
struct
)
map
)
list
)
map
)
list
)
set
)
map
)
AbortError
exception
[Default]
extended
attribute
[EnforceRange]
extended
attribute
[Exposed]
extended
attribute
FrozenArray
interface
NotAllowedError
exception
NotSupportedError
exception
object
type
Promise
interface
promise
)
[SameObject]
extended
attribute
[SecureContext]
extended
attribute
TypeError
exception
undefined
type
unsigned
long
type
WebIDLenum PressureSource
{ "thermals
", "cpu
" };
enum PressureState
{ "nominal
", "fair
", "serious
", "critical
" };
callback PressureUpdateCallback
= undefined (
sequence<PressureRecord
> changes,
PressureObserver
observer
);
[Exposed=(DedicatedWorker,SharedWorker,Window), SecureContext]
interface
interface PressureObserver
{
constructor
(PressureUpdateCallback
callback);
Promise<undefined> observe
(PressureSource
source, optional PressureObserverOptions
options = {});
undefined unobserve
(PressureSource
source);
undefined disconnect
();
sequence<PressureRecord
> takeRecords
();
[SameObject] static readonly attribute FrozenArray<PressureSource
> knownSources
;
};
[Exposed=(DedicatedWorker,SharedWorker,Window), SecureContext]
interface PressureRecord
{
readonly attribute PressureSource
source
;
readonly attribute
readonly attribute PressureState
state
;
readonly attribute DOMHighResTimeStamp time
;
[Default] object toJSON
();
};
dictionary PressureObserverOptions
{
[EnforceRange] unsigned long sampleInterval
= 0;
};
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in: