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=]:
      - -
    1. - Let |supported| be true. -
    2. - Let |virtualPressureSource| be the result of invoking [=get a - virtual pressure source=] with |source| and |relevantGlobal|. -
    3. -
    4. - If |virtualPressureSource| is not null: + If |relevantGlobal|'s [=platform collector mapping=] does not + [=map/contain=] |source|:
      1. - 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. +
      2. +
      3. + Let |virtualPressureSource| be the result of invoking [=get a + virtual pressure source=] with |source| and |relevantGlobal|. +
      4. +
      5. + If |virtualPressureSource| is not null: +
          +
        1. + If |virtualPressureSource|'s [=virtual pressure + source/can provide samples flag=] is true: +
            +
          1. + Set |newCollector|'s [=platform collector/associated + pressure source=] to |virtualPressureSource|. +
          2. +
          3. + [=set/Append=] |newCollector| to + |virtualPressureSource|'s [=virtual pressure + source/connected platform collectors=]. +
          4. +
          +
        2. +
        +
      6. +
      7. + Otherwise: +
          +
        1. + Let |realPressureSource| be an [=implementation-defined=] + [=pressure source=] that provides telemetry information + about |source|, or null if none can be found. +
        2. +
        3. + Set |newCollector|'s [=platform collector/associated + pressure source=] to |realPressureSource|. +
        4. +
      8. -
      -
    5. -
    6. - Otherwise, if |source| is not a [=valid source type=]: -
      1. - Set |supported| to false. + Set |relevantGlobal|'s [=platform collector + mapping=][|source|] to |newCollector|.
    7. - 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|].
    8. - 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. +
    9. +
    10. + Invoke [=activate data collection=] with |source| and + |relevantGlobal|.
    11. [=Queue a global task=] on the [=PressureObserver task source=] given @@ -646,7 +698,7 @@

      The observe() method

      1. 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|.
      2. Return. @@ -709,9 +761,13 @@

        The unobserve() method

        If |registeredObserverList| is [=list/empty=]:
        1. - Deactivate [=data collection=] of |source| data to + Invoke [=deactivate data collection=] with |source| and |relevantGlobal|.
        2. +
        3. + [=map/Remove=] |relevantGlobal|'s [=platform collector + mapping=][|source|]. +
      @@ -753,9 +809,13 @@

      The disconnect() method

      If |registeredObserverList| is [=list/empty=]:
      1. - Deactivate [=data collection=] of |source| data to + Invoke [=deactivate data collection=] with |source| and |relevantGlobal|.
      2. +
      3. + [=map/Remove=] |relevantGlobal|'s [=platform collector + mapping=][|source|]. +
    @@ -1187,31 +1247,101 @@

    Supporting algorithms

    Data Collection and Delivery

    - [=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:

    - +
      +
    1. + If |relevantGlobal|'s [=platform collector mapping=] does not + [=map/contain=] |source|, abort these steps. +
    2. +
    3. + Let |platformCollector| be |relevantGlobal|'s [=platform collector + mapping=][|source|]. +
    4. +
    5. + If |platformCollector|'s [=platform collector/activated=] is true, + abort these steps. +
    6. +
    7. + Set |platformCollector|'s [=platform collector/activated=] to true. +
    8. +
    9. + In an [=implementation-defined=] manner, start running the [=data + collection=] steps with |relevantGlobal|, |source|, and + |platformCollector|. + +
    10. +

    - 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: +

    +
      +
    1. + If |relevantGlobal|'s [=platform collector mapping=] does not + [=map/contain=] |source|, abort these steps. +
    2. +
    3. + Let |platformCollector| be |relevantGlobal|'s [=platform collector + mapping=][|source|]. +
    4. +
    5. + If |platformCollector|'s [=platform collector/activated=] is false, + abort these steps. +
    6. +
    7. + In an [=implementation-defined=] manner, stop running the [=data + collection=] steps with |relevantGlobal|, |source|, and + |platformCollector|. +
    8. +
    9. + Set |platformCollector|'s [=platform collector/activated=] to false. +
    10. +
    11. + If |platformCollector|'s [=platform collector/associated pressure + source=] is a [=virtual pressure source=]: +
        +
      1. + [=set/Remove=] |platformCollector| from its [=platform + collector/associated pressure source=]'s [=virtual pressure + source/connected platform collectors=]. +
      2. +
      +
    12. +
    13. + Otherwise, perform any [=implementation-defined=] steps to signal to + |platformCollector|'s [=platform collector/associated pressure source=] + to stop retrieving telemetry data. +
    14. +
    +

    + The data collection steps given |relevantGlobal|, |source| and + |platformCollector| are as follows:

    1. - Let |state:PressureState| be null. + Let |pressureSource| be |platformCollector|'s [=platform + collector/associated pressure source=].
    2. - Let |virtualPressureSource| be the result of invoking [=get a virtual pressure source=] with |source| and |relevantGlobal|. + If |pressureSource| is null, abort these steps.
    3. - If |virtualPressureSource| is not null: + Let |state:PressureState| be null. +
    4. +
    5. + If |pressureSource| is a [=virtual pressure source=]:
      1. - Set |state| to |virtualPressureSource|'s [=virtual pressure + Set |state| to |pressureSource|'s [=virtual pressure source/pending sample=]. -
      2. +
      3. If |state| is null, abort these steps.
      4. @@ -1404,7 +1534,12 @@

        Handling change of [=Document/fully active=] status

        [=registered observer list=] [=ordered map=]:
        1. - Deactivate [=data collection=] of |source| to |relevantGlobal|. + Invoke [=deactivate data collection=] with |source| and + |relevantGlobal|. +
        2. +
        3. + [=map/Remove=] |relevantGlobal|'s [=platform collector + mapping=][|source|].
        @@ -1449,7 +1584,12 @@

        Handling changes to worker status

        [=registered observer list=] [=ordered map=]:
        1. - Deactivate [=data collection=] of |source| to |relevantGlobal|. + Invoke [=deactivate data collection=] with |source| and + |relevantGlobal|. +
        2. +
        3. + [=map/Remove=] |relevantGlobal|'s [=platform collector + mapping=][|source|].
        @@ -1762,9 +1902,14 @@

        Virtual Pressure Source

        - 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 @@

      5. Let |topLevelVirtualPressureSourceMapping| be the |topLevelTraversable|'s [=virtual pressure source mapping=].
      6. +
      7. + Let |pressureSource| be |topLevelVirtualPressureSourceMapping|[|virtualPressureSourceType|]. +
      8. +
      9. + [=set/For each=] |platformCollector| of |pressureSource|'s [=virtual + pressure source/connected platform collectors=]: +
          +
        1. + Set |platformCollector|'s [=platform collector/associated pressure + source=] to null. +
        2. +
        +
      10. [=map/Remove=] |topLevelVirtualPressureSourceMapping|[|virtualPressureSourceType|].
      11. @@ -2037,7 +2199,10 @@

        Set |virtualPressureSource|'s [=virtual pressure source/pending sample=] to |sample|.
      12. - 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=].
      13. Return [=success=] with data null.