Quick Reference
CPU·GPU 시간을 단순 합산하지 말고 프레임을 늦추는 병목을 실기기에서 재현한 뒤 CPU Profiler·GPU 실험·Frame Debugger로 각각 검증합니다.
- 기준 버전은 Unity 6.5 (6000.5)입니다. 60 fps의 프레임 예산은
16.67 ms, 30 fps는33.33 ms입니다. CPU와 GPU 시간을 더한 값이 아니라, frame pacing을 포함해 다음 프레임을 늦게 만드는 쪽을 먼저 찾습니다. - 실제 타깃 기기의 release와 가까운 Development Build에서 warm-up 후 같은 카메라 경로와 입력을 재현합니다. Editor 수치, 첫 로딩 프레임, 서로 다른 전투 상황을 한 비교표에 섞지 않습니다.
- CPU Usage Profiler는 CPU 병목 가설을, GPU 모듈과 해상도·품질 실험은 GPU 병목 가설을, Frame Debugger는 어떤 draw/pass가 만들어졌는지를 확인합니다.
병목 판독
CPU, GPU, frame pacing
- Main Thread나 Render Thread의 실제 작업 시간이 예산을 넘으면 CPU-bound일 가능성이 큽니다. Scripts, Physics, animation, UI rebuild, culling, render submission을 Profiler Timeline에서 더 좁힙니다.
- 해상도, render scale, 그림자 품질, post-processing을 낮췄을 때 동일 장면의 frame time이 의미 있게 내려가면 GPU-bound 가설이 강해집니다. 하지만 이 변화는 증거 하나일 뿐이며, GPU 타이밍 지원 여부와 frame pacing도 함께 확인합니다.
Gfx.WaitForPresentOnGfxThread처럼 CPU thread가 기다리는 샘플은 CPU가 바쁜 것이 아니라 GPU 또는 present/vsync를 기다린다는 신호일 수 있습니다. 그 시간을 Scripts 최적화 대상으로 읽으면 방향이 틀어집니다.- VSync, 모바일 화면 주사율,
Application.targetFrameRate는 측정값에 상한을 만듭니다. 예를 들어 60 Hz v-sync에서 프레임이 16.67 ms 근처로 고정되면 작은 CPU 개선이 그래프에 바로 드러나지 않을 수 있습니다.
draw call, SetPass, 픽셀 비용
- draw event는 GPU에 제출된 한 번의 그리기 작업입니다. 수가 적어도 큰 full-screen pass, 높은 해상도, 투명 오브젝트 겹침, 무거운 셰이더 때문에 GPU는 느릴 수 있습니다.
- SetPass 증가는 shader/material 상태 전환이 많다는 단서입니다. draw call 수와 항상 같은 방향으로 움직이지 않으므로 Frame Debugger에서 실제 shader pass와 material 변경을 함께 봅니다.
- SRP Batcher는 SRP 호환 셰이더를 쓰는 많은 material의 CPU render submission 비용을 줄이는 기법입니다. GPU 픽셀 비용이나 투명 overdraw를 직접 줄이는 스위치는 아닙니다.
- GPU Instancing은 같은 mesh와 material을 반복 그릴 때 GPU 제출을 묶을 수 있습니다. 오브젝트마다 다른 material instance, instancing 비호환 셰이더, 렌더 상태 차이는 이점을 줄입니다.
측정 설정과 스크립트 연결
VSync Count는 Project Settings > Quality에서 표시 주기와 동기화합니다. 프로파일링 실험에서 frame cap 때문에 차이를 못 보는지 확인할 때만 바꾸며, 출시 설정을 임시 측정값에 맞춰 고정하지 않습니다. 모바일에서는 Application.targetFrameRate가 목표 주사율을 제한하는 대표 설정입니다.
using UnityEngine;
public sealed class FrameRatePolicy : MonoBehaviour
{
[SerializeField] private int targetFrameRate = 60;
private void Awake()
{
// 제품 정책으로 정한 값입니다. 병목을 숨기기 위한 임시 해법이 아닙니다.
Application.targetFrameRate = targetFrameRate;
}
}Application.targetFrameRate는 목표 frame rate를 설정합니다. 플랫폼과 v-sync 정책이 함께 적용되므로, 이 값만 바꿨다고 모든 기기에서 정확히 같은 fps가 보장되지는 않습니다.QualitySettings.vSyncCount는 desktop의 v-sync 동작에 관여합니다. frame cap 실험을 할 때는 현재 quality level, display refresh rate, targetFrameRate를 기록해 결과가 재현되게 합니다.- GPU Profiler 모듈의 유효한 timing은 graphics API와 target platform 지원에 따라 달라질 수 있습니다. GPU 수치가 없거나 신뢰하기 어려우면 품질 단계와 해상도를 하나씩 바꾼 대조 실험으로 가설을 세우고, 지원되는 target에서 다시 검증합니다.
자주 틀리는 부분
CPU 시간과 GPU 시간을 단순 합산하지 마세요. CPU가 다음 프레임 명령을 준비하는 동안 GPU가 이전 명령을 처리할 수 있습니다. 목표는 두 숫자의 합을 낮추는 것이 아니라, target frame budget을 넘기는 작업과 기다림의 원인을 찾는 것입니다.
resolution을 낮췄다고 GPU 병목이 확정되는 것은 아닙니다. Dynamic Resolution, UI Canvas, post-processing, render scale, v-sync가 함께 바뀌면 결과가 섞입니다. 같은 build·scene·camera path에서 한 요인씩 바꾸고, Frame Debugger와 GPU timing으로 교차 확인하세요.
참고 링크
2 sources