작성일 :

Unity Profiler를 넘어서

Part 1에서는 Unity Profiler와 Frame Debugger를 살펴보았습니다. Unity Profiler의 CPU/GPU/Rendering/Memory 모듈로 함수별 비용, 스레드 병목, 드로우콜 수, 에셋 메모리를 측정하고, Frame Debugger로 드로우콜 단위의 렌더링 과정과 배칭 깨짐 원인을 확인하는 방법을 다루었습니다.

하지만 모바일 환경에서의 성능 문제는 Unity Profiler만으로 진단하기 어려운 경우가 많습니다. 에디터에서는 60fps가 나오던 게임이 실기기에서 30fps 이하로 떨어지기도 하고, 게임 시작 직후에는 문제없다가 10분 후 서멀 쓰로틀링으로 성능이 급락하기도 합니다. 모바일 CPU는 데스크톱 대비 클럭이 낮고, 모바일 GPU는 GPU 아키텍처 (2) - 모바일 GPU와 TBDR에서 다룬 타일 기반 렌더링(TBDR)을 사용하며, 메모리 대역폭과 전력 예산이 제한적입니다. 이런 차이 때문에 모바일에서의 성능 분석은 에디터에서의 분석과 근본적으로 다릅니다.


Unity Profiler는 CPU 시간, GPU 통계, 메모리 사용량 같은 엔진 수준의 데이터를 제공합니다. 모바일에서 발생하는 많은 성능 문제를 이 도구로 진단할 수 있지만, 모바일 GPU 내부의 타일 메모리 효율, 셰이더 코어 활용도, 메모리 대역폭 소비량 같은 하드웨어 수준의 데이터까지는 보여주지 않습니다. 이런 데이터를 확인하려면, GPU 벤더가 제공하는 전용 프로파일링 도구가 필요합니다.

이 글에서는 Android와 iOS에서 사용할 수 있는 벤더별 프로파일링 도구, Unity에서 모바일 기기로 원격 프로파일링을 연결하는 워크플로우, 그리고 모바일 성능 테스트 방법론을 다룹니다.


Android 시스템 레벨 프로파일링

Android에서의 프로파일링은 시스템 레벨과 GPU 레벨로 나뉩니다. 시스템 레벨 프로파일링은 CPU의 전체적인 활동을 추적하고, GPU 레벨 프로파일링은 GPU 내부의 상세한 동작을 분석합니다.

systrace와 Perfetto

systrace(Android 10 이전)와 Perfetto(Android 10 이후)는 Android 운영 체제가 제공하는 시스템 레벨 트레이스 도구입니다. Unity Profiler가 Unity 엔진 내부의 함수 호출을 추적하는 것과 달리, systrace/Perfetto는 운영 체제 전체의 CPU 활동을 추적합니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
systrace/Perfetto가 보여주는 정보

시스템 레벨 트레이스

  커널 스케줄링
    → 어떤 CPU 코어에 어떤 스레드가 배치되었는지
    → 스레드가 대기 상태(sleep)인 시간

  프레임 렌더링 타이밍
    → SurfaceFlinger(화면 합성기)의 프레임 제출 시점
    → 프레임 간 간격 (vsync 대비 지연 여부)

  I/O 활동
    → 디스크 읽기/쓰기 시점과 지속 시간
    → 에셋 로딩으로 인한 I/O 블로킹

  메모리 압력
    → 시스템 메모리 부족으로 인한 LMK(Low Memory Killer)
    → 앱의 메모리 할당/해제 패턴

systrace/Perfetto가 유용한 상황은, Unity Profiler에서는 문제가 보이지 않는데 실기기에서 프레임 드롭이 발생하는 경우입니다. 운영 체제가 게임 스레드를 저전력 코어로 이동시켰거나, 백그라운드 서비스가 CPU를 점유하고 있거나, 디스크 I/O로 인해 메인 스레드가 블로킹되는 상황은 Unity Profiler로는 보이지 않지만 systrace/Perfetto에서는 확인할 수 있습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Perfetto 트레이스 예시 — 스레드 스케줄링

