효율적으로 메모리 문제를 감지하고 성능을 최적화하는 데 있어 핵심은 바로 Memory Profiler에 표시되는 정보와 해당 정보의 정밀도입니다. 유니티는 이 분야에 상당한 노력을 기울이고 있습니다. 최근에 포스팅된 두 개의 블로그에서 저희 팀은 Memory Profiler 1.0.0을 소개하고 게임의 메모리 관련 문제를 진단, 검사하기 위한 5가지 주요 워크플로를 살펴보았습니다.
조만간 Memory Profiler 1.1을 출시할 예정이며(실험 버전은 지금 사용 가능) 이 버전에는 메모리가 어떻게 작동하는지, 그리고 애플리케이션 메모리 사용량이 어떻게 계산되는지에 대한 레이블과 설명이 업데이트되어 제공됩니다.
개발자들과 대화해 보면 이들은 늘 메모리 사용량에 신경을 쓰고 있습니다. 따라서 이 포스팅에서는 자주 묻는 질문에 답변하면서 다음 세 가지 주제를 중점적으로 다루려 합니다.
Unity의 메모리 할당을 자세히 살펴보겠습니다. 엔진에서 메모리를 할당할 때 엔진은 요청된 할당에 맞는 가상 주소 공간에서 먼저 여러 메모리 페이지를 예약합니다. 이때 페이지는 메모리 관리의 최소 단위입니다. 가상 주소 공간과 물리적 스토리지는 각각 여러 페이지로 구성되며, 페이지 크기는 사용되는 플랫폼에 따라 달라집니다. 예를 들어 x86 컴퓨터에서는 페이지 크기가 4KB입니다.
페이지를 충분히 예약하고 나면 엔진은 물리적 스토리지를 메모리에 '커밋'하도록 OS(운영체제)에 요청합니다. 이것이 바로 할당된 메모리를 흔히 '커밋됨'이라고 표현하는 이유입니다. 다음으로 OS는 이제 페이지에 물리적 스토리지가 할당되었으며 액세스도 가능하다고 등록합니다. 그러면 애플리케이션에서 보고한 '총 커밋된 메모리'가 늘어납니다. 하지만 애플리케이션의 물리적 메모리 사용량은 그대로입니다.
사용량이 그대로인 이유는 영역을 물리적 스토리지에 커밋했어도 대부분의 OS에는 지연이 발생하며 절약하는 성질이 있어 특정 물리적 스토리지 위치가 할당되지 않았기 때문입니다. 예를 들어 커밋된 영역에 무언가를 쓰려 한다고 가정해 보겠습니다. 영역 아래에 아직 물리적 메모리가 없기 때문에 영역에 액세스하면 페이지 오류가 발생합니다. 이에 대응하여 OS의 메모리 관리자는 작업을 완료할 수 있도록 이전에 사용 가능했던 물리적 페이지를 할당합니다. 모든 작업이 페이지 크기 세분화를 통해 수행되기 때문에 영역에서 액세스되지 않는 페이지는 빈 상태로 유지되고 물리적 메모리가 할당되지 않습니다. 이와 유사하게 애플리케이션의 상주 메모리 크기는 작업을 완료하기 위해 할당된 모든 물리적 메모리 페이지의 총 크기만큼 늘어납니다.
한동안 페이지가 액세스되지 않거나 물리적 메모리에 대한 수요가 높은 경우, OS는 플랫폼에서 지원되는 사항에 따라 할당된 영역의 페이지 일부를 압축 메모리나 페이지 스왑 파일로 오프로드할 수 있습니다.
이 경우 애플리케이션에서 보고한 할당된 메모리는 그대로 유지되지만 상주 메모리 크기는 줄어듭니다.
이미 눈치채셨을 수도 있지만, 할당된 메모리만 확인하면 어떤 할당에서 물리적 메모리를 소비하는지 잘못 판단하여 문제가 없는 항목을 최적화하는 오류가 발생할 수 있습니다. 그러면 소중한 시간을 낭비하게 될 뿐만 아니라 애플리케이션 성능과 안정성을 개선하기도 어려워집니다.
전반적으로 애플리케이션 메모리 상태는 아래 다이어그램으로 설명할 수 있습니다.
요약하자면 메모리 사용량이 계산되는 방식은 다음과 같습니다.
물리적 메모리 사용량 = 애플리케이션 상주 메모리 + 애플리케이션 압축 메모리 페이지
Memory Profiler 1.1의 Summary, Unity Objects, All Of Memory 뷰에서는 할당된 메모리 크기뿐 아니라 상주 메모리에 대한 정보도 제공됩니다. 하지만 이 정보는 Memory Profiler 스냅샷이 Unity 2022.2 이상 버전으로 만들어졌을 때만 표시됩니다. 이전 버전의 스냅샷에서도 업데이트된 UI와 요약 정보 뷰는 표시되지만, 상주 메모리에 대한 정보는 표시되지 않습니다.
Summary 뷰에서는 일반 개요와 함께 필수 지표인 Total Resident on Device가 제공됩니다. 메모리가 제한된 플랫폼에서 애플리케이션을 실행해야 하는 경우 Total Resident on Device는 메모리 부족 경고와 메모리 고갈로 인한 강제 종료를 검토하는 데 아주 중요합니다. 일반적으로 기기에서 사용 가능한 총 물리적 메모리의 70%를 초과해서는 안 됩니다.
상세한 분석을 보려면 Unity Objects와 All of Memory 뷰를 사용하면 됩니다. 사용 중인 총 물리적 메모리를 가장 많이 차지하는 오브젝트를 확인하려면 드롭다운 메뉴에서 Resident on Device 또는 Allocated and Resident on Device를 선택하고 Resident size를 기준으로 정렬합니다.
상주 메모리 사용량을 분석할 때는 다음 사항을 기억하세요.
오브젝트에서 사용하는 모든 Unity 비관리형 할당이 포함된 Native 메모리를 분석하는 경우 Reserved 메모리 항목이 표시됩니다. 이 메모리는 Unity 메모리 관리자에 의해 할당되었으나 캡처 중에 Unity 오브젝트에서 사용하지 않는 메모리입니다. 다음은 몇 가지 유용한 정보입니다.
일부 플랫폼에서는 크기가 큰 경우 플랫폼별 그룹이 추가로 표시됩니다. Android의 Android Runtime을 예로 들 수 있으며, 다음은 Android Runtime에 대한 몇 가지 참고 사항입니다.
이 포스팅에서는 Memory Profiler 1.1(실험 버전 지금 사용 가능)에서 도입될 기능을 간략히 소개하고 메모리 사용량에 관한 여러 가지 주제를 살펴보았습니다. 이 내용이 여러분께 도움이 되었길 바랍니다.
저희 팀의 목표는 Memory Profiler를 계속 개선하여 더 정밀하고 구체적인 정보를 제공하는 동시에, 잠재적인 메모리 고갈 상황과 더불어 메모리 고갈에 얼마나 근접하였는지를 사용자에게 알리고 경고하는 것입니다. 제품 로드맵에서 진행 상황을 알아보고 의견을 들려 주세요.
포럼에 들러 피드백을 공유해 주세요. 연재 중인 Tech from the Trenches 시리즈에서 다른 유니티 개발자들의 새로운 기술 블로그도 확인할 수 있습니다.
Is this article helpful for you?
Thank you for your feedback!