Unity 검색

Inspecting memory with the new Memory Profiler package | Hero image
Inspecting memory with the new Memory Profiler package | Hero image
공유

Is this article helpful for you?

Thank you for your feedback!

이 블로그에서는 게임의 메모리 관련 문제를 진단하고 검사하는 데 사용할 수 있는 새로운 Memory Profiler 패키지의 5가지 주요 워크플로를 다룹니다. 워크플로는 다음과 같습니다.

  • 애플리케이션의 메모리 부담률 모니터링
  • Unity Objects의 분포 보기
  • 잘못 설정된 에셋 감지
  • 의도하지 않은 중복 오브젝트 찾기
  • 메모리 캡처를 비교하여 최적화 검증

Memory Profiler에 대한 소개는 최신 블로그 Memory Profiler 1.0.0에 관한 모든 것을 참조하세요.

애플리케이션의 메모리 부담률 모니터링

첫 번째 워크플로에서는 애플리케이션이 기기의 메모리 리소스를 얼마나 요구하는지 모니터링합니다. 이 프로세스는 애플리케이션이 너무 많은 메모리를 사용하여 성능 문제가 발생하거나 운영 체제에 의해 추방 또는 종료될 위험이 있는지 확인하는 데 중요하게 사용됩니다.

먼저 타겟 기기에서 실행되는 예제 게임의 빌드가 있습니다. 당연히 실제 하드웨어에서 실행되는 게임의 메모리 캡처를 통해 기기의 사용 가능한 메모리 리소스를 어떻게 사용하는지 확인해야 합니다. 또한 메모리는 Unity 에디터에서 Unity 런타임과 동일한 방식으로 작동하지 않으므로, 플레이 모드에서 에디터의 메모리 캡처를 수행하면 게임 메모리가 기기에서 어떻게 나타나는지 잘 확인할 수 없습니다. 참고로 에디터의 메모리 캡처는 커스텀 에디터 창 같은 에디터용 툴을 개발할 때 적합합니다.

게임에서 메모리 사용량을 분석하려는 단계로 이동한 후 Memory Profiler의 드롭다운을 사용하여 Memory Profiler를 기기에 연결합니다. 그런 다음 아래와 같이 메모리 캡처를 수행할 수 있습니다.

Connecting to a build of our game and taking a memory capture.

이 캡처를 열면 Memory Profiler가 Summary 페이지 상단에 애플리케이션의 메모리 사용량을 ‘Memory Usage On Device’로 표시합니다.

Our application’s memory footprint is displayed by the Memory Usage On Device indicator.
여러분의 애플리케이션이 사용하는 메모리 용량이 Memory Usage On Device 표시기에 나타납니다.

이 경우 사용 가능한 3.50GB 중에서 해당 애플리케이션의 메모리 사용량은 492.5MB입니다. 다음으로 캡처 시점에서 RAM 같은 기기의 물리 메모리가 합리적인 비율로 사용되고 있는지 판단을 내려야 합니다. 기기의 물리 메모리는 실행 중인 모든 프로세스에서 공유된다는 점을 기억하세요.

‘메모리 사용량’의 정확한 의미

시각적 표시기를 통해 총 상주 메모리가 표시되는 것을 확인할 수 있습니다. 총 상주 메모리는 RAM 같은 기기의 물리 메모리 하드웨어에 상주하는 애플리케이션 메모리의 양을 나타냅니다. 이는 두 가지 이유로 타겟 기기에서 애플리케이션의 현재 메모리 사용량이 얼마나 많은지를 보여 주는 가장 명확한 지표입니다. 첫째, 애플리케이션의 총 상주 메모리 사용량이 증가함에 따라 운영 체제가 기기의 물리 메모리 내외로 가상 메모리를 페이징해야 하는 페이지 오류가 빈번하게 발생할 가능성이 높아지기 때문입니다. 페이지 오류가 자주 발생하면 애플리케이션의 성능이 크게 저하됩니다. 둘째, 다수의 운영 체제에서 애플리케이션의 상주 메모리 사용량을 통해 애플리케이션의 현재 메모리 사용량을 결정하기 때문입니다. 애플리케이션의 메모리 사용량이 너무 커지면 운영 체제에서 애플리케이션을 추방 및 종료하여 플레이어에게 크래시가 발생합니다.

따라서 Memory Profiler의 Memory Usage On Device 시각적 표시기를 사용하여 캡처 시점의 메모리 과다 사용으로 애플리케이션이 성능 문제를 일으키거나 운영 체제에서 종료될 위험이 있는지 추론할 수 있습니다.