ARM big.LITTLE 구조에서 코어 0~3은 고성능 코어(높은 클럭),
코어 4~7은 효율 코어(낮은 클럭)입니다.

시간 →   0ms        5ms        10ms       15ms              20ms
         │          │          │          │                  │

코어 0   ████░░░░░░████░░░░░░████░░░░░░░░░░░░░░░░░░
(고성능)  메인 타앱    메인 타앱   메인
                                                ↓ 마감(16.67ms)
코어 4   ░░░░░░░░░░████████████████████████████████████████
(효율)    유휴       렌더 스레드───────────────────────→
                                                마감 초과

→ 렌더 스레드가 효율 코어에서 실행되어 마감 시점에도 완료되지 못함
→ 메인 스레드는 고성능 코어를 다른 앱/서비스와 시간 분할하여 실행 시간 부족


Perfetto는 Chrome 기반의 웹 UI(ui.perfetto.dev)에서 트레이스 파일을 열어 분석합니다. 가로축이 시간이고 각 CPU 코어와 스레드가 행으로 표시되는 구조는 Unity Profiler의 Timeline 뷰와 유사하여 동일한 방식으로 읽을 수 있지만, 표시되는 범위가 Unity 엔진 내부가 아닌 운영 체제 전체입니다.


Android GPU 프로파일링 — ARM Mali

모바일 시장에서 높은 점유율을 차지하는 GPU 아키텍처 중 하나가 Arm의 Mali입니다. Samsung Exynos, MediaTek Dimensity 등 다양한 SoC(System on Chip — CPU, GPU, 메모리 컨트롤러 등을 하나의 칩에 통합한 프로세서)에 탑재됩니다.

Mali GPU의 내부 동작을 분석하는 전용 도구는 Arm Performance Studio(이전 명칭: Arm Mobile Studio)입니다. 이 제품군 안에서 GPU 카운터 수집과 시각화를 담당하는 구성 요소가 Streamline입니다.

Streamline이 제공하는 데이터

Streamline은 Mali GPU의 하드웨어 카운터를 직접 읽어서, Unity Profiler가 제공하지 않는 GPU 내부 정보를 보여줍니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
Streamline — Mali GPU 카운터 예시

셰이더 코어 활용도
─────────────────
Fragment Shader Cycles:    2,450,000
Vertex Shader Cycles:        380,000
Shader Core Utilization:       78%

→ 프래그먼트 셰이더가 전체 GPU 비용의 대부분을 차지
→ 셰이더 코어 활용도가 78%이면 GPU가 높은 부하 상태

타일 메모리
─────────────
Tiles:                   3,840
Tile Load/Store:         7,680  (로드 + 스토어)
Transaction Eliminations:  480  (변경 없는 타일 스킵)

→ Transaction Elimination이 낮으면 거의 모든 타일이
  매 프레임 변경되고 있음 → 정적 영역 최적화 가능성 확인

메모리 대역폭
─────────────
External Read Bandwidth:   1.2 GB/s
External Write Bandwidth:  0.8 GB/s
Total:                     2.0 GB/s

→ 기기의 대역폭 한계(예: 6.4 GB/s) 대비 사용률 확인
→ 높으면 텍스처 해상도/포맷 최적화 필요


GPU 아키텍처 (2) - 모바일 GPU와 TBDR에서 설명한 Mali의 FPK(Forward Pixel Kill)는, 불투명 오브젝트가 카메라에서 가까운 순서(front-to-back)로 처리될 때 가려진 프래그먼트를 조기에 제거합니다. 가까운 프래그먼트가 먼저 처리되어야 그 뒤에 가려진 프래그먼트를 감지하고 폐기할 수 있기 때문입니다.

