Skip to content

Commit 10b4251

Browse files
author
Raphael Kubo da Costa
authored
Make PressureObserver.observe() and data delivery algorithm less vague (#283)
Related to #282: we need these algorithms to be properly defined in order to be able to support WebDriver and fake pressure states. This somewhat big change intends to clarify what "activate" and "deactivate" data delivery actually mean, as there used to be just a "data delivery" algorithm and no accompanying definitions for those two verbs. Furthermore, the data delivery algorithm itself was confusing: - It referenced a `data` variable in its declaration that was never passed by any callers. - `data` was of an implementation-defined type and format, but the steps assumed it had some associated information like source type that was not set anywhere. Fixing the above has required changes in different layers: - The "platform collector" concept, which used to be an abstract entity with which all globals interacted to retrieve telemetry data for all source types, is now a per-global and per-source type concept. The lower-level concept that represents a cross-global interface for the hardware or OS is now a "pressure source", which contains a snapshot of the latest reading it has retrieved along with a timestamp. - "Data delivery" is now called "data collection". It uses a platform collector and its associated pressure source to retrieve a telemetry sample that is transformed into a pressure state. - There are algorithms for activating and deactivating data collection. Both ensure they data collection cannot be started/stopped if they have already been. - `PressureObserver.observe()`'s had a "is not a valid source type" check that was too vague, as this step determined whether a given source type is supported by the platform or not, but the definition of "valid source type" was something else entirely. This step has been replaced by a sequence of steps that attempts to retrieve an existing platform collector for a source type and, if one does not exist, tries to connect to a corresponding pressure source. This change makes the same platform collector be used for all observers of a given source type and lays out in more detail what it means to check whether a source type is valid or not in this context. Co-authored with @kenchris in #265. It was split off as a separate pull request to make it easier to review and understand.
1 parent 3a6fa23 commit 10b4251

File tree

1 file changed

+225
-55
lines changed

1 file changed

+225
-55
lines changed

index.html

Lines changed: 225 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,7 @@

Sampling and Reporting Rate

216216
p>
217217
<p>
218218
The <dfn>reporting ratedfn> for a pressure observer is the rate at which it runs
219-
the [=data delivery=] steps, and it will never exceed the [=sampling rate=].
219+
the [=data collection=] steps, and it will never exceed the [=sampling rate=].
220220
p>
221221
<p>
222222
The [=sampling rate=] differs from the [=requested sampling rate=] when the
@@ -243,26 +243,69 @@

Sampling and Reporting Rate

243243

244244
<section> <h2>Platform primitivesh2>
245245
<p>
246-
The [=platform collector=] refers to a platform interface, with which the [=user agent=] interacts to
247-
obtain the telemetry readings required by this specification.
246+
A <dfn>pressure sourcedfn> is an abstract, [=implementation-defined=]
247+
interface to hardware counters or an underlying framework that provides
248+
telemetry data about a <dfn>source typedfn>
249+
defined by {{PressureSource}}. A [=pressure source=] can make use of data
250+
fusion with data from additional sources if that provides more precise
251+
results.
248252
p>
249253
<p>
250-
A [=platform collector=] can be defined by the underlying platform (e.g. in a native telemetry
251-
framework) or by the [=user agent=], if it has a direct access to hardware counters.
254+
The telemetry data provided by a [=pressure source=] is represented in this
255+
specification as a <dfn>pressure source sampledfn>, a [=struct=]
256+
consisting of the following [=struct/items=]:
257+
<ul>
258+
<li>
259+
<dfn data-dfn-for="pressure source sample">datadfn>: [=contributing
260+
factors=] obtained from the underlying hardware or operating system.
261+
li>
262+
<li>
263+
<dfn data-dfn-for="pressure source sample">timestampdfn>: the
264+
[=unsafe shared current time=] when [=pressure source sample/data=] was
265+
obtained.
266+
<aside class="note">
267+
<p>
268+
The purpose of [=pressure source sample/timestamp=] is to use the
269+
same [=monotonic clock/unsafe current time=] for a sample across
270+
all globals and invocations of the [=data collection=] algorithm
271+
which are processing the same [=pressure source sample=].
272+
p>
273+
aside>
274+
li>
275+
ul>
252276
p>
253277
<p>
254-
A [=platform collector=] can support telemetry for different <dfn>source typesdfn> of computing
255-
devices defined by {{PressureSource}}, or there can be multiple [=platform collectors=].
278+
A [=pressure source=] has an associated <dfn
279+
data-dfn-for="pressure source">latest sampledfn>, a [=pressure source
280+
sample=] or null. It is initially null.
256281
p>
257282
<p>
258-
From the implementation perspective [=platform collector=] can be treated as a software proxy for the
259-
corresponding hardware counters. It is possible to have multiple [=platform collector=] simultaneously
260-
interacting with the same underlying hardware if the underlying platform supports it.
283+
A <dfn>platform collectordfn> is an abstract interface responsible for
284+
obtaining telemetry samples from a [=pressure source=], transforming them
285+
into [=pressure states=] and providing them to the [=user agent=].
261286
p>
262287
<p>
263-
In simple cases, a [=platform collector=] represents individual hardware counters, but if the provided
264-
counter readings are a product of data fusion performed in software, the [=platform collector=]
265-
represents the results of the data fusion process. This may happen in user space or in kernel space.
288+
A [=platform collector=] has the following associated data:
289+
p>
290+
<ul>
291+
<li>
292+
an <dfn data-dfn-for="platform collector">associated pressure
293+
sourcedfn>, which is a [=pressure source=] or null.
294+
li>
295+
<li>
296+
an <dfn data-dfn-for="platform collector">activateddfn> boolean,
297+
initially false.
298+
li>
299+
ul>
300+
<p>
301+
The format of the telemetry data provided by a [=pressure source=]
302+
and stored in its [=pressure source/latest sample=]'s [=pressure source
303+
sample/data=] is [=implementation-defined=], and so is the process through
304+
which a [=platform collector=] transforms it into a [=pressure state=].
305+
p>
306+
<p>
307+
For this specification's purposes, [=platform collectors=] are scoped to a
308+
[=global object=] via the [=platform collector mapping=].
266309
p>
267310
<p>
268311
As collecting telemetry data often means polling hardware counters, it is not a free operation and thus,
@@ -361,7 +404,8 @@