이와 대비되는 기능으로 커밋된 메모리라고도 하는 할당된 메모리가 있습니다. Memory Usage On Device 아래에 다양한 그래픽스로 표시되며, 현재 Unity Objects 같은 다른 모든 뷰에서 표시되는 기본 옵션입니다. 할당된 메모리는 물리 메모리에 상주했는지에 관계없이 애플리케이션이 현재 할당한 모든 메모리를 나타내므로 애플리케이션의 메모리 뷰와 더 밀접하게 일치합니다. 따라서 애플리케이션의 현재 할당된 모든 메모리를 탐색하는 데 유용할 수 있습니다. 한편 상주 메모리 사용량은 시점별로 애플리케이션이 하드웨어에 가하는 메모리 부담률을 파악하는 데 중요합니다.

Unity Objects의 분포 보기

Memory Profiler의 Unity Objects 탭은 애플리케이션의 텍스처, 셰이더, 메시, 머티리얼 같은 Unity 오브젝트의 관점에서 애플리케이션 메모리에 대한 개요를 제공합니다. Unity Objects는 Memory Profiler에서 탐색을 시작하기 좋은 위치입니다. 대부분의 Unity 사용자가 Unity 에디터에서 직접 Unity 오브젝트를 사용하여 본질적으로 친숙한 개념이기 때문입니다. 애플리케이션 메모리를 쉽게 파악할 수 있는 진입점이 될 뿐만 아니라 Unity 관련 컨텍스트를 제공하여 다양한 잠재적 문제를 진단하고 해결하는 데 도움이 되는 탭입니다.

The Unity Objects view.
Unity Objects 뷰

Unity Objects 뷰를 보려면 위에 표시된 대로 메모리 캡처를 연 다음 Memory Profiler 상단에서 Unity Objects 탭을 선택합니다.

Unity Objects 뷰를 통해 애플리케이션의 Unity 오브젝트 유형 분포를 빠르게 파악할 수 있다는 것을 실감하실 겁니다. 이를 통해 캡처 시점에 어떤 유형이 가장 많은 메모리를 사용 중이었는지 개괄적으로 파악하고, 특정 씬이 AudioClip 오브젝트를 많이 사용할 것으로 예상되는지 등을 추론할 수 있습니다. 아래와 같이 각 유형을 확장하면 현재 할당된 모든 Unity 오브젝트를 개별적으로 확인할 수도 있습니다.

We can see every mesh object currently allocated by our application by expanding the Mesh type.
Mesh 유형을 확장하여 현재 애플리케이션이 할당한 모든 메시 오브젝트를 볼 수 있습니다.

Unity 오브젝트는 애플리케이션의 총 할당 메모리에서 일부를 차지한다는 점을 기억해야 합니다. 아래 강조 표시된 테이블 상단의 표시기에서 정확한 양을 확인할 수 있습니다.

The indicator above the table shows us the proportion of our total allocated memory that we are seeing in the table.
테이블 상단의 표시기는 테이블에 표시된 총 할당 메모리의 비율을 보여 줍니다.

이 경우 총 할당 메모리 크기인 ‘Total Memory In Snapshot’이 4.64GB고 Unity 오브젝트가 그중 2.37GB를 차지합니다. 또한 검색 기능을 사용하는 등 테이블을 필터링하면 이 표시줄이 업데이트되어 검색 결과가 반영됩니다. 즉 현재 테이블에 나타난 모든 메모리의 크기가 표시됩니다. 이를 통해 전체 캡처 대비 검사 중인 메모리의 양을 정확히 파악하고 어디를 최적화해야 하는지 알 수 있습니다.

The indicator above the table updates as we filter to reflect the size of the memory currently shown in the table, as a proportion of the total allocated memory.
필터를 적용하면 테이블 상단의 표시기가 업데이트되어 총 할당 메모리 대비 현재 테이블에 표시된 메모리의 크기가 반영됩니다.

Memory Profiler 1.0 버전에서는 할당된 메모리가 Unity Objects 테이블에 표시됩니다. 다시 말해 애플리케이션에서 활성화된 모든 Unity 오브젝트가 표시됩니다. 향후 릴리스에서 이 뷰에 상주 메모리를 추가로 표시할 방법을 모색하고 있습니다. 그러면 현재 물리 메모리에 상주하는 Unity 오브젝트를 정확히 확인할 수 있으므로, 애플리케이션의 현재 메모리 사용량에 직접적으로 영향을 주는 것이 무엇인지 정확히 파악할 수 있습니다.

