メモリ測定API

ドラフト コミュニティグループレポート、

このバージョン:
https://wicg.github.io/performance-measure-memory/
編集者:
(Google)
参加:
GitHub WICG/performance-measure-memory (新しいイシュー, オープンなイシュー)

概要

この仕様は、ウェブアプリケーションが自らのメモリ使用量を測定するためのAPIを定義します。

この文書のステータス

この仕様はWeb Platform Incubator Community Groupによって公開されました。 これはW3C標準ではなく、W3C標準トラックにも載っていません。 W3C Community Contributor License Agreement (CLA)の下で限定的なオプトアウトや他の条件が適用されることにご注意ください。 W3C Community and Business Groupsについてさらに学んでください。

1. はじめに

多くのアルゴリズムやデータ構造には、メモリとパフォーマンスのトレードオフが本質的に存在します。 現在のWeb開発者にはタイミング情報を計測する複数の方法がありますが、メモリ使用量を測定する標準的な方法はありません。 この仕様は、ウェブアプリケーションの自身のメモリ使用量(すべてのiframeやworkerを含む)を推定するperformance.measureUserAgentSpecificMemory() APIを定義します。 新しいAPIは、本番環境でのメモリ使用量データの集計を目的としています。主な利用ケースは以下の通りです:

1.1. 例

performance.measureUserAgentSpecificMemory() の呼び出しはPromise を返し、 ページによって割り当てられたメモリの非同期測定を開始します。

async function run() {
  const result = await performance.measureUserAgentSpecificMemory();
  console.log(result);
}
run();

iframeやworkerを含まないシンプルなページの場合、結果は次のようになります:

{
  bytes: 1000000,
  breakdown: [
    {
      bytes: 1000000,
      attribution: [
        {
          url: "https://example.com",
          scope: "Window",
        },
      ],
      types: ["JS", "DOM"],
    },
    {
      bytes: 0,
      attribution: [],
      types: [],
    },
  ],
}
ここでは、すべてのメモリがメインページに帰属しています。 bytes: 0のエントリは、特定のエントリをハードコーディングせず、ジェネリックな方法で結果を処理することを推奨するためにbreakdownリストに存在します。 リストが空でなければ、このようなエントリがランダムな位置に挿入されます。

他の有効な結果の例:

{
  bytes: 1000000,
  breakdown: [],
}
ここでは、実装は総メモリ使用量のみを提供しています。
{
  bytes: 1000000,
  breakdown: [
    {
      bytes: 0,
      attribution: [],
      types: [],
    },
    {
      bytes: 1000000,
      attribution: [
        {
          url: "https://example.com",
          scope: "Window",
        },
      ],
      types: [],
    },
  ],
}
ここでは実装がメモリタイプ別に分解を行っていません。

同一オリジンiframeを埋め込むページの場合、そのiframeに一部のメモリが帰属され、 iframeを識別するための診断情報が提供される場合があります:

  <html>
    <body>
      <iframe id="example-id" src="redirect.html?target=iframe.html"></iframe>
    </body>
  </html>
{
  bytes: 1500000,
  breakdown: [
    {
      bytes: 1000000,
      attribution: [
        {
          url: "https://example.com",
          scope: "Window",
        },
      ],
      types: ["DOM", "JS"],
    },
    {
      bytes: 0,
      attribution: [],
      types: [],
    },
    {
      bytes: 500000,
      attribution: [
        {
          url: "https://example.com/iframe.html"
          container: {
            id: "example-id",
            src: "redirect.html?target=iframe.html",
          },
          scope: "Window",
        }
      ],
      types: ["JS", "DOM"],
    },
  ],
}

iframeのurlとcontainer.srcフィールドがどのように異なるかに注目してください。 前者はiframeの現在のlocation.hrefを反映し、 後者はsrc属性値です。

iframeのメモリをページのメモリから意味のある形で分割できるとは限りません。 実装によっては、iframeとページのメモリをまとめて扱う場合も許容されています:

{
  bytes: 1500000,
  breakdown: [
    {
      bytes: 1500000,
      attribution: [
        {
          url: "https://example.com",
          scope: "Window",
        },
        {
          url: "https://example.com/iframe.html",
          container: {
            id: "example-id",
            src: "redirect.html?target=iframe.html",
          },
          scope: "Window",
        },
      ],
      types: ["JS", "DOM"],
    },
    {
      bytes: 0,
      attribution: [],
      types: [],
    },
  ],
};
ページがWeb Workerを生成した場合、結果にはworkerのURLが含まれます。
{
  bytes: 1800000,
  breakdown: [
    {
      bytes: 0,
      attribution: [],
      types: [],
    },
    {
      bytes: 1000000,
      attribution: [
        {
          url: "https://example.com",
          scope: "Window",
        },
      ],
      types: ["JS", "DOM"],
    },
    {
      bytes: 800000,
      attribution: [
        {
          url: "https://example.com/worker.js",
          scope: "DedicatedWorkerGlobalScope",
        },
      ],
      types: ["JS"],
    },
  ],
};
実装によってはworkerとページのメモリをまとめて計上する場合があります。iframeがworkerを生成した場合、workerのattributionエントリにはiframe要素に対応するcontainerフィールドが入ります。

共有およびサービスワーカーのメモリは結果に含まれません。

共有/サービスワーカーのメモリ使用量を取得するには、そのワーカーのコンテキストでperformance.measureUserAgentSpecificMemory() を呼ぶ必要があります。 結果は次のようになる場合があります:
{
  bytes: 1000000,
  breakdown: [
    {
      bytes: 1000000,
      attribution: [
        {
          url: "https://example.com/service-worker.js",
          scope: "ServiceWorkerGlobalScope",
        },
      ],
      types: ["JS"],
    },
    {
      bytes: 0,
      attribution: [],
      types: [],
    },
  ],
}
クロスオリジンiframeを埋め込んだページの場合、そのiframeのURLは情報漏洩防止のため公開されません。既にページが知っているcontainer要素だけが結果に現れます。 また、クロスオリジンiframe内で他のクロスオリジンiframeやworkerが埋め込まれる/生成される場合、それらの全メモリは最上位クロスオリジンiframeに帰属されます。

以下の構成のページを考えます:

example.com (1000000 bytes)
  |
  *--foo.com/iframe1 (500000 bytes)
       |
       *--foo.com/iframe2 (200000 bytes)
       |
       *--bar.com/iframe2 (300000 bytes)
       |
       *--foo.com/worker.js (400000 bytes)
クロスオリジンiframeが他のiframeやworkerを内包しています。 これら全リソースのメモリは、最初のiframeに帰属されます。
  <html>
    <body>
      <iframe id="example-id" src="https://foo.com/iframe1"></iframe>
    </body>
  </html>
{
  bytes: 2400000,
  breakdown: [
    {
      bytes: 1000000,
      attribution: [
        {
          url: "https://example.com",
          scope: "Window",
        },
      ],
      types: ["JS", "DOM"],
    },
    {
      bytes: 0,
      attribution: [],
      types: [],
    },
    {
      bytes: 1400000,
      attribution: [
        {
          url: "cross-origin-url",
          container: {
            id: "example-id",
            src: "https://foo.com/iframe1",
          },
          scope: "cross-origin-aggregated",
        },
      ],
      types: ["DOM", "JS"],
    },
  ],
}
クロスオリジンiframeのurlおよびscopeフィールドは、情報が利用できないことを示す特別な値となることに注意してください。

実装がクロスオリジンiframeを異なるアドレス空間でロードする場合、そのメモリ使用量は測定されません。 そのようなiframeのbreakdownエントリはbytes: 0となり、対象外であることを示します:

{
  bytes: 100000,
  breakdown: [
    {
      bytes: 1000000,
      attribution: [
        {
          url: "https://example.com",
          scope: "Window",
        },
      ],
      types: ["JS", "DOM"],
    },
    {
      bytes: 0,
      attribution: [
        {
          url: "cross-origin-url",
          container: {
            id: "example-id",
            src: "https://foo.com/iframe1",
          },
          scope: "cross-origin-aggregated",
        },
      ],
      types: ["JS", "DOM"],
    },
    {
      bytes: 0,
      attribution: [],
      types: [],
    },
  ],
}
クロスオリジンiframeがメインページと同じオリジンのiframeを内包する場合、 結果にその同一オリジンiframeが現れます。 メインページは同一オリジンiframeのlocation.hrefにアクセスできるため、情報漏洩はありません。
example.com (1000000 bytes)
  |
  *--foo.com/iframe1 (500000 bytes)
       |
       *--example.com/iframe2 (200000 bytes)
  <html>
    <body>
      <iframe id="example-id" src="https://foo.com/iframe1"></iframe>
    </body>
  </html>
{
  bytes: 1700000,
  breakdown: [
    {
      bytes: 1000000,
      attribution: [
        {
          url: "https://example.com",
          scope: "Window",
        },
      ],
      types: ["DOM", "JS"],
    },
    {
      bytes: 0,
      attribution: [],
      types: [],
    },
    {
      bytes: 500000,
      attribution: [
        {
          url: "cross-origin-url",
          container: {
            id: "example-id",
            src: "https://foo.com/iframe1",
          },
          scope: "cross-origin-aggregated",
        },
      ],
      types: ["DOM", "JS"],
    },
    {
      bytes: 200000,
      attribution: [
        {
          url: "https://example.com/iframe2",
          container: {
            id: "example-id",
            src: "https://foo.com/iframe1",
          },
          scope: "Window",
        },
      ],
      types: ["JS", "DOM"],
    },
  ],
}

実装がクロスオリジンiframeのメモリ測定を省略した場合、結果は次のようになる場合もあります:

{
  bytes: 1200000,
  breakdown: [
    {
      bytes: 1000000,
      attribution: [
        {
          url: "https://example.com",
          scope: "Window",
        },
      ],
      types: ["JS", "DOM"],
    },
    {
      bytes: 0,
      attribution: [
        {
          url: "cross-origin-url",
          container: {
            id: "example-id",
            src: "https://foo.com/iframe1",
          },
          scope: "cross-origin-aggregated",
        },
      ],
      types: ["JS", "DOM"],
    },
    {
      bytes: 200000,
      attribution: [
        {
          url: "https://example.com/iframe2",
          container: {
            id: "example-id",
            src: "https://foo.com/iframe1",
          },
          scope: "Window",
        },
      ],
      types: ["JS", "DOM"],
    },
    {
      bytes: 0,
      attribution: [],
      types: [],
    },
  ],
}

2. データモデル

2.1. メモリ測定結果

performance.measureUserAgentSpecificMemory() 関数は Promise を返し、MemoryMeasurement 辞書のインスタンスに解決されます:

dictionary MemoryMeasurement {
  unsigned long long bytes;
  sequence<MemoryBreakdownEntry> breakdown;
};
measurement . bytes

合計メモリ使用量を表す数値。

measurement . breakdown

合計bytes を分割し、帰属情報やタイプ情報を提供する配列。

dictionary MemoryBreakdownEntry {
  unsigned long long bytes;
  sequence<MemoryAttribution> attribution;
  sequence<DOMString> types;
};
breakdown . bytes

このエントリが記述するメモリのサイズ。

breakdown . attribution

そのメモリを利用しているJavaScript realmのURLおよび/またはコンテナ要素の配列。

breakdown . types

メモリに関連付けられた実装依存のメモリ種別の配列。

dictionary MemoryAttribution {
  USVString url;
  MemoryAttributionContainer container;
  DOMString scope;
};
attribution . url

