메모리 인사이트

메모리 인사이트 개요

Choose your operating system:

Windows

macOS

Linux

언리얼 엔진 5(UE5) 에서는 메모리 인사이트(Memory Insights) 기능에 메모리 트래킹 개선과 프로파일링 지원을 추가하여 언리얼 인사이트(Unreal Insights) 의 기능이 확장되었습니다. 이제 개발자는 메모리 블록별로 연결된 로우 레벨 메모리(Low Level Memory, LLM) 태그 및 콜스택 등 메모리 할당 및 할당 해제와 관련된 상세 정보를 언제든지 볼 수 있습니다. 메모리 인사이트에는 특정 시점의 라이브 할당을 파악하고, 메모리 사용량 증감을 인식하고, 단기 할당과 장기 할당을 구분하고, 메모리 누수를 찾을 수 있는 쿼리 시스템이 있습니다.

세션 레코딩

메모리 인사이트(Memory Insights)를 사용하여 메모리 채널의 트레이스를 기록하려면 다음 단계를 따릅니다.

언리얼 인사이트 실행 또는 빌드

**시작(Start)** > **명령 프롬프트(Command Prompt)** 로 이동하여 다음을 입력합니다.

    Engine\Binaries\Win64\UnrealInsights.exe

또는 Engine\Binaries\Win64 폴더로 이동한 다음 UnrealInsights.exe 파일을 더블클릭하여 실행해도 됩니다.

binaries-exe-in-unreal

메모리 트레이싱(Memory Tracing)으로 게임 프로젝트 실행하기

운영 체제에서 명령 프롬프트(Command Prompt) 를 실행하고 다음 프로젝트 샘플을 실행합니다.

cd C:\MyEngineInstallLocation\

Samples\Games\MyGameSample\Binaries\Win64\MyGameSample.exe -trace=default,memory

프로젝트 세션을 레코딩하려면 메모리 트레이스 채널이 프로세스 시작 때부터 활성화 상태여야 합니다. 그렇지 않으면 후속 연결 세션에서 트레이싱 할당 이벤트를 시작할 수 없습니다. 또는 패키지로 만든 프로젝트에서 트레이스를 실행하는 경우, 해당 프로젝트가 개발(Development) 모드에서 패키징 되었는지 확인해야 합니다.

인사이트 세션 브라우저에서 트레이스 열기

언리얼 인사이트 세션 브라우저(Unreal Insights Session Browser)로 이동한 다음 언리얼 엔진 타이밍 인사이트(Timing Insights) 창에서 분석하기 위해 .utrace 파일을 더블클릭하여 엽니다. 메뉴(Menu) > 메모리 인사이트(Memory Insights) 를 선택하여 메모리 인사이트 창을 엽니다.

memory-insights-menu-option

메모리 할당 - 그래프 트랙

언리얼 인사이트는 각 할당 이벤트에 대해 완전한 콜 스택을 캡처하여 프로젝트에 할당된 메모리를 분석합니다.

메모리 인사이트(Memory Insights) 의 주요 인터페이스는 세션 중 메모리 사용 개요를 보여주는 타임라인으로 구성됩니다.

memory-insights-main-view

메모리 인사이트 트래커는 메모리의 라이브 할당 수에 관한 정보를 보여줍니다. 위 그림은 라이브 할당(Live Allocation) 및 해제 이벤트 수(Free Event Count)가 포함된 메인 메모리 그래프입니다.

언리얼 인사이트는 각 할당 이벤트에 대해 완전한 콜 스택을 캡처하여 프로젝트에 할당된 메모리를 분석합니다.

메인 메모리 그래프(Main Memory Graph) 에서는 LLM 에서 수집한 각 태그에 대한 정보 등 프로젝트에서 트래킹된 메모리의 총량을 보여줍니다. 또한, 라이브 할당의 총개수를 보여주는 그래프도 있습니다.

그래프 타입

색상

설명

메모리 할당 총량

파란색

각 시점에 할당된 메모리의 총량을 상세 할당 트래킹 기반으로 보여줍니다.

라이브 할당 수

노란색

임의의 시점에 활성 상태인 할당의 총개수를 보여줍니다.

할당/해제 이벤트 수

녹색/주황색

유닛당 할당 및 해제 이벤트 수를 보여줍니다. 이는 시간의 '슬라이스'로 표시됩니다.

각 그래프는 상세한 할당 트래킹을 기반으로 표시됩니다. 시간 값 0부터 시작하며, 세분화는 약 1ms입니다. LLM 접두사 태그(RenderTargets, SceneRender, UObject)가 있는 나머지 그래프는 로우 레벨 메모리 트래킹 런타임 시스템을 기반으로 합니다.