361404
a <dfn>registered observer listdfn> per supported [=source type=], which is initially empty.
362405
li>
363406
<li>
364-
a reference to an underlying <dfn>platform collectordfn> as detailed in [[[#platform-primitives]]].
407+
a <dfn>platform collector mappingdfn>, an [=ordered map=] of [=source
408+
types=] to [=platform collectors=].
365409
li>
366410
ul>
367411
A <dfn>registered observerdfn> consists of an <dfn>observerdfn> (a {{PressureObserver}} object).
@@ -606,13 +650,57 @@

The observe() method

606650
Run the following steps [=in parallel=]:
607651
<ol>
608652
<li>
609-
If |source:PressureSource| is not a [=valid source type=],
610-
[=queue a global task=] on the [=PressureObserver task source=]
611-
given |relevantGlobal|
612-
to reject |promise| {{NotSupportedError}} and abort these steps.
653+
Let |platformCollector| be null.
654+
li>
655+
<li>
656+
If |relevantGlobal|'s [=platform collector mapping=]
657+
[=map/contains=] |source|:
658+
<ol>
659+
<li>
660+
Set |platformCollector| to |relevantGlobal|'s [=platform
661+
collector mapping=][|source|].
662+
li>
663+
ol>
664+
li>
665+
<li>
666+
Otherwise:
667+
<ol>
668+
<li>
669+
Let |newCollector| be a new [=platform collector=] whose
670+
[=platform collector/associated pressure source=] is null.
671+
li>
672+
<li>
673+
Let |pressureSource| be an [=implementation-defined=]
674+
[=pressure source=] that provides telemetry data about
675+
|source|, or null if none exists.
676+
li>
677+
<li>
678+
Set |newCollector|'s [=platform collector/associated pressure
679+
source=] to |pressureSource|.
680+
li>
681+
<li>
682+
If |newCollector|'s [=platform collector/associated
683+
pressure source=] is not null:
684+
<ol>
685+
<li>
686+
Set |platformCollector| to |newCollector|.
687+
li>
688+
<li>
689+
Set |relevantGlobal|'s [=platform collector
690+
mapping=][|source|] to |platformCollector|.
691+
li>
692+
ol>
693+
li>
694+
ol>
613695
li>
614696
<li>
615-
Activate [=data delivery=] of |source| data to |relevantGlobal|.
697+
If |platformCollector| is null, [=queue a global task=] on the
698+
[=PressureObserver task source=] given |relevantGlobal| to reject
699+
|promise| {{NotSupportedError}} and abort these steps.
700+
li>
701+
<li>
702+
Invoke [=activate data collection=] with |source| and
703+
|relevantGlobal|.
616704
li>
617705
<li>
618706
[=Queue a global task=] on the [=PressureObserver task source=] given
@@ -623,7 +711,7 @@

The observe() method

623711
<ol>
624712
<li>
625713
If |relevantGlobal|'s [=registered observer list=] for |source| is [=list/empty=],
626-
deactivate [=data delivery=] of |source| data to |relevantGlobal|.
714+
invoke [=deactivate data collection=] with |source| and |relevantGlobal|.
627715
li>
628716
<li>
629717
Return.
@@ -686,9 +774,13 @@

The unobserve() method

686774
If |registeredObserverList| is [=list/empty=]:
687775
<ol>
688776
<li>
689-
Deactivate [=data delivery=] of |source| data to
777+
Invoke [=deactivate data collection=] with |source| and
690778
|relevantGlobal|.
691779
li>
780+
<li>
781+
[=map/Remove=] |relevantGlobal|'s [=platform collector
782+
mapping=][|source|].
783+
li>
692784
ol>
693785
li>
694786
ol>
@@ -730,9 +822,13 @@

The disconnect() method

730822
If |registeredObserverList| is [=list/empty=]:
731823
<ol>
732824
<li>
733-
Deactivate [=data delivery=] of |source| data to
825+
Invoke [=deactivate data collection=] with |source| and
734826
|relevantGlobal|.
735827
li>
828+
<li>
829+
[=map/Remove=] |relevantGlobal|'s [=platform collector
830+
mapping=][|source|].
831+
li>
736832
ol>
737833
li>
738834
ol>
@@ -1109,47 +1205,111 @@

Supporting algorithms

