Copyright © 2025 World Wide Web Consortium. W3C® liability, trademark and permissive document license rules apply.
Compute Pressure APIは、ウェブサイトがターゲットデバイスのCPUプレッシャーの変化に反応し、ユーザーエクスペリエンスの向上のためにリソースとのトレードオフを行う方法を提供します。
このセクションは、本書が公開された時点での位置付けを説明します。現在のW3C刊行物および本技術レポートの最新改訂版は、W3Cの標準およびドラフト一覧(https://www.w3.org/TR/)で確認できます。
この仕様がCR段階を終了するためには、本仕様で定義されたすべての機能について少なくとも2つの独立した実装が実装レポートで文書化されている必要があります。
この文書はデバイスおよびセンサー作業グループが勧告トラックを用いて公開した勧告候補ドラフトです。
勧告候補としての公開は、W3C またはその会員による支持を意味するものではありません。勧告候補ドラフトは、ワーキンググループが次の勧告候補スナップショットに含めることを意図した、以前の勧告候補からの変更点を統合したものです。
これはドラフト文書であり、今後更新・置換・廃止される場合があります。この文書を進行中の作業以外の形で引用するのは好ましくありません。
この文書は W3C特許ポリシーのもとで活動しているグループによって作成されました。 W3Cは、成果物に関連する特許開示の一覧(公開)を管理しています; またそのページには特許開示の手順も記載されています。特許が必須クレームを含むと信じるに足る知識がある者は、W3C特許ポリシー第6節に従って情報を開示しなければなりません。
この文書は 2023年11月3日版W3Cプロセス文書に従います。
このセクションは規範的ではありません。
現代のアプリケーションは、現代的で快適なユーザー体験を提供するために、システムのコンピューティング資源を最大限活用することの利点とトレードオフのバランスを取る必要があります。
例えば、多くのアプリケーションは、さまざまな精度の映像効果をレンダリングできます。これらのアプリケーションはユーザー体験を最適にしつつ、ユーザーのデバイスを高負荷状態へ導かないように工夫しています。
処理ユニットの使用率が100%近く、あるいは頻繁に100%に達すると、異なるタスクが処理時間を争うことになり、悪いユーザー体験につながりやすくなります。 これにより動作が遅くなり、とくに入力遅延が目立つようになります。 さらに、100%近い使用率が長時間続くと、処理ユニットが連続的な ブースト動作により発熱し、スロットリングが発生してユーザー体験がさらに悪化する場合があります。
熱的な制限の結果、多くのスマートフォン、タブレット、ノートパソコンは触れると不快なほど熱くなることがあります。ノートパソコンやデスクトップのファンは非常にうるさくなり、会話や集中の妨げになることもあります。
多くの場合、高負荷のデバイスは応答しないように見えます。これはオペレーティングシステムが、ユーザーが待っているタスクを進行させるスレッドのスケジューリングに失敗するためです。詳しくはユースケースも参照してください。
このセクションは規範的ではありません。
機能検出は、Web開発のベストプラクティスとして確立されています。この話題に関するリソースはオンライン・オフライン問わず多数存在し、本セクションの目的はそれをさらに議論することではなく、ハードウェア依存の機能検出の文脈で位置付けることです。
以下の機能検出例を考えてみましょう。
本仕様では次の概念を定義します。
コンピューティングデバイスは、中央処理装置(CPU)、グラフィックス処理装置(GPU)、その他の多くの特殊な処理ユニットで構成されています。後者には、機械学習やコンピュータビジョンのような特定タスクに特化したものも増えています。
本仕様では現在、有効なソースタイプとして 中央処理ユニット(CPUとしても知られる)のみを定義します。 今後のレベルでは、追加のソースタイプが導入される可能性があります。
PressureSource列挙は有効なソースタイプを表します。
要求サンプリング間隔は、ハードウェアからサンプルを取得する間隔(ミリ秒で表現)を示します。
間隔と周波数は逆数の関係にあるため、要求サンプリング間隔は、1000 を割ることでヘルツ(1秒あたりの回数)による要求サンプリングレートとしても表せます。
サンプリングレートは、プラットフォームコレクタでユーザーエージェントが基盤プラットフォームからテレメトリ値を取得する頻度(ヘルツ)を示します。これはプレッシャーオブザーバごとの要求サンプリングレートとは異なる場合があります。
レポートレートは、プレッシャーオブザーバがデータ収集手順を実行する頻度(ヘルツ)であり、サンプリングレートを上回ることはありません。
サンプリングレートは、要求サンプリングレートが基盤プラットフォームまたはユーザーエージェントでサポートされる上限・下限を超える場合に異なります†。
†仕様ではさらに、11.2.2 レート難読化で述べた通りレートを難読化します。
サンプリングレートがリクエストされていない場合、その値は実装依存です。
プレッシャーソースは、ハードウェアカウンタまたは
実装依存
の基盤フレームワークへの抽象インターフェイスであり、
PressureSourceで定義される
ソースタイプについてのテレメトリデータを提供します。
プレッシャーソースは、より高精度な結果が得られる場合、他のソースのデータと融合を行うことができます。
プレッシャーソースが提供するテレメトリデータは、 本仕様ではプレッシャーソースサンプルと呼ばれる 構造体で表し、 以下の項目からなります:
PressureState
。
プレッシャーソースは 最新サンプル(pressure source sampleまたはnull)を持ちます。初期値はnullです。
プラットフォームコレクタは、 プレッシャーソースからテレメトリサンプルを取得し、 プレッシャー状態へ変換し、 ユーザーエージェントに渡す抽象インターフェイスです。
プラットフォームコレクタは次のデータを持ちます:
プレッシャーソースが提供し 最新サンプルのdataに保存されるテレメトリデータの形式 および プラットフォームコレクタがこれを プレッシャー状態へ変換する方法は、 実装依存です。
本仕様の目的では、プラットフォームコレクタは グローバルオブジェクトごとに platform collector mapping でスコープされます。
オートメーションの目的で、プラットフォームコレクタは 仮想プレッシャーソースに接続し、その dataを プレッシャー状態として利用できる必要があります。 これは生のプラットフォームデータを 調整済プレッシャー状態へ変換する必要がないことを意味します。
テレメトリデータの収集はしばしばハードウェアカウンタのポーリングを伴うため、無償の操作ではありません。 したがって、監視者がいない場合は行うべきではありません。 詳細は10.5 ライフサイクルとガベージコレクションを参照してください。
プラットフォームコレクタは 一定のレートでデータをサンプリングします。 ユーザーエージェントは プライバシー理由でこのレートを変更したり(可能な場合)、特定の読み取り値を無視または融合させることがあります。
ユーザーエージェントは、プレッシャーオブザーバが有効なときにユーザーに通知し、 進行中の操作をブロックまたは通知を閉じる手段を提供する何らかのユーザー可視通知を 推奨します。
Compute Pressure APIは、"compute-pressure" トークンで識別される
ポリシー制御機能を定義します。
そのデフォルト許可リストは
'self'です。
ワーカー(専用・共有)は、所有ドキュメントのパーミッションポリシーに従います。
共有ワーカーは、同一オリジンの他のドキュメントから取得できるため、 通常は複数の所有ドキュメントがあります。 この場合、全ての所有ドキュメントが本仕様で定義される 利用可の ポリシー制御機能 でなければなりません。
専用ワーカーは他のワーカーから作成することもでき、その場合は所有チェーンの最初の ドキュメント(共有ワーカーの場合は全て)のパーミッションポリシーが適用されます。
各グローバルオブジェクトは次を持ちます:
PressureObserverオブジェクト)からなる。
ユーザーエージェントは以下を持ちます:
PressureSource値。
生成されたPressureObserverオブジェクトは以下の内部スロットを持ちます:
PressureUpdateCallback型。生成時にセット。
PressureSource文字列、
promiseにはPromiseオブジェクトを保持。
PressureRecord
オブジェクト、初期値は空。
PressureSource
から最新のPressureRecordへのマップ。
PressureSource
ごとのサンプル間隔を表す正の数値。
レート難読化対策のため、生成された
PressureObserver
オブジェクトはさらに以下の内部スロットを持ちます:
PressureSource単位で
ソースタイプごとに
現在のプレッシャー状態への遷移を引き起こしたものを表す。
このマップの値は 現在の観測ウィンドウ期間内の状態変化数(整数)。
PressureRecord
のソースタイプがキー。
このマップの値は、PressureRecord。
プレッシャー状態は、ウェブサイトが計算資源やシステム負荷の変化に最小限の品質やサービス、ユーザー体験の低下で対応できるようにする、有用な最小限の状態セットを表します。
WebIDLenum PressureState { "nominal", "fair", "serious", "critical" };
PressureState列挙型は、以下のプレッシャー状態を表します:
nominal":
ターゲットデバイスの状態が許容範囲内で、ユーザーに悪影響はありません。
fair":ターゲットデバイスの負荷・温度や消費エネルギーがやや上昇しており、バッテリー寿命の低下やファン(または冷却機構)の稼働と音が発生する可能性があります。それ以外は問題なく追加処理も可能です。
serious":ターゲットデバイスの負荷・温度や消費エネルギーが継続的に非常に高く、熱を下げるためにシステムがスロットリングすることがあります。
critical":ターゲットデバイスやシステムの温度が著しく高く、冷却を要して問題を回避する必要があります。
寄与因子とは、現在のプレッシャー状態を決定するもととなる、ハードウェアやOSのメトリクスであり、実装依存です。
調整済みプレッシャー状態は、プレッシャー状態と実装依存データ(ソースタイプ 及び他の実装依存データ)を入力として、実装依存アルゴリズムにより決定されるプレッシャー状態です。このアルゴリズムは、キャリブレーション解除対策の効果維持のため、決定的であってはなりません。
寄与因子の変化が実質的であるステップは以下の通りです:
PressureUpdateCallback コールバックWebIDLcallback PressureUpdateCallback = undefined (
sequence<PressureRecord> changes,
PressureObserver observer
);
このコールバックは、プレッシャー状態が変化したときに呼び出されます。
PressureObserver オブジェクト
PressureObserverは、プレッシャー状態の変化を観測するために使用できます。
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;
};
PressureObserver インターフェイスは、PressureObserver を表します。
new PressureObserver(callback)
のコンストラクタ手順は次のとおりです:
[[Callback]] を callback に設定する。
observe(source, options)
の手順は次のとおりです:
[[SampleIntervalMap]][source]
を、options の sampleInterval
に設定する。
[[PendingObservePromises]] に格納する。
[[PendingObservePromises]]
から取り除く。
NotSupportedError
で拒否し、これらの手順を中止する。
unobserve(source)
の手順は次のとおりです:
NotSupportedError"
を投げる。
[[QueuedRecords]] から
source に関連するすべての records を取り除く。
[[SampleIntervalMap]][source] を取り除く。
[[LastRecordMap]][source] を取り除く。
[[AfterPenaltyRecordMap]][source] を取り除く。
[[PendingObservePromises]] を反復し、
もし source が promiseSource と等しい場合、reject により pendingPromise を AbortError で拒否する。
disconnect()
の手順は次のとおりです:
[[QueuedRecords]]
を空にする。
[[SampleIntervalMap]] を空にする。
[[LastRecordMap]]
を空にする。
[[AfterPenaltyRecordMap]] を空にする。
[[PendingObservePromises]] を反復し、
reject により pendingPromise を AbortError で拒否する。
takeRecords()
の手順は次のとおりです:
[[QueuedRecords]]
の複製とする。
[[QueuedRecords]]
を空にする。
knownSources ゲッターの手順は次のとおりです:
WebIDL[Exposed=(DedicatedWorker,SharedWorker,Window), SecureContext]
interface PressureRecord {
readonly attribute PressureSource source;
readonly attribute PressureState state;
readonly attribute DOMHighResTimeStamp time;
[Default] object toJSON();
};
生成された PressureRecord オブジェクトは、
次の内部スロットを持ちます:
PressureSource)。現在の
ソースタイプ を表す。
PressureState)。現在の プレッシャー状態 を表す。
DOMHighResTimeStamp)。
これは、通知を生成した PressureObserver
インスタンスに関連付けられたグローバルオブジェクトの time origin に対する、
システムからデータを取得した時刻に対応する。
source の ゲッター手順 は、その [[Source]] 内部スロットを返すことである。
PressureRecord.toJSON が呼び出されたときは、Web IDL
Standard の 既定の toJSON 手順 を実行する。
WebIDLdictionary PressureObserverOptions {
[EnforceRange] unsigned long sampleInterval = 0;
};
sampleInterval メンバーは、
ミリ秒で表される 要求サンプリング間隔 を表します。値が 0
に設定されている場合、システムは
PressureUpdateCallback を、
PressureState に変化がある場合にのみ呼び出します。
各 グローバルオブジェクト は、 自身の 登録済みオブザーバ に対して強参照を持ち、登録済みオブザーバリスト(ソースごとに 1 つ)に格納されます。
このセクションでは、ユーザーエージェントが仕様を実装する際に実行すべき手順の概要を示します。
引数 observer を与えた 観測ウィンドウをリセットする 手順は次のとおりです:
[[ObservationWindow]] を、
ミリ秒単位の 実装依存の範囲内で乱数化された整数値に設定する。
[[MaxChangesThreshold]] を、
observationWindow 内で許可される最大変化数の 実装依存の範囲で乱数化された整数値に設定する。
[[PenaltyDuration]] を、
ミリ秒単位の 実装依存の範囲で乱数化された整数値に設定する。
[[ChangesCountMap]]
マップを空にする。
[[ObservationWindow]]
の時間が経過したときに異なる乱数化値で再度手順を実行するタイマーを開始する。
関連グローバルオブジェクト relevantGlobal の 所有ドキュメント集合 を決定するには:
Window であるなら、追加 により relevantGlobal の 関連付けられたドキュメント を
owningDocumentSet に追加する。
WorkerGlobalScope
の
relevantGlobal の 所有者集合 を反復する:
Document であるなら、追加 により owner を
owningDocumentSet に追加する。
WorkerGlobalScope
であるなら、
owningDocumentSet を、和集合 により
owningDocumentSet と owner の 所有ドキュメント集合 の和集合に設定する。
引数 document を与えた 暗黙のフォーカスを持つドキュメント 手順は次のとおりです:
引数 observer を与えた データ受信可能 手順は次のとおりです:
Window オブジェクトであるなら:
WorkerGlobalScope
オブジェクトであるなら:
[[LastRecordMap]][source] が 存在しない 場合、true を返す。
[[LastRecordMap]][source] とする。
[[SampleIntervalMap]][source] とする。
[[Time]] とする。
[[SampleIntervalMap]][source] > 0 なら、true を返す。
[[LastRecordMap]][source] が 存在しない なら、true を返す。
[[LastRecordMap]][source] とする。
[[State]] が state と等しくないなら、true を返す。
[[ChangesCountMap]][source] をインクリメントする。
[[ChangesCountMap]][source] が、
observer の [[MaxChangesThreshold]] 以下である場合に
true を返す。
ソースタイプ source と relevantGlobal を与えた、 仮想プレッシャーソースを取得する 手順は次のとおりです。戻り値は 仮想プレッシャーソース または null です。
Window オブジェクトであるなら:
DedicatedWorkerGlobalScope
オブジェクトであるなら:
ソースタイプ source と relevantGlobal を与えた データ収集を有効化する 手順は次のとおりです:
ソースタイプ source と relevantGlobal を与えた データ収集を無効化する 手順は次のとおりです:
relevantGlobal、source、platformCollector を与えた データ収集 手順は次のとおりです:
PressureState に設定する。
PressureRecord オブジェクトとし、
その [[Source]] を
source に、
[[State]] を state に、
そして [[Time]] を
timeValue に設定する。
[[AfterPenaltyRecordMap]][source]
が 存在する 場合:
[[AfterPenaltyRecordMap]][source]
を record に設定する。
[[AfterPenaltyRecordMap]][source]
を record に設定する。
[[ChangesCountMap]][source]
を 0 に設定する。
[[PenaltyDuration]]
の期間でタイマーを作成し、次のコールバックを設定する:
[[AfterPenaltyRecordMap]][source]
が 存在する 場合:
[[AfterPenaltyRecordMap]][source]
とする。
[[AfterPenaltyRecordMap]][source]
を取り除く。
引数 observer、 source、record を与えた レコードをキューに入れる 手順は次のとおりです:
[[QueuedRecords]] において
最大キュー済レコード数 を超える場合、削除 により最初の 項目 を取り除く。
[[QueuedRecords]]
に追加する。
[[LastRecordMap]][source] を record
に設定する。
PressureObserver タスクソース は、タスクソースであり、10.6.5 Pressure Observer へ通知する タスクをスケジュールするために使用されます。
入力として relevantGlobal を与えた Pressure Observer タスクをキューに入れる 手順は次のとおりです:
入力として relevantGlobal を与えた Pressure Observer へ通知する 手順は次のとおりです:
[[QueuedRecords]] の複製とする。
[[QueuedRecords]] を空にする。
[[Callback]] を « records,
observer » と
"report" を引数として呼び出す。
本仕様は、Document document
に対する次の ドキュメントのアンロード時クリーンアップ手順 を定義します:
本仕様には以前、Document が再び fully active になるケース(すなわち
Document の reactivate
手順との統合)をカバーする手順が含まれていました。これらの手順は、意図する挙動について議論されている間、削除されています。
WorkerGlobalScope
relevantGlobal の
closing フラグが true
に設定されたとき、次の手順を実行します:
共有されていないオリジン間、すなわち非同一オリジンのサイト同士でも、同時にアクセス可能な一意または極めて高精度の値があると、ユーザーを識別できてしまう可能性があります。 この攻撃は、11.2.1 データ最小化、11.2.2 レート難読化、 および 11.2.7 同一オリジン制限 により緩和されます。
コンピュータセキュリティにおいて、秘匿チャネルは、本来通信が許可されないプロセス間で情報を転送する能力を生み出します。現代のマルチプロセス Web エンジンでは一般的に、各ウィンドウやタブは独自プロセスで実行されます(同一オリジンのドキュメントや、同一サイトは通常同じプロセスを共有します)。本 API を用いると、タブ A 上のサイト A がまず CPU の状態を操作した後、チャネル C に向けて送信を行い、続いて別タブ上の(サイト A と同一サイトではない)サイト B が本 API を使って CPU 状態の変化時刻を読み取り、チャネル C から送られたデータを受信する、といったクロスサイト秘匿チャネル C を構成できてしまう可能性があります。 この処理は、サイト A と B のスクリプトが稼動し続ける限り繰り返されます。
この攻撃は、11.2.2 レート難読化 と 11.2.5 キャリブレーション解除 により緩和されます。 実装者は、長時間実行されるスクリプトに対して、これらすべての緩和策を検討することが推奨されます。
標的型匿名性解除攻撃は、ユーザーの匿名性を危険に晒す重大な脅威クラスに該当します。これらの攻撃により、悪意のある、または一部が侵害された Web サイト(以下「悪性サイト」)は、訪問者が特定の公開識別子(例えばメールアドレスやソーシャルメディアのハンドル)を持っているかどうかを把握できるようになります。
匿名性は一部の人にとっては贅沢かもしれませんが、ある人々にとっては生存に関わる問題です。例えば、政治的抗議活動に参加する人や、機微なテーマを扱うジャーナリストなどが該当します。
一例として、攻撃者が被害者に対して公開のリソース共有サービス(以下「被害者サイト」)を用いてリソースを個別共有し、埋め込みリソースの読み込みによる副作用(アクセス成功を示唆)をサイドチャネルで測定することが挙げられます。ログイン済みの訪問者が埋め込まれたリソースにアクセスできた場合、現在の訪問者がまさに意図した標的であることが示されます。
とりわけ、総合的な CPU プレッシャーに関する信頼できる情報が露出すると、攻撃サイトはクロスオリジン遷移(例: 他サイトの iframe やポップアップ)先のターゲットが CPU 集約的な処理を実行したかどうかを把握できる可能性があります。
ポップアンダー や タブアンダー の手法は、ユーザーから読み込みを隠すために用いられ得ます。
可能な攻撃としては、悪性サイトがポップアップなどを開き、ユーザーがログインしている被害者サイト上のリソース(例: 動画配信サイトやオンラインドキュメントエディタ)において、特定ユーザーと共有されたリソースを指し示す、というものがあります。
リソースの読み込みが CPU への負荷増を招くと仮定すると、これはサイドチャネルを形成し、ユーザーが当該リソースへのアクセス権を持つアカウントにログインしているかどうかを攻撃サイトに明かし、ユーザーの匿名性を失わせます。
近年の CPU は高負荷からの回復が速いため、考えられる緩和策の一つとして、ポップアップや iframe コンテンツの読み込み後、数秒間は読み取りを一時的に無効化することが挙げられます。
本仕様は、基盤プラットフォームの低レベルな詳細に関するデータの露出を、高価値ユースケースに対応するために必要最小限に抑えるため、一般的な データ最小化 原則に従います。これには、デバイス識別情報の露出抑制に関する検討も含まれます。
本仕様の文脈におけるデータ最小化原則の具体的適用については、11.2.2 レート難読化 および 11.2.7 同一オリジン制限 で議論します。
本仕様は、レート難読化の緩和策の実装を要求します。これは、実装依存のスライディング観測ウィンドウに渡るプレッシャー変化回数を追跡し、その回数が実装依存の閾値を超えた場合にフラグを設定するものです。同様に、複数の状態にまたがる多数のプレッシャー状態変化など、異常な活動を観測した場合にも、同様にこのフラグを設定することが推奨されます。
このフラグが設定された場合、実装は、通常であればスクリプトにプレッシャー状態変化を通知するプレッシャーオブザーバに対して、一定期間ペナルティを与えることが推奨されます。このペナルティの期間は 実装依存であり、ランダム化することが推奨されます。 ペナルティ後に プレッシャーオブザーバへ通知 が再開された際には、直近のプレッシャー状態のみが報告され、ペナルティ中にプラットフォームコレクタから受信した中間状態情報は無視されます。
実装経験に基づき、実装者は次を用いなければなりません:
[[MaxChangesThreshold]] 内部スロットには
50〜100 回の変化の範囲。
[[PenaltyDuration]]
内部スロットには 5000〜10000 ミリ秒の範囲。
本節は非規範的です。
実装経験に基づき、実装者には次の使用が推奨されます:
[[ObservationWindow]] 内部スロットには 300000
ミリ秒(5 分)〜 600000 ミリ秒(10 分)の範囲。
キャリブレーション過程では、攻撃者が CPU を操作して、託されたワークロードにより本 API が特定のプレッシャー状態へ遷移すると報告する確率を最大化しようとします。 この キャリブレーション解除 の緩和策は、ランタイムにおいてこれらのプレッシャー状態遷移に寄与する 実装依存の低レベルハードウェア指標をわずかに変化させることで、キャリブレーションの成功を遅らせたり阻止したりします。 たとえ初期キャリブレーションが成功しても、本緩和策が継続的に動作している場合、その結果はランタイムで無効化されます。再キャリブレーションの試みも同様に緩和されます。
本節は非規範的です。
実装経験に基づき、緩和策は 120000 ミリ秒(2 分)〜 240000 ミリ秒(4 分)の範囲内でランダム化した時間値に対して適用することが推奨されます。
既定では、データ配信は、 アクティブな Picture-in-Picture セッションの開始者 と同一オリジンで配信されるドキュメント、キャプチャ中のドキュメント、 あるいは(存在する場合)システムフォーカスを持つドキュメントに制限されます。
上記の規則に基づきデータ配信の資格を満たすドキュメントは、子ナビゲーブル内のドキュメントに配信を委譲できます。
この機能を iframe などのサードパーティコンテキストに拡張するには、宣言済みポリシーが必要です。
共有ワーカーは、トップレベルドキュメントや、それに関連付けられた iframe などのドキュメント間で共有できます。所有者集合内のいずれかのドキュメントが上記のデータ配信要件を満たす場合、その共有ワーカーはデータ配信の資格を得ます。これは、埋め込み iframe が、埋め込み先ドキュメントにデータを受け渡せることを意味します。
Compute Pressure API はユーザー体験の向上に注力しています。API を利用するアプリケーションがアクセシビリティに良い影響を与える方法は二つあります。
API の利用者として、これら双方の機会を考慮することが重要です。以下はいくつかの例です:
Compute Pressure API は、インターフェースを完全に検証するには予測可能に応答する物理ハードウェアデバイスが必要となるため、テスト作成者にとって課題となります。
この課題に対処するため、本ドキュメントは [WEBDRIVER2] 拡張コマンド を定義しており、実際のもののように振る舞い、特定のプロパティを持ち、その読み取り値をユーザーが完全に定義できる仮想プレッシャーソースを定義・制御することを可能にします。
A virtual pressure source は、制御された方法で実際のものの動作をシミュレートする プレッシャーソース であり、接続された プラットフォームコレクタ に対してプレッシャーの変化を報告します。
しかし、実際の プレッシャーソース とは異なり、仮想プレッシャーソースは実装依存の値をプラットフォームコレクタが 実装依存 の値として報告するのではなく、プレッシャー状態 の値を直接報告します。言い換えれば、仮想プレッシャーソースの pressure source sample の data は PressureState です。
全ての プレッシャーソース に関連付けられたデータ(例えば pressure source sample など)に加えて、各 仮想プレッシャーソース は以下を持ちます:
各 トップレベルトラバーサブル は 仮想プレッシャーソースマッピング を持ち、これは 順序付きマップ で、ソースタイプ から 仮想プレッシャーソース への対応を保持します。
| HTTP メソッド | URI テンプレート |
|---|---|
| POST | /session/{session id}/pressuresource |
この 拡張コマンド は、指定された 仮想プレッシャーソース をある ソースタイプ で作成します。同じ ソースタイプ の observe()
を呼ぶと、該当する 仮想プレッシャーソース がそれらの裏側の プレッシャーソース として使用され、13.1.1.2
仮想プレッシャーソースを削除 が実行されるまでそのままになります。
| パラメータ名 | 値の型 | 必須 |
|---|---|---|
| type | String | はい |
| supported | Boolean | いいえ |
リモートエンド手順(session、URL variables、および parameters が与えられた場合)は次のとおりです:
| HTTP メソッド | URI テンプレート |
|---|---|
| DELETE | /session/{session id}/pressuresource/{type} |
この 拡張コマンド は指定された 仮想プレッシャーソース を削除します。つまり、利用可能であれば指定された ソースタイプ のデータは、非仮想の通常の手段で配信されるようになります。
リモートエンド手順(session、URL variables、および parameters が与えられた場合)は次のとおりです:
| HTTP メソッド | URI テンプレート |
|---|---|
| POST | /session/{session id}/pressuresource/{type} |
この 拡張コマンド は、新しい pressure source sample をプッシュすることで、仮想プレッシャーソース の状態を更新することを可能にします。
| パラメータ名 | 値の型 | 必須 |
|---|---|---|
| sample |
PressureState
|
はい |
リモートエンド手順(session、URL variables、および parameters が与えられた場合)は次のとおりです:
PressureState の型でない場合、WebDriver エラーコード
invalid argument のエラーを返す。
この節は非規範的です。
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");
次の例では、プレッシャーがクリティカルになったときに同時に配信するビデオストリームの数を減らしたいと考えています。簡潔にするためにここではこの一つの状態のみを考慮します。
ストリーム数を減らしてもクリティカル状態から抜けられない、あるいはすぐには抜けられない可能性があるため、クリティカル状態が続いている間は30秒ごとに一度ずつストリームを一つずつ減らすという戦略を用います。
これを実現するために、コールバックが少なくとも30秒ごとに一度呼ばれるようにし、あるいは状態が実際に変化したときにも呼ばれるようにします。状態が変化したときにはインターバルタイマーをリセットします。
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");
次の例では、コールバックが最後に呼び出されて以来蓄積された残りの records を取得することで、takeRecords() の使い方を示します。
これは disconnect()
の前に行うことを推奨します。そうしないと disconnect()
によってそれらは消去されて永遠に失われてしまいます。
例えば、ベンチマークのワークロード中のプレッシャーを測定したい場合、ワークロードの正確な期間のプレッシャーテレメトリが必要になります。これはタスク完了時にすべてのオブザーバを直ちに切断し、その時点までにまだイベントループサイクルの一部として配信されていない保留中のプレッシャーテレメトリを手動で要求することを意味します。
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();
次の例では、特定の source の監視を停止するようにオブザーバに指示する方法を、unobserve() を使って示します。
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'.
次の例では、disconnect()
を呼び出して、オブザーバに任意の状態変化の監視を停止させる方法を示します。disconnect() を呼び出すと、これまでの
observe()
呼び出しによって監視されていた全てのソースの監視を停止します。
さらに、最後のコールバックが呼ばれて以来収集された保留中の全てのレコードを消去します。
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();
非規範と明示されている節に加え、本仕様書の著者向けガイドライン、図、例、注はすべて非規範的です。本仕様書のそれ以外の全ては規範です。
文中のキーワード MAY、MUST、および RECOMMENDED は、かつそのときに限り、BCP 14 [RFC2119] [RFC8174] に記載されたとおりに解釈されます。
本仕様は単一の製品、すなわちここに含まれるインターフェースを実装する ユーザーエージェント に対する適合基準を定義します。
この節は非規範的です。
次の方々からの貴重なフィードバックと助言に深く感謝します: Anssi Kostiainen, Asaf Yaffe, Benjamin VanderSloot, 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, Reilly Grant, Ulan Degenbaev, Victor Miura, Wei Wang, および Zhenyao Mo
プライバシーのレビュー、フィードバック、および提案されたクロスサイトの潜在的な密かなチャネル攻撃とその軽減策については、W3C の Privacy Interest Group (PING) と特に Peter Snyder に感謝します。同様に、プライベートブラウジングのプライバシーと本仕様への関連する寄与に関して Ehsan Toreini に感謝します。
Zoom のエンジニアリングチームの Amanda Zhao、Fidel Tian、Zhiliang Wang およびその他の方々には、フィードバックと実地の実験を通じて本 API を実世界のシナリオで改善するのに役立てていただき、特に感謝します。
この節は非規範的です。
[[AfterPenaltyRecordMap]]
(PressureObserver の内部スロット)
§7.
[[Callback]] (PressureObserver
の内部スロット)
§7.
[[ChangesCountMap]]
(PressureObserver の内部スロット)
§7.
constructor()
(PressureObserver 用)
§10.2.1
"cpu"
(PressureSource の列挙値)
§3.2
"critical"
(PressureState の列挙値)
§8.
disconnect()
(PressureObserver のメソッド)
§10.2.4
"fair"
(PressureState の列挙値)
§8.
knownSources
(PressureObserver の属性)
§10.2.6
[[LastRecordMap]]
(PressureObserver の内部スロット)
§7.
[[MaxChangesThreshold]]
(PressureObserver の内部スロット)
§7.
"nominal"
(PressureState の列挙値)
§8.
[[ObservationWindow]]
(PressureObserver の内部スロット)
§7.
observe()
(PressureObserver のメソッド)
§10.2.2
[[PenaltyDuration]]
(PressureObserver の内部スロット)
§7.
[[PendingObservePromises]]
(PressureObserver の内部スロット)
§7.
PressureObserver
インターフェース
§10.2
PressureObserverOptions 辞書
§10.4
PressureRecord
インターフェース
§10.3
PressureSource 列挙
§3.2
PressureState 列挙
§8.
PressureUpdateCallback
§10.1
[[QueuedRecords]]
(PressureObserver の内部スロット)
§7.
sampleInterval
(PressureObserverOptions のメンバー)
§10.4.1
[[SampleIntervalMap]]
(PressureObserver の内部スロット)
§7.
"serious"
(PressureState の列挙値)
§8.
source
(PressureRecord の属性)
§10.3.1
[[Source]] (PressureRecord
の内部スロット)
§10.3
state
(PressureRecord の属性)
§10.3.2
[[State]] (PressureRecord
の内部スロット)
§10.3
takeRecords()
(PressureObserver のメソッド)
§10.2.5
time
(PressureRecord の属性)
§10.3.3
[[Time]] (PressureRecord
の内部スロット)
§10.3
toJSON
(PressureRecord のメソッド)
§10.3.4
unobserve()
(PressureObserver のメソッド)
§10.2.3
Document インターフェース
Node 用)
ECMAScript 用)
globalThis 属性(globalThis 用)
DOMHighResTimeStamp
WorkerGlobalScope 用)
DedicatedWorkerGlobalScope インターフェース
Document 用)
iframe 要素
WorkerGlobalScope 用)
WorkerGlobalScope 用)
Window インターフェース
WorkerGlobalScope インターフェース
AbortError 例外
[Default] 拡張属性
[EnforceRange] 拡張属性
[Exposed] 拡張属性
FrozenArray インターフェース
NotAllowedError 例外
NotSupportedError 例外
object
型
Promise インターフェース
[SameObject] 拡張属性
[SecureContext] 拡張属性
TypeError 例外
undefined 型
unsigned long 型
WebIDLenum PressureSource { "cpu" };
enum PressureState { "nominal", "fair", "serious", "critical" };
callback PressureUpdateCallback = undefined (
sequence<PressureRecord> changes,
PressureObserver observer
);
[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;
};
[Exposed=(DedicatedWorker,SharedWorker,Window), SecureContext]
interface PressureRecord {
readonly attribute PressureSource source;
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: