Version: 2021.3
WebGL용 개발
Interaction with browser scripting

WebGL의 메모리

Unity WebGL의 메모리 제약은 실행할 수 있는 콘텐츠의 복잡도를 제한할 수 있습니다.

WebGL 콘텐츠는 브라우저에서 실행됩니다. 브라우저는 애플리케이션이 콘텐츠를 실행하는 데 필요한 메모리 공간에 메모리를 할당합니다. 사용 가능한 메모리 양은 다음에 따라 다릅니다.

  • 사용하는 기기
  • 사용하는 운영체제
  • 사용하는 브라우저, 그리고 32 또는 64 프로세서에서 실행되는지 여부
  • 브라우저의 JavaScript 엔진이 코드를 파싱하는 데 필요한 메모리 양
  • 브라우저가 각 탭에 대해 별도의 프로세스를 사용하는지, 또는 콘텐츠가 다른 모든 열린 탭과 메모리 공간을 공유해야 하는지 여부

브라우저에서 Unity WebGL 콘텐츠에 상당한 양의 메모리를 할당해야 하는 여러 부분이 있습니다.

Unity 힙

Unity는 메모리 힙을 사용하여 모든 Unity 엔진 런타임 오브젝트를 저장합니다. 여기에는 관리되는 오브젝트와 네이티브 오브젝트, 로드된 에셋, 씬 및 셰이더가 포함됩니다. 이는 Unity 플레이어가 다른 플랫폼에서 사용하는 메모리와 같습니다.

Unity 힙은 할당된 메모리의 연속된 블록입니다. Unity는 애플리케이션의 요구 사항에 맞게 힙의 자동 크기 조절을 지원합니다. 힙 크기는 애플리케이션이 실행되면서 확장되며, 최대 2GB까지 확장할 수 있습니다. Unity는 이 메모리 힙을 메모리 오브젝트로 생성합니다. 메모리 오브젝트의 버퍼 프로퍼티는 WebAssembly 코드에서 액세스하는 메모리의 원시 바이트를 보유한 크기 조절이 가능한 ArrayBuffer입니다.

힙 크기를 자동으로 조절하면 브라우저가 주소 공간에 연속적인 메모리 블록을 할당하지 못할 경우 애플리케이션이 중단될 수 있습니다. 이러한 이유로 Unity 힙 크기를 가능한 한 작게 유지하는 것이 중요합니다. 따라서 애플리케이션의 메모리 사용량을 계획할 때 주의를 기울여야 합니다. Unity 힙의 크기를 테스트하려면 프로파일러를 사용하여 메모리 블록의 콘텐츠를 프로파일링할 수 있습니다.

에셋 데이터

Unity WebGL 빌드를 생성하면 Unity는 .data 파일을 생성합니다. 여기에는 애플리케이션이 시작하는 데 필요한 모든 씬과 에셋이 들어 있습니다. Unity WebGL은 실제 파일 시스템에 액세스할 수 없기 때문에 가상 메모리 파일 시스템을 생성하고 브라우저는 여기에서 .data 파일을 언패킹합니다. Emscipten 프레임워크(JavaScript)는 브라우저 메모리 공간에 이 메모리 파일 시스템을 할당합니다. 콘텐츠가 실행되는 동안 브라우저 메모리는 압축되지 않은 데이터를 유지합니다. 다운로드 시간과 메모리 사용량을 모두 낮게 유지하려면 압축되지 않은 데이터를 가능한 한 작게 유지하십시오.

메모리 사용을 줄이기 위해 에셋 데이터를 에셋 번들로 패킹할 수 있습니다. 에셋 번들을 사용하면 에셋 다운로드를 완벽하게 제어할 수 있습니다. 즉 애플리케이션에서 에셋을 다운로드하는 시기와 런타임에서 에셋을 언로드하는 시기를 제어할 수 있습니다. 사용하지 않는 에셋을 언로드하면 추가 메모리가 확보됩니다.

에셋 번들은 Unity 힙에 직접 다운로드되므로 브라우저에서 추가 할당이 일어나지 않습니다.

Data Caching을 활성화하면 사용자 컴퓨터의 콘텐츠에 있는 에셋 데이터를 자동으로 캐싱합니다. 즉 나중에 실행하는 동안 해당 데이터를 다시 다운로드할 필요가 없습니다. Unity WebGL 로더는 IndexedDB API를 사용하여 데이터 캐싱을 구현합니다. 이 옵션을 사용하면 브라우저가 기본적으로 캐싱하기에 너무 큰 파일도 캐싱할 수 있습니다.

데이터 캐싱을 사용하면 브라우저가 사용자 컴퓨터에 애플리케이션 데이터를 저장할 수 있습니다. 브라우저는 종종 캐시에 저장할 수 있는 양과 캐싱할 수 있는 최대 파일 크기를 제한합니다. 이는 애플리케이션이 원활하게 실행되기 충분하지 않을 때가 많습니다. 따라서 Unity WebGL 로더는 IndexedDB API를 사용하여 날짜 캐싱을 구현합니다. Unity는 콘텐츠를 브라우저 캐시에 저장하는 대신, 데이터를 IndexedDB에 저장합니다.

Data Caching 옵션을 활성화하려면 File > Build Settings > Player Settings > Publishing Settings로 이동하십시오.

Large-Allocation HTTP 헤더

서버에서 콘텐츠에 대한 Large-Allocation HTTP 헤더를 방출할 수 있습니다. 이 헤더는 지원되는 브라우저(현재 Mozilla Firefox만 지원됨)에 필요한 메모리에 대해 알립니다. 이 정보를 통해 지원되는 브라우저는 조각나지 않은 메모리 공간을 사용하여 새로운 프로세스를 생성할 수 있습니다. 또한 브라우저는 대용량 할당에 성공하도록 보장하기 위한 추가 하우스키핑 작업을 수행할 수 있습니다. 이렇게 하면 Unity 힙을 할당하려고 할 때 브라우저 메모리가 부족해지는 문제를 해결할 수 있습니다. 이는 32비트 브라우저에서 특히 중요합니다.

가비지 컬렉션 고려 사항

가비지 컬렉션은 사용하지 않는 메모리를 찾아 확보하는 프로세스입니다. 가비지 컬렉터는 사용되지 않은 메모리를 수집하여 Unity 힙 내부에 다시 ​​할당합니다.

Unity 가비지 컬렉션이 작동하는 방식에 대한 개요는 자동 메모리 관리를 참조하십시오. WebGL 가비지 컬렉션은 스택이 비어 있을 때 실행됩니다. 스택은 Unity 힙의 일부이지만, 힙 자체는 아닙니다. 이 작업은 보통 프레임이 끝날 때마다 실행됩니다. 하지만 컬렉터가 스택 점검을 위해 실행 중인 모든 스레드를 일시 중지하는 다른 플랫폼의 프로세스와는 다릅니다. 또한 이 작업은 JavaScript에서는 불가능합니다. Unity 프로파일러를 사용하여 가비지 컬렉션 프로세스를 디버깅할 수 있습니다.

대부분의 다른 플랫폼에서 가비지 컬렉션은 실행 중인 모든 스레드를 일시 중지합니다. 그런 다음 가비지 컬렉터는 해당 스택을 점검하고 로드된 오브젝트 레퍼런스를 등록합니다. 현재 이 작업은 JavaScript에서는 불가능합니다. 이러한 이유로 가비지 컬렉터는 스택이 비어 있는 경우에만 WebGL에서 실행됩니다. 이 작업은 프레임이 끝날 때마다 한 번씩 발생합니다.

이로 인해 다음 코드는 WebGL에서 실행되지 않습니다. 이는 컬렉터가 루프 반복 사이에 가비지 컬렉터를 실행할 기회를 얻지 못하기 때문입니다. 즉 가비지 컬렉터는 중간 문자열 오브젝트가 사용하는 메모리를 확보할 수 없으며, Unity 힙에서 메모리가 부족할 가능성이 있습니다.

string hugeString = "";
 
for (int i = 0; i < 100000; i++)
 
{
 
  hugeString += "foo";
 
}

2020.1에서 도입된 WebGL 로더 업데이트됨

WebGL용 개발
Interaction with browser scripting