이들 태그는 세션이 시작되고 몇 초 후에 트래킹을 시작하며, 프레임별 세분화를 포함합니다.

기본적으로 각각 할당/해제 이벤트 4,096개마다 타임스탬프 하나가 표시됩니다. 필요에 따라 Engine/Source/Runtime/Core/Private/ProfilingDebugging/MemoryAllocationTrace.cpp에 위치한 MarkerSamplePeriod를 수정하면 이 양을 수정할 수 있습니다. 예를 들어, 이 변수를 0 값으로 설정하면 각 할당/해제 이벤트마다 타임스탬프가 표시됩니다.

메모리 인사이트(Memory Insights) 타임라인은 타이밍 뷰(Timing View) 에 대한 오버레이 트랙을 지원합니다. 메모리 인사이트 뷰를 사용할 때는 타이밍(Timing), 조사(Investigation), LLM 태그(LLM Tags), 모듈(Modules)** 의 4가지 패널을 활용할 수 있습니다.

타이밍 뷰

타이밍(Timing) 을 클릭하면 타이밍 뷰(Timing View) 창의 표시를 토글할 수 있습니다. 여기서는 메모리 사용과 관련된 다양한 트랙의 퍼포먼스 데이터를 관찰 및 필터링할 수 있습니다.

TimingButton.png

조사 패널

조사(Investigation) 패널은 할당과 관련된 다양한 쿼리 기능을 제공합니다.

InvestigationPanel.png

로우 레벨 메모리(LLM) 태그

LLM 태그(LLM Tags) 패널은 다양한 LLM 태그의 비저빌리티를 제어합니다. 이 데이터는 운영 체제에서 직접 트레이스됩니다.

LLMTagsPanel.png

모듈

콜 스택 심볼이 해석되면 결과가 캐시 파일에 저장됩니다. 모듈(Modules) 을 클릭하면 이 파일을 볼 수 있습니다. 이 패널을 사용하면 오래된 트레이스 파일을 열고 심볼을 사용할 수 있습니다.

ModulesPanel.png

메모리 트래킹의 이전 런타임은 Engine\Source\Runtime\Core\Public\HAL\LowLevelMemTracker.h 폴더에 위치한 LowLevelMemTracker 클래스에 구현됩니다. LLM 태그 패널과 LLM 그래프 모두 이 시스템에서 바로 트레이스된 데이터를 사용합니다. 상세한 할당 데이터는 별도의 특정 트레이스 구현에서 옵니다.

메모리 인사이트(Memory Insights)에는 새로운 쿼리 기능과 트래킹된 메모리 할당 정보가 포함되어 있습니다. 따라서 특정한 시간대 내의 특정한 순간 전후에 언리얼 엔진 5에서 할당하고 해제하는 메모리 블록을 식별하거나 메모리 누수를 확인할 수 있습니다. 트레이스 로그를 연 후 조사(Investigation) 탭으로 이동하면 쿼리 시스템에 액세스할 수 있습니다.

조사 - 할당 쿼리

타임라인에서는 메모리 사용의 개요를 제공하는 반면, 개별적인 할당이 특정 시간대 동안 행동하는 방식은 '쿼리'를 사용하여 평가합니다. 쿼리(Query)규칙(Rule)AB 라벨과 같은 하나 이상의 타임스탬프(Timestamps) 에 의해 정의됩니다.

QueryRules.png

조사(Investigation) 패널 에는 데이터 평가를 위한 쿼리 규칙이 있습니다.

사용 가능한 쿼리 규칙 은 다음과 같습니다.

쿼리 규칙

시간 변수

설명

활성 할당(Active Alloc)

A

시간 A에 활성 상태인 모든 할당을 표시합니다.

이전(Before)

A

시간 A 이전에 활성 상태인 모든 할당을 표시합니다.

이후(After)

A

시간 A 이후에 활성 상태인 모든 할당을 표시합니다.

감소(Decline)

A와 B

시간 A 이전에 할당되었고 시간 A와 B 사이에 해제된 모든 할당을 표시합니다.

성장(Growth)

A와 B

시간 A와 B 사이에 할당되었고 시간 B 이후에 해제된 모든 할당을 표시합니다.

성장 대 감소(Growth Vs Decline)

A와 B

