내일배움캠프/TIL

[내배캠][Unity6기][TIL] 24.10.14 특강 - 메모리

binary는 호남선 2024. 10. 15. 20:51

메모리 구조

Code
Data
Heap
Stack

Code : 작성된 코드

Data : static, const 키워드 붙은 변수, 프로그램 시작 시 메모리에 올라가고 종료 시 제거됨, 전역 데이터 저장

Heap : 참조 타입 객체 저장, new로 생성하고 GC로 삭제(참조가 없으면 삭제 대상이 됨)

Stack : local, 매개 변수 저장, 함수 시작 시 메모리에 올라가고 return되면 삭제

Class와 Struct 비교

Class Struct
참조 형식 값 형식
주소는 stack에 데이터는 heap에 할당 주소와 데이터 모두 stack에 할당
여러 곳에서 참조하기 용이함 stack에 있으므로 상대적으로 접근 빠름
큰 데이터 집합 장기적 사용 필요 시 사용 작은 데이터 집합 빠르게 접근 시 사용
Component, GameObject… Vector
생성(new, Unity에서는 Scene에 존재 or Instantiate) 삭제(GC) 시 메모리 파편화 문제 발생 stack에 있으므로 함수 종료 시 자동 삭제

주소 값 분석

struct MyStruct
{
    public int Value;
}
class MyClass
{
    public int Value;
}
internal class Program
{
    static void Main(string[] args)
    {
        MyStruct struct1 = new MyStruct();
        struct1.Value = 10;

        MyStruct struct2 = struct1; // struct2는 struct1의 값 복사

        struct2.Value = 20;

        Console.WriteLine(struct1.Value); // 출력 결과: 10

        /* 분석 */
        /*
            struct1
            값 : 10
            주소 : 0x0000005E0497EB08
            struct2
            값 : 20
            주소 : 0x0000005E0497EB00
        */

        MyClass obj1 = new MyClass();
        obj1.Value = 10;

        MyClass obj2 = obj1; // obj2는 obj1과 동일한 객체를 참조

        obj2.Value = 20;

        Console.WriteLine(obj1.Value); // 출력 결과: 20

        /* 분석 */
        /*
            obj1
            값 : 0x000001E40017A410(스택)
            주소 : 0x000000E2EC97E8E8
            obj2
            값 : 0x000001E40017A410(스택)
            주소 : 0x000000E2EC97E8E0

            동일한 힙 주소를 가리킴, 저장된 값이 같으므로(가리키는 주소가 같으므로)
            obj.Value 저장 주소 0x000001E40017A418(힙)
        */
    }
}

Object Pooling

  • 이미 생성해서 사용한 인스턴스를 삭제하지 않고 비활성화했다가 재사용하거나 미리 사용량 예측하여 필요한 인스턴스 만들고 재사용
  • 인스턴스 생성(new, Unity에서는 Scene에 배치 or Instantiate)과 파괴 Destroy(메모리 해제 X, 참조를 끊음)에 드는 리소스를 줄이고 메모리 파편화 방지 위해 사용
  • 아래와 같은 코드는 매 업데이트 주기마다 몬스터 객체를 생성하고 삭제하게 되므로 리소스 낭비, 횟수가 많은 반복문이나 업데이트 함수에서 객체 생성하지 않도록 주의
  • 많은 오브젝트 생성 및 삭제 필요 시 오브젝트 풀링 사용 고려하기
void Update()
{
		Monster mon = new Monster();
}

String

  • 문자열은 불변의 객체, +=로 변경을 시도하면 새로운 메모리 할당하여 새로운 문자열 생성
  • 잦은 문자열 변경 연산은 리소스 낭비
  • 문자열 보간, StringFormat, StringBuilder 사용 권장