Streamline에서 “Killed Fragments” 카운터를 확인하면, FPK가 실제로 얼마나 많은 프래그먼트를 제거하고 있는지를 수치로 볼 수 있습니다. 이 값이 낮다면 정렬이 올바르지 않아 가려진 프래그먼트가 제거되지 못하고 있을 가능성이 있으며, 그만큼 오버드로우가 GPU 비용에 그대로 반영됩니다. 불투명 오브젝트의 front-to-back 정렬이 제대로 동작하는지 확인해야 합니다.

Graphics Analyzer

Arm Performance Studio에는 Graphics Analyzer도 포함되어 있습니다. Streamline이 프레임 전체의 GPU 카운터를 시간 축으로 보여주는 도구라면, Graphics Analyzer는 특정 프레임을 캡처하여 드로우콜 단위로 분석하는 도구입니다. Unity의 Frame Debugger와 역할이 유사하지만, Frame Debugger가 엔진 수준의 드로우콜 순서를 보여주는 것과 달리, Graphics Analyzer는 Mali GPU의 관점에서 각 드로우콜의 셰이더 비용, 텍스처 접근 패턴, 정점 처리 효율을 보여줍니다.

예를 들어, Streamline에서 프래그먼트 셰이더 사이클이 비정상적으로 높다는 것을 확인했다면, Graphics Analyzer로 해당 프레임을 캡처하여 어떤 드로우콜의 셰이더가 가장 많은 GPU 사이클을 소모하는지를 특정할 수 있습니다. 셰이더 소스 코드에서 비용이 높은 명령어(텍스처 샘플링, 복잡한 수학 연산 등)를 직접 확인하고, 텍스처 캐시 미스가 많이 발생하는 드로우콜도 식별할 수 있습니다.


Android GPU 프로파일링 — Qualcomm Adreno

Qualcomm Snapdragon SoC에 탑재되는 Adreno GPU는 ARM Mali와 함께 Android 기기에서 가장 많이 사용되는 모바일 GPU 아키텍처입니다. Samsung Galaxy S 시리즈(Snapdragon 모델), Xiaomi 등에서 사용됩니다. Adreno GPU의 전용 분석 도구가 Snapdragon Profiler입니다.

Snapdragon Profiler의 주요 기능

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Snapdragon Profiler — 주요 분석 기능

1. 실시간 모니터링 (Realtime)
   CPU 사용률, GPU 사용률, 메모리, 전력 소비를 실시간 그래프로 표시
   → 게임 플레이 중 성능 변화를 즉시 확인

2. 스냅샷 캡처 (Snapshot Capture)
   특정 프레임의 렌더링 상태를 캡처
   → 드로우콜 목록, 셰이더 소스, 텍스처, 렌더 타깃 확인
   → Frame Debugger와 유사하지만 GPU 하드웨어 수준의 정보

3. 트레이스 캡처 (Trace Capture)
   일정 시간 동안의 GPU 카운터를 기록
   → 렌더 스테이지별 시간 (Binning, Rendering, GMEM Load/Store)
   → 오버드로우 히트맵
   → 셰이더 ALU 사용률, 텍스처 페치 대기 시간


Snapdragon Profiler의 오버드로우 히트맵은 화면의 각 픽셀이 몇 번 렌더링되었는지를 색상으로 표현합니다. Unity의 Frame Debugger 오버드로우 뷰보다 정밀한데, Adreno GPU의 하드웨어 카운터에서 직접 데이터를 가져오기 때문입니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
오버드로우 히트맵 — Snapdragon Profiler

오버드로우 횟수별 색상

  1회:  ░░░  (파란색/어두운 색)
  2회:  ▒▒▒  (초록색)
  3회:  ▓▓▓  (노란색)
  4회+: ███  (빨간색)

  ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  ░░░░░░░▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒░░░░░░░
  ░░░░░░░▒▒▓▓▓▓▓▓▓▓▓▓▓▓▒▒░░░░░░░
  ░░░░░░░▒▒▓▓████████▓▓▒▒░░░░░░░
  ░░░░░░░▒▒▓▓████████▓▓▒▒░░░░░░░
  ░░░░░░░▒▒▓▓▓▓▓▓▓▓▓▓▓▓▒▒░░░░░░░
  ░░░░░░░▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒░░░░░░░
  ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░