この帰属が同一オリジンのJavaScript realmに対応する場合、このフィールドはrealmのURLを含みます。 それ以外の場合、帰属は1つまたは複数のクロスオリジンJavaScript realm向けで、このフィールドはセンチネル値"cross-origin-url"となります。

attribution . container

JavaScript realmを(間接的に)内包するDOM要素を記述します。 このプロパティは、同一オリジンのトップレベルrealmの帰属では省略される場合があります。 クロスオリジンrealmはクロスオリジン分離のため、トップレベルになれない点に注意してください。

attribution . scope

同一オリジンJavaScript realmの種別を記述します。 "Window", "DedicatedWorkerGlobalScope", "SharedWorkerGlobalScope", "ServiceWorkerGlobalScope" またはクロスオリジン用の"cross-origin-aggregated"。

dictionary MemoryAttributionContainer {
  DOMString id;
  USVString src;
};
container . id

コンテナ要素のid属性。

container . src

コンテナ要素のsrc属性。コンテナ要素がobject 要素の場合、このフィールドは data 属性値となります。

2.2. 中間メモリ測定

本仕様は、与えられた現在のエージェントクラスタのアドレス空間内で、指定されたエージェントクラスタ集合のメモリ使用量を測定する実装依存アルゴリズムの存在を仮定します。 このようなアルゴリズムの結果は中間メモリ測定であり、 これは集合としての中間メモリ分解エントリからなります。

アドレス空間分離のセキュリティ保証を維持するため、現在のアドレス空間外のメモリを表す中間メモリ分解エントリはbytesを0にする必要があります。

フィンガープリンティングリスク低減のため、 結果には与えられたエージェントクラスタ集合によって割り当てまたは利用されたWebプラットフォームオブジェクトに関連するメモリのみが含まれる必要があります。 例えばこれにはユーザーエージェント固有拡張や空ページのベースラインメモリは含まれません。 メモリはアドレス空間レベルで計上し、メモリ圧縮や遅延確保などプラットフォーム固有最適化は除外する必要があります。

中間メモリ分解エントリは、次の構造体の項目を持ちます:

bytes

この中間メモリ分解エントリが記述するメモリサイズ、または現在のアドレス空間外の場合は0。

realms

そのメモリが割り当てられるJavaScript realmの集合。

types

メモリに結びつけられた実装依存メモリ種別を指定する文字列の集合。

本仕様で定義されるアルゴリズムは、中間メモリ測定をMemoryMeasurement インスタンスに変換する方法を示します。

2.3. メモリ帰属トークン

埋め込みJavaScript realmとそのコンテナ要素のリンクは一時的で、常に存在が保証されるものではありません。 例えば、コンテナ要素で他のドキュメントへナビゲートしたり、DOMツリーから要素を削除した場合、このリンクは切断されます。

メモリ帰属トークンは、JavaScript realmからそのコンテナ要素への参照方法を提供します。 これは構造体で、以下の項目を持ちます:

container

MemoryAttributionContainer のインスタンス。

cross-origin aggregated flag

このトークンがクロスオリジンJavaScript realmのメモリ集計用として作成されたかどうかを示すブールフラグ。

この値はWindowOrWorkerGlobalScope の新しい内部フィールドに構築時保持され、常にメモリレポートで利用可能です。

3. 処理モデル

3.1. Performance インターフェースへの拡張

partial interface Performance {
  [Exposed=(Window,ServiceWorker,SharedWorker), CrossOriginIsolated] Promise<MemoryMeasurement> measureUserAgentSpecificMemory();
};
performance . measureUserAgentSpecificMemory()

非同期メモリ測定を行うメソッド。このメソッドの結果詳細は §2.1 メモリ測定結果 を参照。

3.2. トップレベルアルゴリズム