[#GrowthDecline 포함

해제 이벤트(Free Events)

A와 B

시간 A와 B 사이에 해제된 모든 할당을 표시합니다.

할당 이벤트(Alloc Events)

A와 B

시간 A 와 B 사이에 할당된 모든 할당을 표시합니다.

단기 할당(Short Living Allocs)

A와 B

시간 A 이후에 할당되었고 시간 B 전에 해제된 모든 할당을 표시합니다. 이 규칙은 스택 할당일 수 있는 할당을 식별하는 데 사용할 수 있습니다. 즉, 이 규칙은 일시적이거나 단기적인 할당을 식별합니다.

장기 할당(Long Living Allocs)

A와 B

시간 A 전에 할당되었고 시간 B 이후에 해제된 모든 할당을 표시합니다.

메모리 누수(Memory Leaks)

A, B, C

시간 A와 B 사이에 할당되었고 시간 C까지 해제되지 않은 모든 할당을 표시합니다. 레벨 전환 도중 등 특정한 시간에 해제될 것으로 예상되는 메모리를 찾는 데 유용합니다.

제한적 수명(Limited Lifetime)

A, B, C

시간 A와 B 사이에 할당되었고 시간 B와 C 사이에 해제된 모든 할당을 표시합니다.

장기 할당 감소(Decline of Long Living Allocs)

A, B, C

시간 A 전에 할당되었고 시간 B와 C 사이에 해제된 모든 할당을 표시합니다.

일정 수명(Specific Lifetime)

A, B, C, D

시간 A와 B 사이에 할당되었고 시간 C와 D 사이에 해제된 모든 할당을 표시합니다.

쿼리는 규칙을 선택하고 라벨이 지정된 마커를 타임라인에서 원하는 위치로 드래그하거나, 조사(Investigation) 탭에서 시간을 지정하여 작성할 수 있습니다.

RuleSelect.png

원하는 규칙과 시간을 선택한 뒤 조사 탭에서 쿼리 실행(Run Query) 버튼을 눌러서 쿼리를 작성할 수 있습니다.

RunQuery.png

쿼리와 캡처하는 데이터세트에 따라 쿼리를 실행하는 데 상당한 시간이 소요될 수 있습니다.

‘성장' 할당(시간 A와 B 사이에 할당되었고 시간 B 이후에 해제) 및 ‘감소' 할당(시간 A 이전에 할당되었고 시간 A와 B 사이에 할당)을 모두 식별합니다. 감소 할당은 음수의 크기를 가지도록 변경되므로, 크기 집계에서 시간 A와 B 사이의 베리에이션을 확인할 수 있습니다. 이 쿼리의 결과로 시간 A에 할당된 양과 시간 B에 할당된 양을 비교할 수 있습니다. 메모리 할당을 태그 또는 콜 스택으로 그룹화하면 각 그룹의 베리에이션(B-A)이 표시됩니다.

할당 분석 뷰

쿼리를 실행하면 새 창이 표시되고, 쿼리가 완료되면 할당 테이블에 결과가 채워집니다. 기본적으로 이 결과는 일반 목록에 표시됩니다.

각 할당은 수(Count), 크기(Size), LLM 태그(Tag), 할당을 만든 함수(Function) 와 함께 표시됩니다.

AllocsTable.png

함수 또는 정보 아이콘에 마우스를 올리면 전체 콜 스택에 추가적인 상세 정보가 표시됩니다.

CallStackInfo.png

정보 아이콘에 마우스를 올리면 전체 콜 스택이 표시됩니다.

정렬

테이블 헤더를 클릭하면 열별로 목록을 정렬할 수 있습니다.

Sorting.png

열 정렬

설명

할당 계층구조(Allocation Hierarchy)

할당 트리의 계층구조에 따라 정렬합니다.

할당 수(Allocation Count)

할당 개수에 따라 정렬합니다.

크기(Size)

할당의 크기에 따라 정렬합니다.

LLM 태그(LLM Tag)

할당의 LLM 태그에 따라 정렬합니다.

함수(콜스택)(Function (Callstack))

할당의 콜 스택에서 해석된 상위 함수에 따라 정렬합니다.

그룹화

디폴트(Default)

디폴트 할당을 표시합니다.

상세(Detailed)

할당의 상세 정보를 표시하도록 트리 뷰를 환경설정합니다.

힙(Heap)

메모리의 여러 타입이 사용되는 방식을 조사합니다. 다중 주소 공간을 참고하세요.

크기(Size)

크기가 큰 할당을 빠르게 찾습니다.

태그(Tags)

시스템당 할당을 표시합니다.

콜스택(Callstack)

콜 스택 할당이 오는 곳을 조사합니다.

반전 콜스택(Inverted Callstack)

반전된 콜 스택별로 할당 분석을 표시하도록 트리 뷰를 환경설정합니다.

주소(4k 페이지)(Address(4k Page))

할당을 주소 기반으로 정렬된 4k 메모리 페이지로 그룹화합니다.

  • 콜스택(Callstack) 또는 반전 콜스택(Inverted Callstack)으로 그룹화하면 컨텍스트 메뉴에 Visual Studio에서 열기(Open in Visual Studio) 액션이 표시됩니다.

  • R 단축키를 누르면 현재 트리의 중요한 경로가 확장됩니다.

프리셋(Preset) 옵션을 사용하여 할당을 그룹화할 수 있습니다.

Preset.png

계층구조(Hierarchy) 로 이동하여 모두(All) 를 클릭하면 디폴트 일반 뷰(Flat view) 를 추가적인 대체 그룹으로 변경하는 드롭다운 메뉴가 표시됩니다.

AlternateGroups.png

고급 필터 적용

검색 텍스트 박스로 결과에 계층형 노드 텍스트 기반의 필터를 빠르게 적용할 수 있습니다. 검색 텍스트 박스 옆의 필터 컨피규레이터(Filter Configurator) 를 클릭하면 쿼리에 의해 만들어진 할당 세트를 더욱 필터링하여 할당 그룹을 격리할 수 있습니다.

AdvancedFilter.png

그룹과 AND/OR 키워드를 사용하면 고급 쿼리를 빌드할 수 있습니다.

콜 스택 심볼 해석

프로그램 카운터 주소를 사용하여 프로젝트에서 콜 스택 심볼 트레이싱(Call Stack Symbol Tracing) 을 수행할 수 있습니다. 분석에서 이러한 주소는 해당하는 소스 파일에 관한 정보와 함께 읽을 수 있는 스트링으로 해석해야 합니다.

이를 위해서는 메모리 인사이트(Memory Insights)가 디버그 정보를 포함하고 있는 올바른 버전의 파일에 액세스할 수 있어야 합니다. 플랫폼에 따라 .pdb 또는 .elf 파일입니다. 인사이트는 다음 목록에 따라 올바른 파일을 검색합니다.

  1. 이 세션에서 사용자가 입력한 모든 새로운 경로.

  2. 실행파일 경로. 가능한 일부 플랫폼의 경우 바이너리로 컴파일됩니다.

  3. UE_INSIGHTS_SYMBOLPATH 인바이런먼트 변수에서의 경로. 이 변수에는 세미콜론으로 구분된 경로를 사용할 수 있습니다.

  4. 사용자 환경설정 파일의 경로.

심볼이 해석되면 결과가 캐시 파일에 저장됩니다. 모듈(Modules) 패널을 클릭하면 파일을 볼 수 있습니다. 그런 다음 선택한 파일을 우클릭하고 드롭다운 메뉴에서 다음 옵션 중 하나를 선택하면 파일을 열 수 있습니다.

SymbolLoading.png

그러면 해당 디버그 정보에 대한 액세스 권한이 없는 다른 사용자에게도 트레이스 파일을 전송할 수 있습니다.

로드 메서드

설명

파일에서 심볼 로드

파일을 지정하여 모듈에 대한 심볼을 로드합니다. 성공하면 같은 디렉터리에서 다른 실패한 모듈의 로드를 시도합니다.

디렉터리에서 심볼 로드

디렉터리를 지정하여 모듈에 대한 심볼을 로드합니다. 성공하면 같은 디렉터리에서 다른 실패한 모듈의 로드를 시도합니다.

심볼 해석은 현재 Win64, XB1/XSX, PS4/PS5, Switch에서 사용할 수 있습니다.

다중 주소 공간

메모리 트레이싱은 다양한 힙(Heap) 에서 메모리를 트래킹합니다. 개념적으로 모든 할당은 한 가지 메모리 타입을 나타내는 루트 힙(Root Heap) 에 속해야 합니다. 예를 들어 데스크톱 플랫폼에서는 시스템 메모리가 하나의 루트 힙이고, 그래픽 카드의 비디오 메모리가 또 하나의 루트 힙입니다. 각 루트 힙에는 자체 주소 공간이 있습니다. 각 루트 힙 아래에 할당을 호스팅할 수 있는 힙 할당이 만들어집니다. 이는 보통 할당을 백업하는 가상 메모리 할당을 의미하지만, 블록 스타일 할당자 역시 힙 할당으로 표시될 수 있습니다. 그러면 이 메모리 블록의 사용에 대한 조사를 제공합니다.