화면 중앙이 빨간색 → 4회 이상 렌더링
→ 반투명 파티클, UI 겹침 등이 원인일 가능성


GPU 아키텍처 (2) - 모바일 GPU와 TBDR에서 Adreno의 LRZ(Low Resolution Z-buffer)가 보이지 않는 프래그먼트를 사전에 제거한다고 했습니다. Snapdragon Profiler에서 LRZ의 효율(제거된 프래그먼트 비율)을 확인하면, 불투명 오브젝트의 정렬이 LRZ에 얼마나 도움이 되는지를 수치로 검증할 수 있습니다. Binning 단계와 Rendering 단계의 시간 비율은 별도 카운터로 제공되며, 이를 통해 타일 기반 렌더링의 효율을 직접 측정할 수 있습니다.


iOS 프로파일링

앞에서 Android의 Mali와 Adreno GPU를 분석하는 도구를 살펴봤습니다. iOS 기기는 이들과 다른 GPU 아키텍처를 사용합니다. Apple이 직접 설계한 Apple GPU와 그래픽스 API Metal로 구성되며, Apple은 Xcode에 통합된 프로파일링 도구를 제공합니다.

Xcode GPU Debugger

Xcode의 GPU Debugger(Metal Debugger)는 Metal 프레임을 캡처하여 분석하는 도구입니다. Xcode에서 앱을 실행한 뒤 “Capture GPU Frame” 버튼을 누르면, 해당 프레임의 모든 렌더링 명령이 캡처됩니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Xcode GPU Debugger의 주요 기능

Metal 프레임 캡처
  프레임의 모든 렌더 패스, 드로우콜, 컴퓨트 디스패치를 목록화
  각 단계의 소요 시간, 파이프라인 상태, 리소스 바인딩 확인

셰이더 프로파일링
  셰이더 함수별 GPU 실행 시간 표시
  어떤 셰이더 함수가 가장 비싼지 직접 확인
  셰이더 소스 코드에서 비용이 높은 라인 강조 표시

의존성 그래프
  렌더 패스 간의 의존 관계를 그래프로 시각화
  불필요한 렌더 패스나 리소스 전환을 발견할 수 있음

메모리 뷰어
  GPU에 할당된 버퍼, 텍스처, 렌더 타깃의 목록과 크기 확인


GPU 아키텍처 (2) - 모바일 GPU와 TBDR에서 Apple GPU의 HSR(Hidden Surface Removal)이 타일 단위로 보이지 않는 프래그먼트를 제거한다고 했습니다. Xcode GPU Debugger의 셰이더 프로파일링에서 프래그먼트 셰이더의 실행 횟수를 확인하면, HSR이 실제로 얼마나 효과적으로 동작하는지를 검증할 수 있습니다. HSR이 잘 동작하면, 화면에 실제로 보이는 픽셀마다 프래그먼트 셰이더가 한 번씩만 실행되므로 실행 횟수가 화면 해상도(픽셀 수)에 근접합니다. 오버드로우가 심하면 같은 픽셀 위치에 여러 물체가 겹쳐 렌더링되어 실행 횟수가 화면 픽셀 수의 몇 배가 됩니다.

Instruments

Xcode의 Instruments는 CPU와 GPU를 포괄하는 시스템 레벨 프로파일링 도구입니다. CPU 실행 시간, GPU 파이프라인 타이밍, 메모리 할당, 전력 소비 등 각기 다른 측정 항목을 담당하는 “인스트루먼트”를 조합하여 원하는 관점으로 성능을 분석합니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
Instruments의 주요 인스트루먼트

Time Profiler
  CPU에서 실행되는 함수의 호출 시간 측정
  콜 스택을 트리 형태로 표시
  Unity Profiler의 CPU 모듈과 유사하지만, 네이티브 코드
  (IL2CPP로 변환된 코드 포함)까지 추적 가능

