메모리 측정 API

초안 커뮤니티 그룹 보고서,

현재 버전:
https://wicg.github.io/performance-measure-memory/
에디터:
(Google)
참여하기:
GitHub WICG/performance-measure-memory (새 이슈, 오픈 이슈)

개요

이 명세서는 웹 애플리케이션이 자신의 메모리 사용량을 측정할 수 있는 API를 정의합니다.

이 문서의 상태

이 명세서는 웹 플랫폼 인큐베이터 커뮤니티 그룹에서 발행했습니다. W3C 표준이 아니며 W3C 표준 트랙에도 포함되어 있지 않습니다. W3C 커뮤니티 기여자 라이선스 계약 (CLA)에 따라 제한적 옵트아웃 및 기타 조건이 적용됨에 유의하시기 바랍니다. W3C 커뮤니티 및 비즈니스 그룹에 대해 자세히 알아보세요.

1. 소개

메모리와 성능 간의 트레이드오프는 많은 알고리즘과 데이터 구조에서 내재되어 있습니다. 현재 웹 개발자는 타이밍 정보를 측정하는 다양한 방법을 가지고 있지만, 메모리 사용량을 측정하는 표준 방법은 없습니다. 이 명세서는 performance.measureUserAgentSpecificMemory() API를 정의하며, 이는 웹 애플리케이션의 모든 iframe과 worker를 포함하여 메모리 사용량을 추산합니다. 새 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"],
    },
  ],
}
url 필드와 container.src 필드가 iframe에 대해 서로 다름을 주목하세요. 전자는 iframe의 현재 location.href를 반영하고, 후자는 iframe 요소의 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: [],
    },
  ],
};
웹 워커를 생성하는 페이지의 경우, 결과에 워커의 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"],
    },
  ],
};
구현체가 워커와 페이지 메모리를 합쳐서 제공할 수 있습니다. 워커가 iframe에 의해 생성된 경우, 워커의 귀속 항목에 해당 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은 정보 유출을 피하기 위해 표시되지 않습니다. 결과에는 이미 페이지에서 알고 있는 컨테이너 요소만 나타납니다. 또한 교차 출처 iframe이 다른 교차 출처 iframe을 포함하거나 워커를 생성하면, 이들의 모든 메모리가 최상위 교차 출처 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을 포함하고, 워커도 생성합니다. 이러한 리소스의 모든 메모리는 첫 번째 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 항목의 urlscope 필드는 정보가 없음을 나타내는 특수 값을 가집니다.

구현체가 교차 출처 iframe을 별도의 주소 공간에서 로드하면, 해당 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 딕셔너리 인스턴스로 resolve됩니다:

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을 포함합니다. 그렇지 않으면 귀속 정보는 하나 이상의 교차 출처 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으로 설정해야 합니다.

핑거프린팅 위험을 줄이기 위해, 결과에는 주어진 에이전트 클러스터 집합에 의해 할당되거나 사용된 웹 플랫폼 객체와 관련된 메모리만 포함해야 합니다. 예를 들어, UA(사용자 에이전트) 고유 확장과 빈 페이지의 기준 메모리는 제외해야 합니다. 메모리는 주소 공간 수준에서 집계되어야 하며, 메모리 압축, 지연 메모리 할당 등 플랫폼 전용 메모리 최적화는 제외해야 합니다.

중간 메모리 분할 엔트리는 다음 항목을 가지는 struct입니다:

bytes

중간 메모리 분할 엔트리가 설명하는 메모리의 크기 또는 이 엔트리가 현재 주소 공간 외부의 메모리를 나타내면 0입니다.

realms

메모리가 귀속되는 집합JavaScript Realm 들입니다.

types

메모리와 연관된 구현 정의 메모리 타입을 지정하는 집합문자열 입니다.

본 명세서에서 정의한 알고리즘은 중간 메모리 측정MemoryMeasurement 인스턴스로 변환하는 방법을 보여줍니다.

2.3. 메모리 귀속 토큰

임베드된 JavaScript Realm과 그 컨테이너 요소 사이의 연결은 일시적이며 항상 존재함이 보장되지 않습니다. 예를 들어, 컨테이너 요소 내에서 다른 문서로 내비게이션하거나 해당 요소를 DOM 트리에서 제거하면 연결이 끊어집니다.

메모리 귀속 토큰JavaScript Realm에서 컨테이너 요소로 이동할 수 있는 방법을 제공합니다. 이는 다음 항목을 가지는 struct입니다:

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. Assert: 현재 Realmsettings objectcross-origin isolated capability가 true임을 보장한다.

  2. 메모리 측정 허용 조건자에 현재 Realm을 넘기면 false인 경우:

    1. promise를 "SecurityError" DOMException으로 reject하여 반환한다.

  3. the current agent cluster를 현재 Realm의 agent에이전트 클러스터로 할당한다.

  4. agent clustersget all agent clusters에 현재 Realm을 넘겨 구한다.

  5. promise를 새로운 Promise로 생성한다.

  6. the current agent cluster, agent clusters, promise를 인자로 비동기 구현 정의 메모리 측정을 시작한다.

  7. promise를 반환한다.

메모리 측정 허용 조건자JavaScript Realm realm에 대해 평가하려면:
  1. global objectrealmglobal object로 할당한다.

  2. global objectSharedWorkerGlobalScope이면 true를 반환한다.

  3. global objectServiceWorkerGlobalScope이면 true를 반환한다.

  4. global objectWindow이면

    1. settings objectrealmsettings object로 할당한다.

    2. settings objectoriginsettings objecttop-level origin과 같으면 true를 반환한다.

  5. false를 반환한다.

get all agent clustersJavaScript Realm realm에 대해 실행하려면:
  1. realmglobal objectWindow이면:

    1. group브라우징 컨텍스트 그룹으로 할당하며, 이는 realmglobal objectbrowsing context를 포함한다.

    2. groupagent cluster map에서 값들을 가져와서 반환한다.

  2. « realmagent에이전트 클러스터 »를 반환한다.

구현 정의 메모리 측정에이전트 클러스터 the current agent cluster, 집합에이전트 클러스터들 agent clusters, Promise promise에 대해 병렬로 다음 단계 실행:
  1. intermediate memory measurement구현 정의 중간 메모리 측정the current agent clusteragent clusters에 대해 수행한다.

  2. promiserelevant global object에서 TODO 태스크 소스에 글로벌 태스크를 큐에 추가하여, resolve promise새로운 메모리 측정 생성 결과로 완료한다.

3.3. 중간 메모리 측정값을 결과로 변환하기

새로운 메모리 측정값 생성중간 메모리 측정값 intermediate measurement에 대해 수행하려면:
  1. bytes를 0으로 둔다.

  2. 각각의 중간 메모리 분할 엔트리 intermediate entry에 대해 intermediate measurement에서:

    1. bytesbytes + intermediate entrybytes로 설정한다.

  3. breakdown을 새로운 리스트로 둔다.

  4. breakdown에 다음 내용을 가진 새로운 MemoryBreakdownEntry를 추가한다:

  5. 각각의 중간 메모리 분할 엔트리 intermediate entry에 대해 intermediate measurement에서:

    1. breakdown entry새로운 메모리 분할 엔트리 생성의 결과로 둔다 (intermediate entry를 인자로).

    2. breakdownbreakdown entry를 추가한다.

  6. breakdown의 순서를 임의로 섞는다.

  7. 다음 값을 가진 새로운 MemoryMeasurement를 반환한다:

새로운 메모리 분할 엔트리 생성중간 메모리 분할 엔트리 intermediate entry에 대해 수행하려면:
  1. attribution을 새로운 리스트로 둔다.

  2. 각각의 JavaScript realm realm에 대해 intermediate entryrealms에서:

    1. attribution entry새로운 메모리 귀속 정보 생성의 결과로 둔다 (realm를 인자로).

    2. attributionattribution entry를 추가한다.

  3. typesintermediate entrytypes로 둔다.

  4. types의 순서를 임의로 섞는다.

  5. 다음 값을 가진 새로운 MemoryBreakdownEntry를 반환한다:

새로운 메모리 귀속 정보 생성JavaScript realm realm에 대해 수행하려면:
  1. tokenrealmglobal object메모리 귀속 토큰으로 둔다.

  2. tokencross-origin aggregated flag가 true이면

    1. 다음 내용을 가진 새로운 MemoryAttribution을 반환한다:

  3. scope nameidentifier로 설정 (realmglobal objectinterface).

  4. 다음 값을 가진 새로운 MemoryAttribution을 반환:

3.4. 메모리 귀속 토큰 생성 또는 획득

window 메모리 귀속 토큰 획득origin origin, origin parent origin, origin top-level origin, HTMLElement container element, 그리고 memory attribution token parent token에 대해:
  1. container element가 null이면:

    1. Assert: parent origin은 null이다.

    2. Assert: parent token도 null이다.

    3. Assert: originparent origin과 같다.

    4. 다음 값을 가지는 새로운 메모리 귀속 토큰을 반환:

  2. parent origintop-level origin과 다르면:

    1. parent token을 반환.

  3. container컨테이너 요소 속성 추출의 결과(container element 인자)로 둔다.

  4. origintop-level origin과 같으면:

    1. 다음 값의 새로운 메모리 귀속 토큰을 반환:

  5. 다음 값의 새로운 메모리 귀속 토큰을 반환:

worker 메모리 귀속 토큰 획득WorkerGlobalScope worker global scope, environment settings object outside settings에 대해:
  1. worker global scopeDedicatedWorkerGlobalScope라면, outside settingsglobal object메모리 귀속 토큰을 반환.

  2. Assert: worker global scopeSharedWorkerGlobalScope 또는 ServiceWorkerGlobalScope여야 한다.

  3. 다음 값을 가진 새로운 메모리 귀속 토큰을 반환:

컨테이너 요소 속성 추출HTMLElement container element에 대해:
  1. container elementlocal name에 따라 처리:

    "iframe"

    다음 값을 가진 새로운 MemoryAttributionContainer를 반환:

    • id 값은 container elementid 속성,

    • src 값은 container elementsrc 속성,

    "frame"

    다음 값을 가진 새로운 MemoryAttributionContainer를 반환:

    • id 값은 container elementid 속성,

    • src 값은 container elementsrc 속성,

    "object"

    다음 값을 가진 새로운 MemoryAttributionContainer를 반환:

    • id 값은 container elementid 속성,

    • src 값은 container elementdata 속성,

4. 기존 명세와의 통합

4.1. WindowOrWorkerGlobalScope 확장

WindowOrWorkerGlobalScope에 새로운 내부 필드가 추가됩니다:
memory attribution token

이 환경의 메모리 사용량을 보고하는 데 사용되는 memory attribution token입니다.

4.2. 기존 알고리즘의 확장

run a worker 알고리즘은 6단계에서 새로 생성된 글로벌 오브젝트의 memory attribution token 필드를 설정합니다:

  1. realm execution context를 agent 및 다음 커스터마이징을 사용하여 새로운 JavaScript realm을 생성한 결과로 둔다:

create and initialize a Document object 알고리즘은 새 글로벌 오브젝트의 memory attribution token 필드를 설정합니다:

  1. 그렇지 않은 경우:

    1. token을 빈 memory attribution token으로 둔다.

    2. browsingContext가 top-level browsing context가 아니면:

      1. parentTokenparentEnvironmentglobal objectmemory attribution token으로 둔다.

      2. tokenwindow 메모리 귀속 토큰 획득 결과로 설정 (origin, parentEnvironment의 origin, topLevelOrigin, browsingContext의 container, parentToken 인자).

    3. 그 외에는 tokenwindow 메모리 귀속 토큰 획득 결과로 설정 (origin, null topLevelOrigin, null, null).

    4. window global scoperealm execution context의 Realm 컴포넌트의 global object로 둔다.

    5. window global scopememory attribution tokentoken으로 설정한다.

create a new browsing context 알고리즘은 새 글로벌 오브젝트의 memory attribution token 필드를 설정합니다:

  1. token을 빈 토큰으로 둔다.

  2. embedder가 null이면 tokenwindow 메모리 귀속 토큰 획득 결과로 설정 (origin, null, topLevelOrigin, null, null).

  3. 그 밖의 경우, tokenwindow 메모리 귀속 토큰 획득 결과로 설정하는데, 인자는 origin, embedder관련 settings object의 origin, topLevelOrigin, embedder, embedder관련 글로벌 객체메모리 귀속 토큰을 사용한다.

  4. window global scoperealm execution context의 Realm 컴포넌트의 global object로 둔다.

  5. window global scopememory attribution tokentoken으로 설정한다.

5. 프라이버시 및 보안

5.1. 교차 출처 정보 유출

결과에 나타나는 URL 및 기타 문자열 값은 API를 호출하는 origin이 이미 알고 있는 값임이 보장됩니다.

교차 출처로 노출되는 유일한 정보는 memoryMeasurement.bytesmemoryBreakdownEntry.bytes에 제공된 size 정보입니다. API는 교차 출처 크기 정보 유출을 완화하기 위해 교차 출처 격리 메커니즘에 의존합니다. 구체적으로, API는 현재 주소 공간의 모든 리소스가 자신의 임베더 origin에 임베드 및 접근 가능함을 opt-in 했음을 보장하는 불변식에 의존합니다. API는 별도 주소 공간에 로드된 교차 출처 리소스의 크기를 노출하지 않습니다.

5.2. 핑거프린팅

API의 결과는 웹 페이지 자체가 할당한 객체에만 의존하며, 빈 페이지의 기준 메모리 사용량 등과 같은 무관한 메모리는 포함하지 않습니다. 즉, 동일한 사용자 에이전트 바이너리가 두 다른 장치에서 동일한 웹 페이지에 대해 실행될 때 동일한 결과가 나와야 합니다.

웹 페이지는 아래와 같은 사용자 에이전트 정보를 추론할 수 있습니다:

유사한 정보는 기존 API(navigator.userAgent, navigator.platform)에서도 얻을 수 있습니다. 사용자 에이전트의 비트 수 또한 32비트/64비트 연산의 실행 시간 측정으로 추론할 수 있습니다.

현재 API는 오직 최상위 origin에서만 사용할 수 있습니다. 향후에는 최상위 origin이 Permissions Policy를 사용해 다른 origin에 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();
};