WebGL 성능 고려사항
WebGL: 브라우저 스크립트와 상호작용

WebGL의 메모리

Unity WebGL에서 메모리는 실행가능한 콘텐츠의 복잡성을 제한하는 억제 요소가 될 수 있습니다. 이 페이지에서는 WebGL의 메모리 사용 방법에 대해 설명합니다.

WebGL 콘텐츠는 브라우저 안에서 실행되므로 브라우저에서 메모리를 브라우저의 메모리 공간 안에 할당해야 합니다. 사용 가능한 메모리의 양은 사용하는 브라우저, OS 및 기기에 따라 매우 다를 수 있습니다. 결정 요인은 브라우저가 32비트 프로세스인지 64비트 프로세스인지, 브라우저가 각 탭마다 별도의 프로세스를 사용하는지 아니면 콘텐츠가 모든 열린 탭과 함께 메모리 공간을 공유하는지, 그리고 브라우저의 JavaScript 엔진이 코드를 파싱하는 데 메모리가 얼마나 필요한지 등입니다.

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

Unity 힙

Unity에서 모든 상태와 관리 및 네이티브 오브젝트와 현재 로드된 에셋 및 씬을 저장하는 데 사용하는 메모리입니다. 다른 플랫폼에서 Unity 플레이어에 사용되는 메모리와 유사합니다. Unity WebGL 플레이어 설정에서 크기를 설정할 수 있습니다. Unity 프로파일러를 사용하여 이 메모리의 콘텐츠를 프로파일링하고 샘플링할 수 있습니다. 이 메모리는 JavaScript 코드에서 바이트의 TypedArray로 생성되며, 브라우저에서 이 크기의 연속 메모리 블록을 할당할 수 있어야 합니다. 이 공간은 (메모리가 조각난 경우에도 브라우저에서 할당할 수 있도록) 최대한 작으면서도 콘텐츠의 모든 씬을 플레이하는 데 필요한 모든 데이터를 저장할 수 있을 만큼 커야 합니다.

에셋 데이터

Unity WebGL 빌드를 만들면 Unity가 콘텐츠에 필요한 모든 씬과 에셋이 포함된 .data 파일을 작성합니다. WebGL에는 실제 파일 시스템이 없으므로 이 파일은 콘텐츠를 시작할 수 있기 전에 다운로드되고 압축을 푼 데이터는 콘텐츠가 실행되는 동안 브라우저 메모리의 연속적인 블록에 계속 보관됩니다. 따라서 다운로드 시간과 메모리 사용량을 모두 낮게 유지하려면 이 데이터를 최대한 작게 유지하려고 해야 합니다. 에셋의 빌드 크기를 최적화하는 방법에 대한 내용은 파일 크기 축소에 대한 문서 페이지를 참조하십시오.

에셋 데이터를 에셋 번들에 패킹하여 로드 시간과 에셋에 사용되는 메모리 양을 줄일 수도 있습니다. 그러면 에셋을 다운로드해야 하는 시기를 다음대로 관리하고 더 이상 필요하지 않은 에셋을 언로드할 수 있으므로 에셋에 사용되는 메모리를 사용 가능한 메모리로 전환할 수 있습니다. 에셋 번들은 Unity 힙에 직접 로드되므로 (브라우저의 IndexDB를 통해 지원되는 메모리 맵 버추얼 파일 시스템을 사용하는 WWW.LoadFromCacheOrDownload 를 사용하여 에셋 번들 캐싱을 사용하지 않는 한) 브라우저에서 메모리를 추가로 할당하지 않습니다.

Dealing with memory issues

When you see an error related to memory in a Unity WebGL build, it is important to understand whether it is the browser which is failing to allocate memory or if the Unity WebGL runtime is failing to allocate a free block of memory within the pre-allocated block of the Unity heap. If the browser is failing to allocate memory, then it may help to try to reduce the size used by one or more of the memory areas above (for instance by reducing the size of the Unity heap). On the other hand, if the Unity runtime is failing to allocate a block inside the Unity heap, you may want to increase the size of that instead.

Unity will try to interpret error messages to tell which of the two it is (and provide suggestions on what to do). Since different browsers may report different messages, that is not always easy, however, and we may not be interpreting all of them. When you see a generic “Out of memory” error from the browser, it is likely to be an issue of the browser running out of memory (where you might want to use a smaller Unity heap). Also, you may sometimes see browsers simply crashing when loading Unity content without showing a human-parseable error message. This can have many reasons, but is frequently caused by JavaScript engines requiring too much memory to parse and optimize the generated code.

Large-Allocation Http Header

Your server can emit the Large-Allocation http header for your content. This tells supported browsers (currently only Firefox) about your memory needs, allowing them to spawn a new process with an unfragmented memory space, or to perform other housekeeping to make sure that the large allocation succeeds. This can solve issues where the browser runs out of memory when trying to allocate the Unity heap, especially on 32-bit browsers.

Garbage Collection considerations

When you allocate managed objects in Unity, they will need to be garbage collected when they are no longer used. See our documentation on automatic memory management for more information. In WebGL, this is the same. Managed, garbage collected memory is allocated inside the Unity heap.

One distinction in WebGL, however, concerns the points in time when garbage collection (GC) can take place. To perform garbage collection, the GC would normally need to pause all running threads and inspect their stacks and registers for loaded object references. This is not currently possible in JavaScript. For this reason, the GC will only run in WebGL in situations where the stack is known to be empty (which is currently once after every frame). This is not a problem for most content which deals with managed memory conservatively and has relatively few GC allocations within each frame (you can debug this using the Unity profiler).

However, the following code would fail running on WebGL, becuase it would not get a chance to run the GC between iterations of the loop, to free up memory used by all the intermediate string objects - which would eventually cause it to run out of memory in the Unity heap.

string hugeString = "";

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

Further reading


2018–08–23 편집 리뷰 없이 페이지 수정됨

WebGL 성능 고려사항
WebGL: 브라우저 스크립트와 상호작용