Metal System Trace
  GPU 파이프라인의 각 단계(Vertex, Fragment, Compute)별 시간
  CPU와 GPU의 동기화 지점, GPU 유휴 시간 확인
  CPU 바운드/GPU 바운드 판별에 유용

Allocations
  메모리 할당과 해제의 타임라인
  메모리 누수 추적, 할당 소스(콜 스택) 확인

Energy Log
  CPU/GPU/네트워크/디스플레이의 전력 소비 추정
  에너지 효율이 낮은 구간 식별


Metal System Trace는 CPU가 GPU에 명령을 제출하는 시점과 GPU가 명령을 실행하는 시점을 타임라인에 함께 표시합니다. CPU와 GPU 사이의 동기화 대기(fence wait) 시간이 길면 CPU 또는 GPU 중 한쪽이 병목이라는 뜻입니다. Metal System Trace에서 fence wait가 긴 구간을 특정한 뒤, Unity Profiler의 Timeline 뷰에서 같은 프레임 구간을 열면 어떤 C# 호출이 그 대기를 발생시켰는지 추적할 수 있습니다.


원격 프로파일링 워크플로우

Arm Streamline, Snapdragon Profiler, Xcode Instruments 등 벤더 도구들은 모두 실기기에서 실행됩니다. Unity Profiler도 실기기에서 데이터를 수집하려면, 개발 PC와 모바일 기기를 연결해야 합니다.

Development Build 설정

원격 프로파일링을 위해서는 빌드 설정에서 Development Build를 활성화해야 합니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
Build Settings에서 설정할 항목

Build Settings

[x] Development Build
     → 프로파일러 연결을 위한 필수 옵션

[x] Autoconnect Profiler
     → 앱 시작 시 자동으로 Unity Profiler에 연결 시도
     → 수동 연결도 가능하지만, 자동 연결이 편리

[ ] Script Debugging
     → 성능 측정 시에는 끄는 것이 권장
     → 활성화하면 디버깅용 오버헤드가 추가됨

[ ] Deep Profiling Support
     → 실기기에서는 오버헤드가 커서 비권장
     → 필요한 경우에만 한시적으로 활성화


Development Build는 릴리스 빌드에 비해 약간의 오버헤드가 있습니다. 프로파일러 데이터를 수집하고 전송하는 비용이 포함되기 때문입니다. 하지만 이 오버헤드는 Deep Profiling에 비하면 미미하며, 실제 성능 패턴을 유의미하게 변형하지 않습니다.

USB 연결

USB 케이블로 모바일 기기를 개발 PC에 직접 연결하는 방법이 가장 안정적입니다.


Android의 경우, USB 디버깅이 활성화된 상태에서 adb forward 명령으로 포트를 포워딩합니다. Unity가 이 과정을 자동으로 처리하는 경우가 대부분이지만, 연결이 되지 않을 때는 수동으로 포트 포워딩을 설정해야 할 수 있습니다.

iOS의 경우, Xcode에서 Development Build를 기기에 설치한 뒤, Unity Profiler의 연결 대상 드롭다운에서 기기를 선택합니다.

Wi-Fi 연결

USB 케이블 없이 Wi-Fi로 프로파일링하는 것도 가능합니다. 개발 PC와 모바일 기기가 같은 네트워크에 있어야 하며, Unity Profiler의 연결 대상에서 기기의 IP 주소를 직접 입력하거나, 자동 감지된 기기를 선택합니다.

Wi-Fi 프로파일링은 편리하지만 한계가 있습니다. 네트워크 지연으로 인해 프로파일 데이터의 전송이 지연될 수 있고, 대량의 데이터(Deep Profiling 등)를 전송할 때 패킷 손실이 발생할 수 있습니다. 정밀한 측정이 필요한 경우에는 USB 연결이 권장됩니다.

에디터 프로파일링과 실기기 프로파일링의 차이

에디터에서의 프로파일링 결과와 실기기에서의 결과는 크게 다릅니다.