measureUserAgentSpecificMemory() メソッドの手順:
  1. アサート:現在のRealmのsettings objectのクロスオリジン分離機能がtrueであること。

  2. memory measurement allowed predicate を現在のRealmで評価し、偽であれば:

    1. a promise rejected with "SecurityError" DOMException を返す。

  3. 現在のエージェントクラスタを、現在のRealmのagentのエージェントクラスタとする。

  4. agent clusters を get all agent clustersに現在のRealmを渡して実行した結果とする。

  5. 新しいPromise をpromiseとする。

  6. 非同期で実装依存メモリ測定を現在のエージェントクラスタ、agent clusters、promiseを用いて開始する。

  7. promiseを返す。

memory measurement allowed predicate を JavaScript realm realm で評価する:
  1. global object を realm の global object とする。

  2. global objectがSharedWorkerGlobalScopeならtrueを返す。

  3. global objectがServiceWorkerGlobalScopeならtrueを返す。

  4. global objectがWindow なら

    1. settings object を realm の settings objectとする。

    2. settings object のoriginが settings objectのトップレベルoriginと同じならtrueを返す。

  5. falseを返す。

get all agent clusters をJavaScript realm realm で実行するには:
  1. realmのglobal objectがWindowのとき:

    1. group を browsing context groupで、realmのglobal objectのbrowsing contextを含むものとする。

    2. groupのagent cluster mapの値取得結果を返す。

  2. « realmのagentのエージェントクラスタ » を返す。

実装依存メモリ測定を エージェントクラスタ 現在のエージェントクラスタ、 集合としての エージェントクラスタ agent clusters、 Promise promise を受けて 並列に以下を実行:
  1. intermediate memory measurement を現在のエージェントクラスタとagent clustersで実装依存の中間メモリ測定の実行結果とする。

  2. promiseのrelevant global objectに、グローバルタスクをキューイングし、 resolve promiseを新しいMemoryMeasurementの生成(intermediate memory measurement渡し)で解決する。

3.3. 中間メモリ測定を結果に変換する

新しいメモリ測定を作成するには、中間メモリ測定 intermediate measurement を与える:
  1. bytes を0とする。

  2. それぞれの 中間メモリ分解エントリ intermediate entry をintermediate measurementから取り出して:

    1. bytes に bytes + intermediate entry の bytes を設定。

  3. breakdown を新しいリストとする。

  4. 新規に MemoryBreakdownEntry をbreakdownへ追加する。この:

  5. それぞれの 中間メモリ分解エントリ intermediate entry をintermediate measurementから取り出して:

    1. breakdown entry を 新しいメモリ分解エントリを作成する (intermediate entry ) の結果とする。

    2. 追加 breakdown entry をbreakdownへ。

  6. breakdown 内の項目順をランダム化する。

  7. 新しい MemoryMeasurement を返す。これは:

新しいメモリ分解エントリを作成するには、中間メモリ分解エントリ intermediate entry を与える:
  1. attribution を新しいリストとする。

  2. それぞれの JavaScript realm realm を intermediate entry の realms から取り出して:

    1. attribution entry を 新しいメモリ帰属を作成する (realm) の結果とする。

    2. 追加 attribution entry を attribution へ。

  3. types を intermediate entry の types とする。

  4. types 内の項目順をランダム化する。

  5. 新しい MemoryBreakdownEntry を返す。これは:

新しいメモリ帰属を作成するには、JavaScript realm realm を与える:
  1. token を realm の global object の メモリ帰属トークン とする。

  2. token の cross-origin aggregated flag がtrueなら:

    1. 新しい MemoryAttribution を返す。これは:

      • url は "cross-origin-url",

      • container は token の container(nullでなければ)であり、そうでなければ container 項目は省略される,

      • scope は "cross-origin-aggregated"。

  3. scope name を identifier として、realm の global object のinterface名を取得。

  4. 新しい MemoryAttribution を返す。これは:

3.4. メモリ帰属トークンの作成または取得

windowメモリ帰属トークンを取得するには、origin origin、origin parent origin、origin top-level origin、 HTMLElement container element、およびメモリ帰属トークン parent tokenを与える:
  1. container element がnullの場合:

    1. アサート:parent origin はnull。

    2. アサート:parent token はnull。

    3. アサート:origin はparent origin と等しい。

    4. 新しいメモリ帰属トークンを返す。これは:

  2. parent origin がtop-level originと等しくない場合:

    1. parent token を返す。

  3. container を コンテナ要素属性抽出(container element) の結果とする。

  4. origin がtop-level originと等しい場合:

    1. 新しいメモリ帰属トークンを返す。これは:

  5. 新しいメモリ帰属トークンを返す。これは:

workerメモリ帰属トークンを取得するには、WorkerGlobalScope worker global scope、environment settings object outside settings を与える:
  1. worker global scope が DedicatedWorkerGlobalScope の場合、 outside settings の global object の メモリ帰属トークン を返す。

  2. アサート:worker global scope は SharedWorkerGlobalScope または ServiceWorkerGlobalScope である。

  3. 新しいメモリ帰属トークンを返す。これは:

コンテナ要素属性抽出には、HTMLElement container element を与える:
  1. container element の local name を判定:

    "iframe"

    新しい MemoryAttributionContainer を返す。これは:

    • id は container element の id 属性,

    • src は container element の src 属性,

    "frame"

    新しい MemoryAttributionContainer を返す。これは:

    • id は container element の id 属性,

    • src は container element の src 属性,

    "object"

    新しい MemoryAttributionContainer を返す。これは:

    • id は container element の id 属性,

    • src は container element の data 属性,

4. 既存仕様との統合

4.1. WindowOrWorkerGlobalScopeへの拡張

新しい内部フィールドがWindowOrWorkerGlobalScopeに追加される:
メモリ帰属トークン

この環境のメモリ使用量を報告するのに使われるメモリ帰属トークン。

4.2. 既存アルゴリズムへの拡張

ワーカーの実行アルゴリズムは、ステップ6で新たに作成されるグローバルオブジェクトの メモリ帰属トークンフィールドを設定する:

  1. realm execution context を agent と以下カスタマイズで新しい JavaScript realm を作成した結果とする:

Document オブジェクトの作成および初期化アルゴリズムは、 新たに作成されるグローバルオブジェクトのメモリ帰属トークンフィールドを設定する:

  1. それ以外の場合:

    1. token を空のメモリ帰属トークンとする。

    2. browsingContext がトップレベルでない場合:

      1. parentToken を parentEnvironmentのグローバルオブジェクトのメモリ帰属トークンとする。

      2. token に origin、 parentEnvironment のorigin、topLevelOrigin、 browsingContextのcontainer、parentToken を与えて windowメモリ帰属トークン取得した結果を設定。

    3. そうでなければ、origin、null topLevelOrigin、null、null で windowメモリ帰属トークン取得し、 その結果をtokenに設定。

    4. window global scope を realm execution contextの Realm コンポーネントのグローバルオブジェクトとする。

    5. window global scopeのメモリ帰属トークンにtokenを設定。

新しいブラウジングコンテキストの作成アルゴリズムは、 新たに作成されるグローバルオブジェクトのメモリ帰属トークンフィールドを設定する:

  1. token を空のトークンとする。

  2. embedder がnullの場合、token にorigin、 null、topLevelOrigin、null、null で windowメモリ帰属トークン取得した結果を設定。

  3. そうでなければ、tokenに origin、embedderのrelevant settings objectのorigin、 topLevelOrigin、embedder、embedderのrelevant global object のメモリ帰属トークンを与えて windowメモリ帰属トークン取得の結果を設定。

  4. window global scope を realm execution contextの Realm コンポーネントのグローバルオブジェクトとする。

  5. window global scopeのメモリ帰属トークンにtokenを設定。

5. プライバシーとセキュリティ

5.1. クロスオリジン情報漏洩

結果に現れるURLや他の文字列値は、APIを呼び出したオリジンが知っていることが保証されている。

クロスオリジンで公開される唯一の情報は、memoryMeasurement.bytes とmemoryBreakdownEntry.bytes で提供されるサイズ情報である。 APIはクロスオリジン分離 メカニズムによりクロスオリジンのサイズ情報漏洩を緩和している。 すなわち、現在のアドレス空間内のすべてのリソースが埋め込み元オリジンによる埋め込みや認識を許可しているという不変式を前提とする。 異なるアドレス空間でロードされるクロスオリジンリソースのサイズはAPIで公開されない。

5.2. フィンガープリンティング

このAPIの結果は、そのウェブページ自身が割り当てたオブジェクトのみに依存し、空のウェブページの基準メモリ使用量など、無関係なメモリは含まれない。 つまり、同一のバイナリのユーザーエージェントが異なる端末であっても、同じ固定ページに対しては同じ結果となるべきである。

ウェブページはユーザーエージェントについて以下の情報を推定可能である:

同様の情報は既存API(navigator.userAgent、 navigator.platformなど)でも得られる。 ユーザーエージェントのビット幅は32/64bit演算の実行時間測定からも推定できる。

現状、このAPIはトップレベルオリジンだけが利用できる。 将来的にはトップレベルオリジンがPermissions Policyで他のオリジンへAPI利用を委譲可能になる予定である。 いずれの場合も、クロスオリジンiframeはデフォルトではAPIにアクセスできない。

6. 謝辞

Domenic Denicola氏、Shu-yu Guo氏にAPI設計貢献および仕様レビューの謝意を示す。

また、Adam Giacobbe氏、Anne van Kesteren氏、Artur Janc氏、Boris Zbarsky氏、Chris Hamilton氏、Chris Palmer氏、Daniel Vogelheim氏、Dominik Inführ氏、Hannes Payer氏、Joe Mason氏、Kentaro Hara氏、L. David Baron氏、Mathias Bynens氏、Matthew Bolohan氏、Michael Lippautz氏、Mike West氏、Neil Mckay氏、Olga Belomestnykh氏、Per Parker氏、Philipp Weis氏、Yoav Weiss氏にフィードバックおよび貢献の謝意を示す。

索引

本仕様で定義された用語

参照によって定義された用語

参考文献

規範的参考文献

[DOM]
Anne van Kesteren. DOM Standard. Living Standard. URL: https://dom.spec.whatwg.org/
[ECMASCRIPT]
ECMAScript Language Specification. URL: https://tc39.es/ecma262/
[HR-TIME-2]
Ilya Grigorik. High Resolution Time Level 2. URL: https://w3c.github.io/hr-time/
[HTML]
Anne van Kesteren; et al. HTML Standard. Living Standard. URL: https://html.spec.whatwg.org/multipage/
[INFRA]
Anne van Kesteren; Domenic Denicola. Infra Standard. Living Standard. URL: https://infra.spec.whatwg.org/
[SERVICE-WORKERS-1]
Alex Russell; et al. Service Workers 1. URL: https://w3c.github.io/ServiceWorker/
[WebIDL]
Boris Zbarsky. Web IDL. URL: https://heycam.github.io/webidl/

IDL索引

dictionary MemoryMeasurement {
  unsigned long long bytes;
  sequence<MemoryBreakdownEntry> breakdown;
};

dictionary MemoryBreakdownEntry {
  unsigned long long bytes;
  sequence<MemoryAttribution> attribution;
  sequence<DOMString> types;
};

dictionary MemoryAttribution {
  USVString url;
  MemoryAttributionContainer container;
  DOMString scope;
};

dictionary MemoryAttributionContainer {
  DOMString id;
  USVString src;
};

partial interface Performance {
  [Exposed=(Window,ServiceWorker,SharedWorker), CrossOriginIsolated] Promise<MemoryMeasurement> measureUserAgentSpecificMemory();
};