유니티에서 가비지 컬랙션

Lee Hyeuk Jin·2024년 1월 10일

개념공부 및 실습

목록 보기
9/12

가비지 컬랙션(GC)

메모리 관리를 위해 사용되며, 더 이상 사용되지 않는 메모리를 해체하여 성능을 최적화한다.
유니티에서 GC는 Mono런타임에 의해 관리되며, C# 스크립트에서 사용되는 객체들의 메모리를 관리한다.

가비지 컬랙션 발생 순서

1. 메모리 할당
	- 새로운 객체나 데이터 구조가 메모리에 할당된다.
2. 참조 계수 증가
	- 해당 객체애 대한 참조가 증가한다.
	- 참조 계수 : 객체가 몇번 참조되고 있는지를 나타내는 카운트이다. 객체가 최초로 생성되면 참조 계수가 1이다.
     			 참조 계수가 0이 되면 해당 객체는 더이상 사용되지 않은 것으로 판단되고, 메모리에서 해제될 수 있다.
3. 사용 및 참조 해제
	- 객체가 사용되고 필요 없어질 때, 해당 객체 대한 참조를 해제한다.
4. 가바지 컬렉션 트리거
5. 표시
	- 가비지 컬렉션이 필요한 메모리 블록을 식별하는 과정이다. 이 과정에서 어떤 객체가 여전히 유효한지 검사한다.
6. 수거
	- 표시되지 않거나 참조가0인 객체를 메모리에서 해제한다.
7. 세대 이동
	- 가비지 컬렉션에서 남아 있는 객체가 다음 세대로 이동한다.

가비지 컬렉션 발생 시 단점

1. 일시적인 중단
	 - 가비지 컬렉션 실행 중에 프로그램이 일시적으로 중단될 수 있음
2. CPU 소모
	- 가비지 컬렉션이 실행될 때 CPU자원을 소모하기 때문에 빈번한 가비지 컬렉션은 성능에 영향을 끼칠 수 있다.
3. 메모리 사용 지연
	- 가비지 컬렉션이 진행되는 동안에 메모리를 해제하는 시간이 오래 걸릴 수 있어 메모리 사용량이 높게 측정될 수 있음
4. 메모리 누수
	- 부정확하게 사용할 경우 메모리 누수가 발생할 수 있으며, 참조를 적절하게 관리하지 못하면 객체 해제를 못할 수도 있다.

가비지 컬렉션 빈도를 줄이는 법

1. 객체 풀링 사용
	- 빈번한 객체 생성 과 제거를 피하기 위해 객체 폴링을 사용한다.
2. 로컬 변수 사용
	- 로컬 변수를 활용하여 메서드 내에서 사용되는 객체의 범위를 최소화 한다.
3. 불필요한 객체 생성 자제
4. 약한 참조 활용
	- 약한 참조를 하여 컬렉션의 대상이되는 객체의 수를 줄인다.
5. 명시적인 가비지 컬렉션 호출 최소화

가비지 컬렉션이 많이 발생하는 예제 코드

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Test : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        
    }

    // Update is called once per frame
    void Update()
    {
        // 매 프레임마다 새로운 벡터를 생성하고 사용
        Vector3 newPosition = new Vector3(1.0f, 2.0f, 3.0f);
        transform.position = newPosition;

        string result = "Hello " + "World";
        Debug.Log(result);

        // 리스트에 계속해서 새로운 객체를 추가하고 사용
        for (int i = 0; i < 100; i++)
        {
            var tempList = new System.Collections.Generic.List<int>();
            tempList.Add(i);
            // tempList를 사용하지 않고 버림, 그러나 가비지 컬렉션의 대상이 됨
        }
    }
}

해당 코드에서 가비지콜렉션 빈도를 줄인 코드

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Test : MonoBehaviour
{
    private Vector3 newPosition;

    // Start is called before the first frame update
    void Start()
    {
        newPosition = new Vector3(); // 초기화
    }

    // Update is called once per frame
    void Update()
    {
        // 매 프레임마다 새로운 벡터를 재사용
        newPosition.Set(1.0f, 2.0f, 3.0f);
        transform.position = newPosition;

        // 문자열 연산을 사용하지 않고 이미 존재하는 문자열을 출력
        Debug.Log("Hello World");

        // 리스트를 재활용하고 불필요한 객체 생성을 방지
        var tempList = new System.Collections.Generic.List<int>();
        tempList.Clear(); // 리스트를 초기화하고 재활용
        for (int i = 0; i < 100; i++)
        {
            tempList.Add(i);
            // tempList를 사용하지 않고 버리지 않음
        }
    }
}
profile
유니티 C# 학습자

0개의 댓글