에디터 vs 실기기 프로파일링 차이

항목 에디터 실기기
CPU 성능 데스크톱 CPU (높은 클럭) 모바일 CPU (낮은 클럭, 서멀 쓰로틀링 있음)
GPU 성능 데스크톱 GPU 모바일 GPU (TBDR), 대역폭·셰이더 성능 다름
메모리 수 GB 이상 여유 1~4 GB (OS와 공유), OOM Kill 가능
에디터 오버헤드 Inspector, Scene View, 에디터 스크립트 포함 게임 로직만 실행
IL2CPP Mono 런타임 IL2CPP (AOT 컴파일), 실행 패턴이 다를 수 있음
텍스처 압축 원본 포맷 사용 가능 ASTC/ETC2 압축 적용, 메모리 사용량 다름


에디터 프로파일링은 개발 초기에 명백한 문제(매 프레임 GC 할당, 비효율적 알고리즘)를 빠르게 발견하는 용도로 유용합니다. 하지만 성능 검증의 최종 단계는 반드시 실기기에서 수행해야 합니다. 도구를 갖췄다면, 다음으로 중요한 것은 무엇을 어떤 조건에서 측정할 것인가를 체계적으로 정하는 일입니다.


성능 테스트 방법론

프로파일링 도구를 확보했다면, 측정 대상과 측정 조건을 체계적으로 정해야 합니다. 일관된 테스트 방법론이 없으면 최적화 전후 비교가 불가능하고, 문제가 재현되지 않아 원인을 특정할 수 없습니다.

최악 조건에서의 테스트

성능 테스트는 게임이 가장 무거운 상황에서 수행해야 합니다. 평균적인 상황에서 30fps가 나온다고 해도, 보스전에서 파티클이 폭발하고 적이 20마리 동시에 등장하며 UI에 대미지 숫자가 쏟아지는 상황에서 15fps로 떨어진다면, 그것이 사용자가 체감하는 성능입니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
최악 조건 시나리오 설계

최대 부하 장면 구성

적 캐릭터: 최대 동시 출현 수 (예: 20체)
  → 각각 AI 연산, 애니메이션, 물리 충돌

파티클: 동시 활성 파티클 시스템 수 (예: 10개)
  → 폭발, 마법, 피격 이펙트 동시 재생

UI: 최대 표시 요소 (대미지 숫자, 체력바, 미니맵)
  → 대미지 숫자 팝업 20개 이상 동시 표시

카메라: 가장 많은 오브젝트가 보이는 시점
  → 컬링 효율이 최저인 위치

물리: 다수의 충돌이 동시에 발생하는 상황
  → 폭발로 인한 리지드바디 연쇄 충돌


이런 최악 조건을 재현 가능한 테스트 씬으로 구성하면, 최적화 전후의 성능 변화를 일관되게 비교할 수 있습니다.

저사양 기기에서의 테스트

모바일 게임의 타깃 유저가 사용하는 기기는 개발 팀이 사용하는 최신 플래그십 기기가 아닙니다. 타깃 시장에서 주로 사용되는 중저가 기기에서 테스트해야 합니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
기기 등급별 테스트 전략

최소 사양 기기 (Min Spec)
  게임이 동작해야 하는 가장 낮은 사양
  → 30fps 유지가 목표
  → 메모리 예산의 하한선
  예: 2~3년 전 중저가 기기, RAM 3~4GB

기준 기기 (Target Spec)
  타깃 유저의 평균 기기
  → 안정적인 30fps 또는 목표 프레임레이트 유지
  → 주요 테스트 대상
  예: 1~2년 전 중급 기기, RAM 4~6GB

고사양 기기 (High Spec)
  고품질 설정 적용 대상
  → 60fps, 고해상도 텍스처, 후처리 효과 활성화
  예: 최신 플래그십, RAM 8GB 이상


최소 사양 기기에서 프레임 드롭이 발생하지 않는 것이 먼저이고, 고사양 기기에서의 품질 향상은 그 다음입니다. 최소 사양 기기에서의 테스트 결과가 출시 가능 여부를 결정합니다.

