From c01a9a913d9cc0d85b9043f5eefe5924b67fd40e Mon Sep 17 00:00:00 2001
From: Raphael Kubo da Costa
Date: Mon, 3 Jun 2024 17:26:41 +0200
Subject: [PATCH] Fix platform collector cardinality, define pressure source
and activation/deactivation
This addresses
https://github.com/w3c/compute-pressure/pull/265#discussion_r1616265626 by
properly defining several concepts in one change:
- "Pressure source" is now a proper ``. It is similar to a "device
sensor" in the Generic Sensor API spec, in that it works as the concept
closest to the OS/hardware and retrieves some abstract telemetry data that
is fed to one or more platform collectors. A virtual pressure source is a
pressure source.
- Platform collector's granularity has been fixed: there isn't one per
global, but rather one per source type. To make it easier to follow, a
global now has a "platform collector mapping" rather than just an
associated platform collector.
- Each platform collector now has some associated data: an "associated
pressure source", which is the pressure source it retrieves data from, as
well as an "activated" flag that is used when activating/deactivating data
collection.
With these new building blocks, we can fix and/or properly define some
concepts that have been unclear so far:
- A null associated pressure source indicates that a given pressure source
is not available.
This is used, for example, in `PressureObserver.observe()`, which is now
responsible for creating a platform collector when one is not available in
its global and attempting to set the platform collector's associated
pressure source to either a virtual pressure source or a real one.
When neither can be found, it remains null, which signals that `observe()`
must reject with NotSupportedError.
Previously (see #273), the `observe()` steps simply checked if `|source|`
was a "valid source type", which did not properly reflect the potentially
asynchronous checks involved in the real pressure source case.
- The absence of an entry for a given source type in the "platform collector
mapping" indicates that `PressureObserver.observe()` must attempt to
create a new platform collector as described above.
An existing "platform collector mapping" entry is removed only by calls to
`disconnect()` and `unobserve()` as well as when a document is no longer
fully active or a worker's closing flag is set to true.
Conceptually, this indicates more clearly that once a platform collector
is created in `observe()` it will continue using the same associated
pressure source. In other words, if `observe()` is called before "create
virtual pressure source", all observers for the same source type will
continue using a real pressure source until they all disconnect (and
vice-versa).
- A virtual pressure source keeps track of connected platform collectors so
that it can set their associated pressure source to null when it is
removed before they disconnect. This is used in the new data collection
algorithm described below.
- The data collection steps have been revamped.
- "Data collection" itself has not changed much: it tries to get a
platform collector's pressure source if one exists, read data from it
and dispatch it to observers.
- We finally have proper definitions for what it means to activate and
deactivate data collection. The steps themselves do not do much besides
making sure 1) a platform collector for the desired source exists and 2)
these steps cannot run more than once for a platform collector. The
"deactivate data collection" steps also takes care of removing a
collector from a virtual pressure source's connected platform collectors
set.
---
index.html | 273 ++++++++++++++++++++++++++++++++++++++++++-----------
1 file changed, 219 insertions(+), 54 deletions(-)
diff --git a/index.html b/index.html
index d1b5d30..759f2c5 100644
--- a/index.html
+++ b/index.html
@@ -243,18 +243,38 @@
Sampling and Reporting Rate
Platform primitives
- The [=platform collector=] refers to an abstract platform interface, with which the
- [=user agent=] interacts to obtain the telemetry samples required by this specification.
+ A pressure source is an abstract, [=implementation-defined=]
+ interface to hardware counters or an underlying telemetry framework that
+ provides information about a source types
+ defined by {{PressureSource}}. A [=pressure source=] can make use of data
+ fusion with data from additional sources if that provides better results.
- For this specification's purposes, there is one separate [=platform collector=] per
- [=global object=], which can support telemetry for different source types
- defined by {{PressureSource}}.
+ A platform collector is an abstract interface responsible for
+ obtaining telemetry samples from a [=pressure source=], translating them
+ into [=pressure states=] and providing them to the [=user agent=].
- From the implementation perspective it can be treated as a software proxy for the
- corresponding hardware counters or underlying telemetry framework, and it can make use
- of data fusion with data from additional sources if that provides better results.
+ A [=platform collector=] has the following associated data:
+
+
+
+ an associated pressure
+ source, which is a [=pressure source=] or null.
+
+
+ an activated boolean flag,
+ initially false.
+
+
+
+ The format of the data provided by a [=pressure source=] is
+ [=implementation-defined=], and so is the process through which a
+ [=platform collector=] translates it into a [=pressure state=].
+
+
+ For this specification's purposes, [=platform collectors=] are scoped to a
+ [=global object=] via the [=platform collector mapping=].
For automation purposes, a [=platform collector=] must have the ability to connect to
@@ -358,7 +378,8 @@
a registered observer list per supported [=source type=], which is initially empty.
- a platform collector as detailed in [[[#platform-primitives]]].
+ a platform collector mapping, an [=ordered map=] of [=source
+ types=] to [=platform collectors=].
A registered observer consists of an observer (a {{PressureObserver}} object).
@@ -602,40 +623,71 @@
The observe() method
Run the following steps [=in parallel=]:
-
-
- Let |supported| be true.
-
- Let |virtualPressureSource| be the result of invoking [=get a
- virtual pressure source=] with |source| and |relevantGlobal|.
-
-
- If |virtualPressureSource| is not null:
+ If |relevantGlobal|'s [=platform collector mapping=] does not
+ [=map/contain=] |source|:
- Set |supported| to |virtualPressureSource|'s [=virtual
- pressure source/can provide samples flag=].
+ Let |newCollector| be a new [=platform collector=] whose
+ [=platform collector/associated pressure source=] is null.
+
+
+ Let |virtualPressureSource| be the result of invoking [=get a
+ virtual pressure source=] with |source| and |relevantGlobal|.
+
+
+ If |virtualPressureSource| is not null:
+
+
+ If |virtualPressureSource|'s [=virtual pressure
+ source/can provide samples flag=] is true:
+
+
+ Set |newCollector|'s [=platform collector/associated
+ pressure source=] to |virtualPressureSource|.
+
+ Let |realPressureSource| be an [=implementation-defined=]
+ [=pressure source=] that provides telemetry information
+ about |source|, or null if none can be found.
+
+
+ Set |newCollector|'s [=platform collector/associated
+ pressure source=] to |realPressureSource|.
+
+
-
-
-
- Otherwise, if |source| is not a [=valid source type=]:
-
- Set |supported| to false.
+ Set |relevantGlobal|'s [=platform collector
+ mapping=][|source|] to |newCollector|.
- If |supported| is false,
- [=queue a global task=] on the [=PressureObserver task source=]
- given |relevantGlobal|
- to reject |promise| {{NotSupportedError}} and abort these steps.
+ Let |platformCollector| be |relevantGlobal|'s [=platform collector
+ mapping=][|source|].
- Activate [=data collection=] from |relevantGlobal|'s [=platform collector=] of |source| data to |relevantGlobal|.
+ If |platformCollector|'s [=platform collector/associated pressure
+ source=] is null, [=queue a global task=] on the
+ [=PressureObserver task source=] given |relevantGlobal| to reject
+ |promise| {{NotSupportedError}} and abort these steps.
+
+
+ Invoke [=activate data collection=] with |source| and
+ |relevantGlobal|.
[=Queue a global task=] on the [=PressureObserver task source=] given
@@ -646,7 +698,7 @@
The observe() method
If |relevantGlobal|'s [=registered observer list=] for |source| is [=list/empty=],
- deactivate [=data collection=] of |source| data to |relevantGlobal|.
+ invoke [=deactivate data collection=] with |source| and |relevantGlobal|.
Return.
@@ -709,9 +761,13 @@
The unobserve() method
If |registeredObserverList| is [=list/empty=]:
- Deactivate [=data collection=] of |source| data to
+ Invoke [=deactivate data collection=] with |source| and
|relevantGlobal|.
- [=Data collection=] from a [=platform collector=] can be activated and deactivated in an
- [=implementation-defined=] manner per [=source type=] and [=global object=].
+ To activate data collection given a [=source type=] |source|
+ and |relevantGlobal|, perform the following steps:
-
+
+
+ If |relevantGlobal|'s [=platform collector mapping=] does not
+ [=map/contain=] |source|, abort these steps.
+
+
+ Let |platformCollector| be |relevantGlobal|'s [=platform collector
+ mapping=][|source|].
+
+
+ If |platformCollector|'s [=platform collector/activated=] is true,
+ abort these steps.
+
+
+ Set |platformCollector|'s [=platform collector/activated=] to true.
+
+
+ In an [=implementation-defined=] manner, start running the [=data
+ collection=] steps with |relevantGlobal|, |source|, and
+ |platformCollector|.
+
+
+
- The data collection steps given |relevantGlobal| as input, are run when
- |relevantGlobal|'s associated [=platform collector=] needs to obtain new data
- for a [=source type=] |source:PressureSource| and are as follows:
+ To deactivate data collection given a [=source type=] |source|
+ and |relevantGlobal|, perform the following steps:
+
+
+
+ If |relevantGlobal|'s [=platform collector mapping=] does not
+ [=map/contain=] |source|, abort these steps.
+
+
+ Let |platformCollector| be |relevantGlobal|'s [=platform collector
+ mapping=][|source|].
+
+
+ If |platformCollector|'s [=platform collector/activated=] is false,
+ abort these steps.
+
+
+ In an [=implementation-defined=] manner, stop running the [=data
+ collection=] steps with |relevantGlobal|, |source|, and
+ |platformCollector|.
+
+
+ Set |platformCollector|'s [=platform collector/activated=] to false.
+
+
+ If |platformCollector|'s [=platform collector/associated pressure
+ source=] is a [=virtual pressure source=]:
+
+
+ [=set/Remove=] |platformCollector| from its [=platform
+ collector/associated pressure source=]'s [=virtual pressure
+ source/connected platform collectors=].
+
+
+
+
+ Otherwise, perform any [=implementation-defined=] steps to signal to
+ |platformCollector|'s [=platform collector/associated pressure source=]
+ to stop retrieving telemetry data.
+
+
+
+ The data collection steps given |relevantGlobal|, |source| and
+ |platformCollector| are as follows:
- Let |state:PressureState| be null.
+ Let |pressureSource| be |platformCollector|'s [=platform
+ collector/associated pressure source=].
- Let |virtualPressureSource| be the result of invoking [=get a virtual pressure source=] with |source| and |relevantGlobal|.
+ If |pressureSource| is null, abort these steps.
- If |virtualPressureSource| is not null:
+ Let |state:PressureState| be null.
+
+
+ If |pressureSource| is a [=virtual pressure source=]:
- Set |state| to |virtualPressureSource|'s [=virtual pressure
+ Set |state| to |pressureSource|'s [=virtual pressure
source/pending sample=].
-
+
If |state| is null, abort these steps.
@@ -1404,7 +1534,12 @@
Handling change of [=Document/fully active=] status
[=registered observer list=] [=ordered map=]:
- Deactivate [=data collection=] of |source| to |relevantGlobal|.
+ Invoke [=deactivate data collection=] with |source| and
+ |relevantGlobal|.
+
- A virtual pressure source simulates the behavior of a real pressure source in controlled ways.
+ A virtual pressure source simulates the behavior of a real [=pressure source=] 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=].
+
Each [=virtual pressure source=] has:
@@ -1776,6 +1921,10 @@
a can provide samples
flag, a boolean.
+
+ a connected platform
+ collectors [=set=] of [=platform collectors=].
+
@@ -1810,7 +1959,7 @@
This [=extension command=] creates a new [=virtual pressure source=] of a specified
[=source type=]. Calls to {{PressureObserver/observe()}} from {{PressureObserver}} instances
of the same [=source type=] will cause this [=virtual pressure source=] to be used as their
- backing pressure source until [[[#delete-virtual-pressure-source]]] is run.
+ backing [=pressure source=] until [[[#delete-virtual-pressure-source]]] is run.
@@ -1934,6 +2083,19 @@
Let |topLevelVirtualPressureSourceMapping| be the |topLevelTraversable|'s [=virtual pressure source mapping=].
+
+ Let |pressureSource| be |topLevelVirtualPressureSourceMapping|[|virtualPressureSourceType|].
+
Set |virtualPressureSource|'s [=virtual pressure source/pending sample=] to |sample|.
- In an [=implementation-defined=] way, run the [=data collection=] steps.
+ In an [=implementation-defined=] way, make |virtualPressureSource|'s
+ [=virtual pressure source/pending sample=] available to
+ |virtualPressureSource|'s [=virtual pressure source/connected platform
+ collectors=].