EveryDay.DevUp

[Unity] GC ( 가비지 컬렉터 ) 본문

Unity

[Unity] GC ( 가비지 컬렉터 )

EveryDay.DevUp 2020. 4. 30. 14:04

 

 

Unity의 가비지 컬렉터에 대해 설명하고자 한다.

C# 은 기본적으로 메모리를 자동으로 관리 해줌

* C# 메모리 : https://everyday-devup.tistory.com/10

[Unity] C#에서의 메모리

* Heap ▶ 위치가 정해져 있지 않고 용량이 큰 대신 느림 ▶ 참조 타입 ( ex class, string, object ) ▶ 변수 선언 시 데이터가 저장되어있는 메모리를 가리키게 됨 * Stack ▶ 정렬되어 있고 빠르지만 사용에..

everyday-devup.tistory.com

● Stack의 메모리 관리 

▶ Stack은 Last In First Out 구조로 순서대로 값 타입의 변수가 설정되고, 사용이 종료되는 시점에 메모리가 반환 됨 

▶ 사용이 종료되는 시점에 메모리가 반환 되기 때문에 관리가 어렵지 않음

 

public class StackMemory {
    void Main(){
    	int result = Sum();
    }

    public int Sum() {
    	int a = 1;
        int b = 2;
        
        return a + b;
    }
}

 

 

 

● Heap 메모리 관리

Unity에서의 Heap 메모리 사용은 2가지로 나누어짐

▶ Native Heap : C++로 작성된 유니티 엔진에서 사용하는 메모리로, Texture, Asset, Mesh 와 같은 것을 담고 있음

+ Unity Engine에서 Scene 전환이 발생할 때에 위의 요소들이 사용되지 않으면 메모리를 해제하는 동작을 함

+ DontDestroyOnLoad 를 통해 Scene전환 시에도 남아 있는 GameObject는 해제되지 않음

( 남아 있는 GameObject에 Script가 사라진 Scene에 있는 어셋 ( Audio, Texture 등 )을 참조 하고 있을 때에도 메모리가 해제 되지 않음 )

▶ Managed Heap : Mono에서 관리하는 메모리로 Script에서 할당한 class, string 과 같은 요소 들을 담고 있음

+ 가비지 컬렉션은 Managed Heap에서 수행

▣ GC ( 가비지 컬렉션 )의 동작 원리

1. C# 메모리 할당

- C#은 선형적인 Heap 메모리를 가지고 있으며, 메모리 할당을 위한 포인터 만을 가지고 있음

- 메모리 할당이 필요한 경우 현재 필요한 메모리 크기만큼 증가시키고 0세대값으로 설정. 포인터는 증가된 크기만큼 이동 시킴 

- 할당을 위한 충분한 메모리가 없을 경우, GC가 호출되고 GC가 호출됨에도 충분한 메모리가 없을 경우에는 Heap메모리가 확장 됨. 대부분의 Unity 플램폼의 경우 힙의 크기를 2배로 늘림

- 만일 사용 가능한 메모리 공간이 부족해지는 경우 앱이 강제 종료 됨

 

 

2. C# 메모리 해제

- GC 는 시스템의 실제 메모리가 부족 하거나, Managed Heap에 할당된 개체에 사용되는 메모리가 허용되는 임계 값을 넘었을 때, GC.Collect 메서드가 호출 될 때 발생

- GC는 힙 메모리 상에서 사용 중인 객체들의 참조 그래프를 가지고 있으며, 이를 통해 현재 사용 중이지 않은 메모리를 해제하고 사용 중인 메모리는 재배치를 하게 됨

- 참조 그래프의 Root는 Stack에 있는 로벌 켠수, 정적 빌드, 전역 변수 등이 되고, 하위는 객체 간의 참조가 될 수 있음

 

Root가 참조하는 A,C 그리고 A가 참조하는 D가 GC 이후에도 남아 있음을 확인할 수 있음

 