11091205
p>
11101206
section>
11111207
<section>
1112-
<h3>Data deliveryh3>
1208+
<h3>Data Collection and Deliveryh3>
11131209
<p>
1114-
[=Data delivery=] from a [=platform collector=] can be activate and deactivated in an
1115-
[=implementation-defined=] manner per [=source type=] and [=global object=].
1210+
To <dfn>activate data collectiondfn> given a [=source type=] |source|
1211+
and |relevantGlobal|, perform the following steps:
11161212
p>
1117-
<aside class="note">
1118-
It is recommended that the [=platform collector=] suspends low-level data polling
1119-
when there is no active [=data delivery=] to any {{PressureObserver}} [=relevant global object=].
1120-
aside>
1213+
<ol class="algorithm">
1214+
<li>
1215+
If |relevantGlobal|'s [=platform collector mapping=] does not
1216+
[=map/contain=] |source|, abort these steps.
1217+
li>
1218+
<li>
1219+
Let |platformCollector| be |relevantGlobal|'s [=platform collector
1220+
mapping=][|source|].
1221+
li>
1222+
<li>
1223+
If |platformCollector|'s [=platform collector/activated=] is true,
1224+
abort these steps.
1225+
li>
1226+
<li>
1227+
Set |platformCollector|'s [=platform collector/activated=] to true.
1228+
li>
1229+
<li>
1230+
In an [=implementation-defined=] manner, start running the [=data
1231+
collection=] steps with |relevantGlobal|, |source|, and
1232+
|platformCollector|.
1233+
<aside class="note">
1234+
<p>
1235+
This step givens implementations leeway to collect telemetry data
1236+
via polling or by subscribing to platform- or OS-specific
1237+
notifications.
1238+
p>
1239+
aside>
1240+
li>
1241+
ol>
11211242
<p>
1122-
The <dfn>data deliverydfn> steps that are run when
1123-
an [=implementation-defined=] |data| sample of [=source type=] |source:PressureSource| is
1124-
obtained from [=global object=] |relevantGlobal|'s [=platform collector=],
1125-
are as follows:
1126-
<ol>
1243+
To <dfn>deactivate data collectiondfn> given a [=source type=] |source|
1244+
and |relevantGlobal|, perform the following steps:
1245+
p>
1246+
<ol class="algorithm">
1247+
<li>
1248+
If |relevantGlobal|'s [=platform collector mapping=] does not
1249+
[=map/contain=] |source|, abort these steps.
1250+
li>
1251+
<li>
1252+
Let |platformCollector| be |relevantGlobal|'s [=platform collector
1253+
mapping=][|source|].
1254+
li>
1255+
<li>
1256+
If |platformCollector|'s [=platform collector/activated=] is false,
1257+
abort these steps.
1258+
li>
1259+
<li>
1260+
In an [=implementation-defined=] manner, stop running the [=data
1261+
collection=] steps with |relevantGlobal|, |source|, and
1262+
|platformCollector|.
1263+
li>
1264+
<li>
1265+
Set |platformCollector|'s [=platform collector/activated=] to false.
1266+
li>
1267+
<li>
1268+
Perform any [=implementation-defined=] steps to signal to
1269+
|platformCollector|'s [=platform collector/associated pressure source=]
1270+
to stop retrieving telemetry data.
1271+
li>
1272+
ol>
1273+
<p>
1274+
The <dfn>data collectiondfn> steps given |relevantGlobal|, |source| and
1275+
|platformCollector| are as follows:
1276+
<ol class="algorithm">
11271277
<li>
1128-
Let |source:PressureSource| be the [=source type=] of the |data| sample.
1278+
Let |pressureSource| be |platformCollector|'s [=platform
1279+
collector/associated pressure source=].
11291280
li>
11301281
<li>
1131-
Let |state:PressureState| be an [=adjusted pressure state=] given |data| and |source|.
1132-
<aside class="note">
1133-
The |data| sample and mapping between |data| sample, and [=pressure states=],
1134-
is [=implementation-defined=] and may use many different metrics. For instance,
1135-
for CPU, it might consider processor frequency and utilization, as well
1136-
as thermal conditions.
1137-
aside>
1282+
If |pressureSource| is null, abort these steps.
11381283
li>
11391284
<li>
1140-
Let |timestamp| be the [=unsafe shared current time=] corresponding
1141-
to the moment when |data| was obtained from |relevantGlobal|'s
1142-
[=platform collector=].
1143-
<aside class="note">
1144-
The goal of this step is to ensure that the same [=monotonic
1145-
clock/unsafe current time=] is used across all globals. The value is
1146-
then converted into a global-specific, [=coarsened moment=] in the
1147-
step below.
1148-
aside>
1285+
Let |sample| be |pressureSource|'s [=pressure source/latest sample=].
11491286
li>
11501287
<li>
1151-
Let |timeValue| be the [=relative high resolution time=] based on |timestamp| and
1152-
|relevantGlobal|.
1288+
If |sample| is null, abort these steps.
1289+
li>
1290+
<li>
1291+
Let |state| be an [=adjusted pressure state=] calculated from
1292+
|source| and |sample|'s [=pressure source sample/data=].
1293+
<aside class="note">
1294+
<p>
1295+
The mapping between |sample|'s [=pressure source sample/data=]
1296+
and [=pressure states=] is [=implementation-defined=] and may use
1297+
many different metrics. For instance, for CPU, it might consider
1298+
processor frequency and utilization, as well as thermal
1299+
conditions.
1300+
p>
1301+
aside>
1302+
li>
1303+
<li>
1304+
[=Assert=]: |state| is not null.
1305+
li>
1306+
<li>
1307+
Let |rawTimestamp| be |sample|'s [=pressure source
1308+
sample/timestamp=].
1309+
li>
1310+
<li>
1311+
Let |timeValue| be the [=relative high resolution time=] based on
1312+
|rawTimestamp| and |relevantGlobal|.
11531313
li>
11541314
<li>
11551315
[=list/For each=] |observer:PressureObserver| in |relevantGlobal|'s
@@ -1313,7 +1473,12 @@

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

13131473
[=registered observer list=] [=ordered map=]:
13141474
<ol>
13151475
<li>
1316-
Deactivate [=data delivery=] of |source| to |relevantGlobal|.
1476+
Invoke [=deactivate data collection=] with |source| and
1477+
|relevantGlobal|.
1478+
li>
1479+
<li>
1480+
[=map/Remove=] |relevantGlobal|'s [=platform collector
1481+
mapping=][|source|].
13171482
li>
13181483
ol>
13191484
li>
@@ -1358,7 +1523,12 @@

Handling changes to worker status

13581523
[=registered observer list=] [=ordered map=]:
13591524
<ol>
13601525
<li>
1361-
Deactivate [=data delivery=] of |source| to |relevantGlobal|.
1526+
Invoke [=deactivate data collection=] with |source| and
1527+
|relevantGlobal|.
1528+
li>
1529+
<li>
1530+
[=map/Remove=] |relevantGlobal|'s [=platform collector
1531+
mapping=][|source|].
13621532
li>
13631533
ol>
13641534
li>

0 commit comments

Comments
 (0)