using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
publicclassDisplayFPS : MonoBehaviour
{
[SerializeField]
Text text;
float frames = 0f;
float timeElap = 0f;
float frameTime = 0;
voidStart()
{
}
voidUpdate()
{
frames++;
timeElap += Time.unscaledDeltaTime;
// 1초가 넘었을 때 FPS 갱신하고 timeElap 초기화// FPS는 1초에 몇 프레임을 그리는가// FPS = ms / 1000// frameTime은 1프레임 당 몇 초가 걸리는가// frameTime = 1000 / FPSif (timeElap > 1f)
{
frameTime = timeElap / (float)frames;
timeElap -= 1f;
UpdateText();
frames = 0;
}
}
privatevoidUpdateText()
{
text.text = string.Format("FPS = {0} frameTime = {1}", frames, frameTime * 1000.0f);
}
}
왜 Frame Time으로 프로파일링 해야하는가?
1. 결과가 아니라 각 렌더링 순간의 지표가 필요
a구간이 1ms, b구간이 2ms, c구간이 10ms 가 걸린다고 하면 c구간을 최적화 해야 좋을 것이다.FPS는 1초의 평균 값이기 때문에 한 프레임을 렌더링 할 때 걸리는 시간인 Frame Time을 중요시 해야한다.
2. FPS는 비선형적 지표이다.ex1)오브젝트가 추가 될 때 성능 변화량이 90FPS, 45FPS, 30FPS일 때 비선형적으로 떨어지는 것으로 보이지만 계산해보면 - 1개 : 1000/90.0 = 11.1ms- 2개 : 1000/45.0 = 22.2ms- 3개 : 1000/30.0 = 33.3ms이처럼 선형적으로 떨어지는 것이다.ex2)씬에서 보면 더 큰 차이가 있다.A씬 : 900FPS -> 450FPS900FPS = 1000 / 900 => 1.1ms450FPS = 1000 / 450 => 2.2msB씬 : 60FPS -> 56.5FPS60FPS = 1000 / 60 => 16.6ms56.5FPS = 1000 / 56.5 => 17.7ms
두 씬에서 모두 동일하게 1.1ms의 영향을 주고 있음을 보인다.
프로파일링 할 때는 FPS보다 Frame Time으로 프로파일링을 하는 것이 좋다.
데이터를 측정할 때는 여러 번 측정해 평균 값을 데이터로 사용하자.
매번 잴 때마다 값이 조금씩 다를 수 있기 때문이다.
또한 각 시나리오마다 다를 수 있는데 평균적으로 NPC가 몇 없는 마을보다 몬스터가 많이 나오는 사냥터가 FPS가 더 낮게 나오겠지만 NPC의 모델의 텍스처가 매우 크다면 마을이 더 낮을 수도 있다.
ex1)
아래의 Rendering Path가 Deffered로 되어있다면 기본적으로 대역폭에 요구되는 성능 비용이 커서 FPS가 낮게 나올 수 있다.
ex2)
포스트 프로세싱 등 후처리 효과도 비용이 크다.
Target Frame Rate
모바일 디바이스에서 쓰로틀링 상태로 진입하는 상태를 막기 위해 강제로 최고 FPS를 낮추는 방법이다.
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
publicclassTargetFrameRate : MonoBehaviour
{
voidStart()
{
Application.targetFrameRate = 40;
}
}
프로파일링 할 때는 FPS가 60까지 충분히 나오는지 확인하기 위해서 Application.TargetFrameRate를 60으로 설정하는 것이 좋다.
60프레임으로 표현할 수 있을 만큼 성능이 충분함에도 불구하고 40으로 제한을 두는 것은 그만큼 프로세서가 쉴 수 있는 시간을 충분히 확보해 둔다는 의미이다.
* Target Device : 갤럭시 노트 8
WaitForTargetFPS는 디바이스가 작업 후 쉴 시간이다. 쓰로틀링 방지를 위해 여유분이 있으면 좋다.
Target Frame = 30으로 설정 시 WaitForTargetFPS 10ms정도로 넉넉히 돌아간다.
Target Frame = 60으로 설정 후 시간이 좀 지났을 때 프로파일링 시 WaitForTargetFPS가 간신히 적용되는 것을 볼 수 있었다.
추가로 모바일 기기에서 TargetFrame = 40; 이 동작하지 않는 경우가 있었는데 이는 60Frames를 integer 값으로 나눌 수 있는 값이어야 한다고 한다.
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
publicclassTargetFrameRate : MonoBehaviour
{
voidStart()
{
QualitySettings.vSyncCount = 0;
Application.targetFrameRate = 40;
}
}
VSync(수직 동기화)
targetFrameRate를 높게 설정해도 프레임이 60FPS를 넘지 않을 때 VSync를 의심해보자.
VSync(Vertical Synchronization = 수직동기화): 모니터에서 렌더링 할 때 더블 버퍼링을 사용하는데 이 때 모니터의 주파수에 맞게 렌더링 퍼포먼스를 조절하는 것
더블 버퍼링: 백 버퍼와 프론트 버퍼를 사용해서 다음에 출력될 화면을 백 버퍼에 집어 넣고 화면이 갱신될 때 프론트 버퍼와 백 버퍼를 바꿔치게 해 백 버퍼의 내용을 보여 줌으로써 자연스러운 화면 전환이 일어나게끔 하는 것
티어링 : 더블 버퍼링으로 각 버퍼 간의 전환이 이루어질 때 화면이 섞여 출력되어서 화면이 찢어지는 것처럼 보이는 것