서멀 쓰로틀링 테스트

모바일 기기는 칩의 온도가 일정 수준을 넘으면 서멀 쓰로틀링(Thermal Throttling)으로 CPU와 GPU의 클럭을 강제로 낮춥니다. 게임 시작 직후에는 60fps가 나오더라도, 10분 후에는 칩이 과열되어 클럭이 절반으로 떨어지고 30fps 이하로 내려갈 수 있습니다.


서멀 쓰로틀링을 확인하려면, 10분 이상 연속으로 게임을 플레이하면서 프로파일링해야 합니다. 시작 직후의 프레임 시간과 10분 후의 프레임 시간을 비교하여, 서멀 쓰로틀링으로 인한 성능 저하 폭을 측정합니다. 여러 번 테스트를 반복할 때는, 기기를 충분히 냉각시킨 뒤 다음 테스트를 시작해야 합니다. 이전 테스트의 열이 남아 있으면 쓰로틀링 발생 시점이 앞당겨져 결과가 달라지기 때문입니다.

서멀 쓰로틀링 자체를 완전히 방지할 수는 없지만, GPU와 CPU의 부하를 줄이면 발열 속도를 늦출 수 있습니다. 시리즈에서 다룬 모든 최적화(드로우콜 감소, 셰이더 단순화, 오버드로우 감소, 물리 연산 감소 등)가 직접적으로 발열 감소에 기여합니다.

메모리 워터마크 측정

메모리 워터마크(Memory Watermark)는 게임 실행 중 메모리 사용량의 최대치(피크)입니다. 게임의 평균 메모리가 500MB이더라도, 보스전에서 잠깐 700MB까지 올라간다면, 워터마크는 700MB입니다. 메모리 관리 (2) - 네이티브 메모리와 에셋에서 다룬 것처럼, 모바일 OS는 메모리 한계를 초과한 앱을 강제 종료(OOM Kill)합니다. 워터마크가 기기의 가용 메모리를 초과하면 크래시가 발생합니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
메모리 워터마크 측정

  메모리(MB)
  │
  │                          ▲ 워터마크 (피크)
  │                     ┌────┤
  │              ┌──────┘    └────┐
  │  ┌───────────┘                └──────────────────
  │  │
  │──┴────────────────────────────────────────────────▶ 시간
     타이틀    로비    게임플레이  보스전   결과 화면

  → 보스전에서 메모리 피크 발생
  → 이 피크가 기기의 가용 메모리를 초과하지 않는지 확인


메모리 워터마크를 측정하려면, 게임의 모든 주요 장면(타이틀, 로비, 게임플레이, 보스전, 결과 화면)을 순서대로 진행하면서 Memory 모듈의 최대값을 기록합니다. 최소 사양 기기에서 워터마크가 가용 메모리의 70% 이내인 것이 안전한 기준입니다. OS와 다른 앱이 나머지 30%를 사용하기 때문입니다.


프로파일링 데이터 기록과 비교

앞에서 최악 조건, 저사양 기기, 서멀 쓰로틀링, 메모리 워터마크 등 무엇을 어떤 조건에서 측정해야 하는지를 살펴봤습니다. 하지만 프로파일링은 한 번 하고 끝나는 작업이 아닙니다. 최적화 전후의 데이터를 비교하여 개선 효과를 검증하고, 빌드마다 성능 회귀(regression)가 발생하지 않는지 확인하는 지속적인 과정입니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
프로파일링 데이터 기록 항목

테스트 환경
  기기 모델, OS 버전, Unity 버전, 빌드 설정

프레임 시간
  평균, 중간값(P50), 99번째 백분위(P99), 최대값
  → 평균보다 P99이 사용자 체감에 가까움

CPU 세부
  스크립트 시간, 물리 시간, 렌더링 준비 시간
  GC 발생 횟수, GC 평균 시간

GPU 세부
  드로우콜 수, SetPass 수, 삼각형 수