All Of Memory 탭을 사용하여 캡처 시 애플리케이션 메모리의 나머지 부분을 검사할 수 있습니다. 여기에는 다양한 Unity 보조 시스템, 관리 전용(C#) 메모리, DLL 및 실행 파일 같은 Unity 오브젝트 외의 메모리가 포함됩니다.

잘못 설정된 에셋 감지

Unity Objects 뷰는 다양한 잠재적 문제를 진단하는 데 도움이 될 수 있습니다. 잘못 설정되어 필요한 것보다 더 많은 메모리를 사용하는 에셋을 감지하는 것이 그 예입니다.

아래 캡처에서 현재 사용 중인 Unity 오브젝트의 상당 부분이 텍스처임을 알 수 있습니다. 이 캡처는 고해상도 렌더 파이프라인을 활용하고 시각 효과를 많이 사용하여 그래픽 정확도가 높은 프로젝트에서 가져온 것입니다. 이 컨텍스트를 고려하면 텍스처를 많이 사용할 것으로 예상할 수 있고 실제로도 그렇습니다.

The amount of memory associated with Unity Objects in this capture is dominated by RenderTexture and Texture2D types.
이 캡처에서 Unity 오브젝트와 관련된 메모리 양은 RenderTexture 및 Texture2D 유형이 가장 큽니다.

그러나 두 번째로 큰 카테고리인 Texture2D를 확장하면 두 개의 텍스처가 다른 텍스처보다 훨씬 더 크게 나타나는 것을 알 수 있습니다. 그 두 개의 텍스처가 HoloTable_Normal 또는 HoloTable_Mask 같은 비교군 텍스처보다 더 크다는 것은 놀라운 사실이었습니다. 저희들이 생각하기에 서로 크기가 비슷할 것으로 예상했기 때문입니다.

Two textures in our capture appear to be double the size of comparable textures.
캡처에 표시된 두 개의 텍스처가 비교군 텍스처 크기의 두 배로 보입니다.

따라서 테이블에서 해당 텍스처 중 하나를 선택하여 자세히 알아보고 원인을 조사하기 시작합니다. Details 뷰에서 설명을 찾을 수 있습니다. 해당 텍스처는 ‘Read/Write Enabled’가 활성화되어 쓰기 가능 상태입니다.

The Details view displays additional information about the selected object, and reveals that our texture is “read/write enabled.”
Details 뷰에 선택한 오브젝트의 추가 정보가 표시된 덕분에 해당 텍스처가 ‘읽기/쓰기 활성화’ 상태임을 확인할 수 있습니다.

다수의 사용자 프로젝트에서 볼 수 있는 일반적인 문제입니다. 텍스처 임포트 설정에서 ‘읽기/쓰기’ 설정을 선택하여 텍스처를 불필요하게 쓰기 가능으로 설정하는 실수를 저지른 것입니다. 텍스처에서 이 플래그가 활성화되면 메모리 크기가 두 배가 됩니다. CPU에서 액세스할 수 있도록 텍스처 데이터의 두 번째 복사본이 필요하기 때문입니다. 텍스처의 총 크기가 예상보다 두 배 크거나 유사 텍스처의 크기보다 두 배 큰 것이 이를 나타내는 신호입니다.

두 텍스처에서 ‘읽기/쓰기’ 플래그를 비활성화하고 두 번째 캡처를 수행하면 두 텍스처의 크기가 절반으로 줄어드는 것을 볼 수 있습니다.

The offending two textures in our capture are now the same size as comparable textures after the change.
캡처에서 문제가 됐던 두 텍스처는 이제 변경 후 비교군 텍스처와 크기가 동일해졌습니다.

이 예와 같이 Unity 오브젝트가 그래픽스 메모리를 할당한 경우를 더 쉽게 찾을 수 있도록 향후 릴리스에서 Unity Objects 테이블에 그래픽스 GPU 메모리에 대한 열을 추가하는 방법을 모색하고 있습니다.

의도하지 않은 중복 오브젝트 찾기

Unity 프로젝트에서 흔히 볼 수 있는 실수는 의도치 않게 중복 Unity 오브젝트를 생성하는 것입니다. 예를 들어 MeshRenderer의 머티리얼 프로퍼티에 액세스하여 실수로 중복된 머티리얼을 생성하기 매우 쉽습니다. 특정 MeshRenderer의 모든 인스턴스에서 이 작업이 수행되는 등 해당 사례가 빠르게 늘어날 뿐만 아니라, 이렇게 동적으로 생성된 머티리얼은 반드시 명시적으로 파괴해야 합니다.

이런 유형의 문제를 찾는 데 도움이 되도록 Unity Objects 테이블에서는 중복될 수 있는 Unity 오브젝트만 표시하는 빠른 필터를 제공합니다. 이 뷰는 이름과 크기가 모두 동일한 인스턴스가 여러 개 있는 Unity 오브젝트만 표시하도록 테이블을 필터링합니다. 잠재적 중복이 다수 예상되지만 걱정할 필요는 없다는 것이 매우 중요한 지점이죠. 예를 들어 프리팹의 여러 인스턴스에 동일한 이름과 크기의 트랜스폼 컴포넌트가 있을 수 있으며 해당 컴포넌트는 중복될 것으로 예상됩니다. 목표는 의도치 않은 중복 항목을 발견하는 것뿐입니다. 이 워크플로에서 다음 예시를 통해 설명하겠습니다.

아래 캡처는 2개의 Door 프리팹 인스턴스가 있는 간단한 씬에서 받은 것이며, Unity Objects 테이블 아래에 있는 Show Potential Duplicates Only 필터가 활성화되었습니다. 그 결과 이름과 크기가 같은 인스턴스가 여러 개 있는 Unity 오브젝트만 표시되도록 테이블이 필터링되었습니다.

The “Show Potential Duplicates Only” quick filter shows us only Unity Objects that have multiple instances with the same name and size.
‘Show Potential Duplicates Only’ 빠른 필터는 이름과 크기가 같은 인스턴스가 여러 개 있는 Unity 오브젝트만 표시합니다.

이 씬에는 2개의 Door 프리팹 인스턴스가 있기 때문에 당연히 MeshRenderer, Transform, GameObject 등 모든 관련 오브젝트의 인스턴스도 2개씩 있습니다. 그러나 위의 캡처에는 ‘Door’ 머티리얼의 인스턴스도 2개 있습니다. Door 인스턴스는 씬에서 동일하게 보이기 때문에 머티리얼을 공유할 것으로 예상됩니다. 이것이 바로 의도치 않은 중복이며, 이 예에서는 프리팹에서 MeshRenderer의 머티리얼 프로퍼티에 액세스한 것이 원인이 되어 중복이 발생했습니다. 이 프로퍼티 액세스를 제거하고 두 번째 캡처를 수행하면 Unity Objects 테이블에 더 이상 중복 머티리얼이 표시되지 않습니다.

The unintentional duplicate material is no longer present in the Unity Objects table.
더 이상 Unity Objects 테이블에 의도하지 않은 중복 머티리얼이 표시되지 않습니다.

이 필터는 단순히 이름과 크기가 같은 인스턴스가 여러 개 있는 Unity 오브젝트를 모두 표시한다는 점을 기억하세요. 잠재적 중복이 예상된 것인지, 아니면 의도하지 않은 것이며 조사가 필요한지 판단하려면 프로젝트에 대한 지식이 있어야 합니다. 테이블에 표시되는 애플리케이션의 할당된 메모리 비율을 시각적으로 표시하는 상단의 Total Memory In Table 표시줄에 주의를 기울이는 것이 좋습니다. 최적화 작업을 집중할 지점을 파악하는 시야를 갖추는 데 도움이 되는 기능입니다.

메모리 캡처를 비교하여 최적화 검증

Memory Profiler는 두 개의 메모리 캡처를 비교하는 기능도 제공합니다. 이 기능을 사용하면 발견한 문제를 해결하기 위해 프로젝트를 변경하고, 변경 사항이 적용되어 원하는 결과를 실제로 얻었는지 등의 상황을 테스트할 수 있습니다. 가설이 올바르고 변경 사항을 통해 실제 하드웨어에서 원하는 결과를 얻었는지 항상 테스트하는 것이 중요합니다. 이제 이 비교 워크플로의 예를 살펴보겠습니다.

아래는 첫 번째 수준에서 받은 모바일 게임의 캡처입니다. Unity Objects의 가장 큰 카테고리는 Texture2D임을 알 수 있습니다. 이 카테고리를 열어 가장 큰 텍스처가 무엇인지 확인해 보면 게임의 나머지 텍스처(각각 메가바이트 단위)에 비해 상당히 큰 UI 텍스처가 몇 개 있다는 것을 알 수 있습니다. 이때 이 텍스처가 다른 텍스처보다 훨씬 큰 이유와 그 필요성에 대한 의구심이 생깁니다. 그 이유를 알아보려면 먼저 Memory Profiler에서 텍스처를 선택하고 프로젝트(Project) 창에서 소스 텍스처 에셋을 강조 표시하는 ‘Select In Editor’ 버튼을 사용하여 프로젝트에서 소스 텍스처 에셋을 찾습니다.

Use the “Select In Editor” button in the Details view to select the source asset in the Project window.
Details 뷰에서 ‘Select In Editor’ 버튼을 사용하여 프로젝트 창에서 소스 에셋을 선택합니다.

인스펙터(Inspector) 창을 사용하면 2의 거듭제곱이 아님을 뜻하는 ‘NPOT’ 텍스트에서 볼 수 있듯, 문제가 되는 대형 UI 텍스처의 크기가 2의 거듭제곱이 아니기 때문에 모두 압축되지 않은 것을 볼 수 있습니다.

The six large textures are all not being compressed due to their dimensions not being a power-of-two.
크기가 2의 거듭제곱이 아니므로 6개의 대형 텍스처가 모두 압축되지 않습니다.

해당 텍스처 크기가 지나치게 큰 이유를 알아냈습니다. 이제 프로젝트에 대한 지식을 사용하여 메모리 사용량을 줄일 수 있습니다. 그중 3개의 텍스처(도움말 컨트롤)는 항상 UI에 함께 표시되며 다른 3개의 텍스처(크리처)도 마찬가지입니다. 따라서 3개 텍스처로 이뤄진 각 세트에 2개의 스프라이트 아틀라스를 생성하면 메모리의 텍스처 수를 늘리지 않고도 압축할 수 있으므로, 할당된 메모리 사용량이 줄어들 것이라는 가설을 높은 정확도로 세울 수 있습니다.

Creating two sprite atlases for each set of three textures.
3개의 텍스처로 이뤄진 각 세트에 2개의 스프라이트 아틀라스를 생성합니다.

두 스냅샷을 비교하려면 먼저 첫 번째 스냅샷을 엽니다. 이 스냅샷이 비교에 사용될 ‘기준’입니다. 열린 스냅샷 위에 있는 ‘Compare Snapshots’ 탭을 선택하고 두 번째 스냅샷을 선택합니다. 이제 Memory Profiler에 두 스냅샷을 비교하는 요약이 아래와 같이 표시됩니다.

The Memory Profiler’s Summary page presents a summary of the differences between two memory captures when two snapshots are being compared.
Memory Profiler의 Summary 페이지는 두 스냅샷을 비교할 때 두 메모리 캡처 간의 차이점에 대한 요약이 표시됩니다.

변경 사항의 효과를 확인하고 실제로 Texture2D 카테고리에서 애플리케이션의 할당된 메모리 크기가 줄었는지 확인하려면 Unity Objects 탭을 선택합니다. 여기에서는 변경된 Unity 오브젝트 유형과 캡처 간에 변경된 정도를 보여 주는 비교 테이블이 제공됩니다(아래 참조).

The Unity Object types that changed between the two memory captures.
두 메모리 캡처 간에 변경된 Unity 오브젝트 유형

Texture2D 유형이 전체적으로 크기가 3.6MB 줄었고 이전보다 텍스처가 4개 줄었습니다. 이 카테고리를 확장하면 압축되지 않은 개별 스프라이트 텍스처가 제거되고 2개의 스프라이트 아틀라스 텍스처가 추가되어 최종적으로 텍스처 크기는 3.6MB, Texture2D 오브젝트 수는 4개 줄었음을 확인할 수 있습니다.

The Texture2D Unity Objects that have changed between the two captures.
두 캡처 간에 변경된 Texture2D Unity 오브젝트

비교 기능을 사용하여 가설이 옳았다는 것을 확인했고 할당된 메모리에서 해당 텍스처의 크기를 줄였습니다.

결론

이 블로그를 보면 새로운 Memory Profiler 패키지의 다섯 가지 주요 워크플로를 더 명확히 이해할 수 있습니다. 이 워크플로는 게임의 메모리 관련 문제를 진단하고 검사하기 위해 설계되었습니다. Unity 2022.2에서 릴리스된 Memory Profiler 패키지가 게임의 메모리 사용량을 더 효율적으로 모니터링하고, 검사하고, 이해하는 데 도움이 되기를 바랍니다. 언제든지 유니티 포럼 페이지를 통해 성능 프로파일링 툴을 개선할 수 있는 방법에 대한 피드백을 공유해 주세요. 또는 유니티 로드맵 페이지에서 작업 중인 몇 가지 기능을 확인하고 제안 사항을 공유할 수도 있습니다.

이 주제에 대한 자세한 내용에 관심이 있다면 몇 주 안에 게시될 다른 블로그를 참조하세요. 애플리케이션의 메모리 사용량이 계산되는 방법과 상주 메모리 및 할당된 메모리와 같은 주제를 자세히 다룰 예정입니다.

2023년 2월 28일 엔진 & 플랫폼 | 15 분 소요

Is this article helpful for you?

Thank you for your feedback!

관련 게시물