유니티에서 Garbage Collector는 오브젝트로 부터 발생한 사용하지 않는 메모리가 차지하는 공간을 비워서, 사용 가능한 메모리를 확보해 주는 역할을 한다.
GC의 성능
별도로 사용자가 직접 GC를 구현하는 경우를 제외하면, 우리는 유니티에서 제공하는 GC를 사용하게 된다. 직접 GC를 구현하는 것은 매우 어려운 작업이다.
그렇다면, 유니티에서 제공하는 GC의 성능은 어떨까?
결론부터 말한다면
"현재까지의 유니티 GC는 성능이 좋지 않다."
왜 GC의 성능이 좋지 않은가?
stop-the-world
유니티의 GC는 stop- the-world 방식으로 메인 스레드를 멈추고 GC가 실행된다.
모든 작업을 메인 스레드에서 처리해주는 유니티 엔진에서 메인 스레드가 멈춘다는 의미는 게임이 멈춘다는 의미와 같다. 이로 인해서 성능 스파이크가 발생할 수 있다.
GC의 호출 시점
GC는 항상 사용하지 않는 메모리가 발생할 때마다 실행되지 않는다. 현재 사용하는 메모리가 일정 크기를 넘어갈 때, GC가 실행된다.
"여러번에 나누어서 작업을 진행하거나, 그때 그때 발생한 사용하지 않는 메모리를 처리하는 방식이 아니기 때문에, 순간적인 성능 저하가 발생한다."
Incremental GC(점진적 GC)
GC의 실행을 한 프레임 내에 처리하는 것이 아닌, 여러 프레임에 나누어 실행하는 것이다.
나누어서 실행하는 것이기 때문에, 사용되는 성능의 총합은 동일하다. 단지 GC로 인해서 발생하는 스파이크를 개선할 수 있다.
가능한 모든 상황에서 Incremental GC를 사용하는 것을 권장한다.
Edit - ProjectSetting - Player - Use Incremental GC
GC를 직접 호출하기
GC는 직접 실행시켜 줄 수 있다.
System.GC.Collect();
직접 호출해 주는 작업은 신중히 해주어야 한다. 실행하는 시점에 따라서 메모리 공간을 확보할 수 있지만, 사용하지 않는 메모리가 없다면 단순히 성능의 저하만 발생할 수 있다.
개선방안
GC의 호출 시점을 정한다.
언제 호출될지 모르는 GC를 특정 시점에서 직접 실행해준다. 이를 통해서 게임이 진행 중일 때, GC가 호출되지 않도록 예방한다.
"Scene이 변경된 이후에, GC를 호출해 주는 것으로 이전 Scene에서 사용되었던, 메모리 공간을 확보할 수 있다."
주기적인 GC 호출
if (Time.frameCount % 30 == 0)
{
System.GC.Collect();
}
반복적으로 GC가 실행되기 때문에, 평균적인 실행 속도가 느려지는 대신에, 사용하지 않는 메모리를 주기적으로 처리해서, GC로 인해서 게임이 멈추지 않는 결과를 기대할 수 있다.
'유니티 > 개념 정리' 카테고리의 다른 글
| Call Back (0) | 2024.12.02 |
|---|---|
| 초기화가 호출되었는가? (0) | 2024.11.28 |
| 대리자 활용 (0) | 2024.11.19 |
| IEnumerable과 IEnumerator (0) | 2024.11.18 |
| Predicate(술어) (0) | 2024.11.11 |