메모리
  피크 메모리(워터마크), 에셋별 사용량

서멀 상태
  10분 후 프레임 시간 변화, 기기 온도(가능한 경우)


평균 프레임 시간이 16ms(약 60fps)이더라도, 플레이 중 주기적으로 끊김이 느껴질 수 있습니다. 대부분의 프레임이 16ms 안에 끝나지만, 간헐적으로 50ms 이상 걸리는 프레임이 섞여 있기 때문입니다. 평균은 이런 끊김을 숫자 속에 묻어버립니다. P99(99번째 백분위)는 이 문제를 드러내는 지표입니다. 전체 프레임을 빠른 순서대로 나열했을 때 99% 지점의 값으로, P99이 50ms이면 100 프레임마다 한 번꼴로 50ms 이상의 프레임이 발생한다는 뜻입니다. 사용자가 체감하는 성능은 평균보다 P99에 가깝습니다.

최적화 작업 후에는, 동일한 테스트 환경과 시나리오에서 동일한 항목을 측정하여 이전 데이터와 비교합니다. 프레임 시간이 감소하고 메모리 워터마크가 낮아졌으면 개선이 확인된 것이고, 반대로 수치가 악화되었으면 최적화가 역효과를 낸 것입니다.


프로파일링 도구 선택 가이드

여러 도구를 살펴봤지만, 실전에서는 모든 도구를 동시에 사용하지 않습니다. 분석 대상에 따라 적합한 도구가 다릅니다.


상황별 프로파일링 도구 선택

상황 도구
프레임 드롭 원인 추적 Unity Profiler CPU 모듈 (Hierarchy + Timeline)
GC 스파이크 추적 Unity Profiler CPU 모듈 (GC Alloc 컬럼)
배칭 깨짐 확인 Frame Debugger
메모리 누수 추적 Memory Profiler 패키지 (스냅샷 비교)
Mali GPU 상세 분석 Arm Streamline
Adreno GPU 상세 분석 Snapdragon Profiler
Apple GPU 상세 분석 Xcode GPU Debugger
OS 레벨 CPU 스케줄링 확인 Perfetto (Android) / Instruments (iOS)
서멀 쓰로틀링 확인 장시간 연속 프로파일링 + 벤더 도구의 온도·클럭 모니터


실전에서는 Unity Profiler로 시작하여 문제 영역을 좁힌 뒤, 벤더 도구로 상세 분석하는 순서가 효율적입니다. Unity Profiler에서 GPU 바운드임을 확인하면, Streamline이나 Snapdragon Profiler로 GPU 내부를 분석합니다. CPU 바운드이면서 Unity Profiler로 원인을 특정할 수 없으면, Perfetto나 Instruments로 시스템 레벨을 확인합니다.


마무리

  • 모바일 성능 문제는 엔진 수준, 시스템 수준, GPU 하드웨어 수준에서 각각 다른 정보를 보여주므로, 한 도구로는 전체 그림을 볼 수 없습니다.
  • 에디터와 실기기는 CPU 클럭, GPU 아키텍처, 메모리 예산, 서멀 쓰로틀링이 모두 다르므로, 성능 검증의 최종 단계는 반드시 실기기에서 수행해야 합니다.
  • 평균 프레임 시간은 간헐적 끊김을 숨기므로, P99(99번째 백분위)을 기준으로 체감 성능을 판단해야 합니다.
  • 최적화 전후의 데이터를 동일 조건에서 비교해야 개선 효과를 검증할 수 있습니다.

프로파일링 능력은 시리즈에서 다룬 모든 최적화 지식을 실전에서 활용하기 위한 핵심 역량입니다. 병목이 어디인지 모르면 최적화는 추측이 되고, 프로파일러가 가리키는 곳에 시리즈의 기법을 적용하면 측정 가능한 개선이 됩니다.



관련 글

시리즈

전체 시리즈

Tags: Android, iOS, Unity, 모바일, 최적화, 프로파일링

Categories: ,