- 세대별 가비지 컬렉션

: 최근에 할당된 메모리부터 GC가 한번 불릴 때마다 살아 남은 메모리까지 0 ~ 2 세대까지 분리

: 최근에 생성될 객체일 수록 메모리 해제가 발생할 가능성이 높기 때문에 0 세대의 메모리 부터 관리

: 0세대의 GC에서 남아 있는 메모리는 1세대로 변경 됨, 1세대의 GC가 발생하고 남이 있는 1세대는 2세대로 변경 됨

: 0 세대의 메모리 관리 후에도 메모리가 부족해지면 1세대 -> 2세대 순으로 메모리를 관리

 

 

3. SOH, LOH

- C# 에서는 85KB 를 기준으로 SOH( Small Object Heap ), LOH( Large Object Heap )으로 나눔

- LOH 는 SOH와 달리 할당과 동시에 2세대로 시작, LOH는 메모리 재배치 시 오버헤드가 크기 때문에 재배치를 하지 않음

 

# 참고 자료

- MSDN : https://docs.microsoft.com/ko-kr/dotnet/standard/garbage-collection/

 

.NET 가비지 수집

 

docs.microsoft.com

- Unity : https://docs.unity3d.com/kr/current/Manual/UnderstandingAutomaticMemoryManagement.html

자동 메모리 관리 이해 - Unity 매뉴얼

오브젝트나 문자열, 배열을 생성한 이후 저장하려면 메모리 공간이 필요합니다. 필요한 공간은 heap이라고 하는 중심 풀에서 할당됩니다. 메모리 공간을 할당받은 항목이 더 이상 사용되지 않게 되면 차지하던 메모리를 회수하여 다른 항목을 저장하는 데 사용할 수 있습니다. 이전에는 프로그래머가 적절한 함수 호출을 통해 명시적으로 힙 메모리 블록을 할당하고 회수해야 했습니다. 하지만 최근에는 Unity Mono 엔진과 같은 런타임 시스템이 자동으로 메모리 관리를

docs.unity3d.com

- http://www.simpleisbest.net/post/2011/04/01/Review-NET-Garbage-Collection.aspx

SimpleIsBest.NET | 닷넷 가비지 컬렉션 다시 보기 - Part I

CLR(Common Language Runtime)의 가비지 컬렉션(Garbage Collection)의 작동 원리를 파악한다는 것은 매우 중요한 일입니다. 가비지 컬렉션의 작동 방식을 충분히 파악해야만 어플리케이션의 메모리 문제를 ��

www.simpleisbest.net

- https://hijuworld.tistory.com/32?category=817153

C#/.NET 가비지 컬렉션의 메모리 할당 및 해제 기본 원리 (Garbage collection)

C와 C++에서 직접 new 연산자와 malloc 함수를 이용해서 힙(heap)영역에 동적 메모리 할당을 받고 delete 연산자와 free 함수를 이용해서 동적 메모리를 해제하게 된다. C, C++에서 메모리 할당과 해제 원��

hijuworld.tistory.com

- http://ehpub.co.kr/56-%EB%A7%A4%EA%B0%9C%EB%B3%80%EC%88%98-%EC%A0%84%EB%8B%AC-%EC%9B%90%EB%A6%AC/

56. 매개변수 전달 원리 – 언제나 휴일

이번에는 함수 호출에서 종료까지 수행 원리를 간단히 알아볼게요. 함수를 호출하면 해당 함수의 지역 변수를 위한 메모리를 스택에 할당해요. 그리고 피호출 함수의 동작이 끝나면 호출한 함수의 다음 부분을 수행하는 것이 기본 동작이죠. main 함수가 시작하면 main함수의 지역 변수를 위한 메모리를 스택에 할당해요. 그리고 Add 함수를 호출하면 입력 인자를 복사한 후에 Add 함수의 지역 변수를 할당한 후에 복사한 값으로 초기화를 수행하죠. 그리고 함수의

ehpub.co.kr