이전에 C#에서 가비지 컬렉션이 어떤 방식으로 메모리를 할당하고 해제 하는지에 대해서 포스팅 하였다.

해당 포스팅은 아래 링크를 참고하자.


C, C++에서 메모리 할당과 해제 원리 : http://hijuworld.tistory.com/28

C#/닷넷 에서 가비지 컬렉션의 메모리 할당 및 해제 기본 원리 : http://hijuworld.tistory.com/32


이번에는 가비지 컬렉션이 동작할때 세대별로 관리를 하는 방식에 대해서 알아보자.

힙영역에 할당된 메모리들은 0세대, 1세대, 2세대 세가지로 구분된다.

가장 처음 할당되는 메모리들은 0세대이며 가비지 컬렉션이 한번이 이루어 질때마다 한세대씩 증가한다.

가비지 컬렉션은 0세대 가비지 컬렉션 부터 발생하며 0세대 가비지 컬렉션은 0세대 메모리들만을 메모리해제 한다. 남은 메모리들은 1세대씩 증가한다.

0세대 가비지 컬렉션이 이루어 졌는데도 메모리가 부족하다 판단되면 1세대 가비지 컬렉션이 발생한다.

그러면 0세대 메모리와 1세대 메모리 모두 사용하지 않는 메모리는 해제된다. 그리고 한세대씩 증가하게 된다.

0세대와 1세대 가비지 컬렉션이 발생하였는데도 메모리가 부족하면 2세대 가비지 컬렉션이 발생한다.


글로 이해하면 어려울 수 있으니 아래 그림을 참고하자.

0세대 가비지 컬렉션의 원리이다.



아래는 1세대와 2세대 가비지 컬렉션 동작 원리이다.



이러한 방식으로 동작하는 이유는 최근 생성된 객체는 금방 사용하지 않을 가능성이 높고 오래된 객체일수록 계속 사용할 가능성이 높은 이유이다.


2세대 가비지 컬렉션은 상당히 큰 오버해드가 될 수 있다.


가비지 컬렉션이 똑똑하기는 하지만 완벽하지는 않다. 항상 주의해서 사용해야 한다.


Google에 C# 메모리라고 검색해도 C#에 메모리에 관한 이슈가 많이 검색이 된다.


한번 프로그램을 다 만들고 나서 이후에 관련 메모리 이슈를 해결하려면 쉽지 않기 때문에 프로그램을 만들면서 서 주의를 해야 한다. 특히나 24시간 돌아가는 프로그램들에 특히 주의가 필요하다.


다음으로 메모리 사이즈가 큰 객체에 대해서는 어떻게 가비지컬렉션이 일어나는지 알아보자.


용량이 큰 객체에 메모리 할당 해제 방식  : http://hijuworld.tistory.com/46

Posted by 꿈만은공돌
,

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


C, C++에서 메모리 할당과 해제 원리 : http://hijuworld.tistory.com/28


하지만 C#과 JAVA 에서는 가비지 컬렉터(garbage collecter)에 의해서 메모리 할당과 메모리 해제가 이루어진다.


사용하지 않는 메모리를 가비지 컬렉션(garbage collection)이 해제 시킨다.


우선 간단하게 메모리를 할당하는 방식에 대해서 알아 보자.




1. C#에서 객체 생성시 메모리 할당 방식

new 키워드를 통해 객체를 생성하게 되면 힙(Heap) 메모리 영역에 객체가 할당된다. C언어와 C++과 다른점은 메모리 첫영역부터 차례대로 할당하게 되고 할당이 가능한 부분의 첫 주소에 포인터로 가르키게 된다. 다음에 또 객체를 생성하면 할당 가능한 메모리의 포인터 영역부터 메모리를 할당하고 다시 해당 포인터는 할당된 사이즈 만큼 증가하게 됩니다.


C, C++과 다르게 이렇게 하면 메모리 할당이 가능한 영역을 찾는 과정이 없기 때문에 속도가 훨씬 빠르다.

아래 그림을 보면 쉽게 이해가 갈것이다.








2. C#에서 Garbage Collector에 의한 메모리 해제 방식

Test a = new TEST();

a = null;

위와 같은 코드를 만나면 처음에 할당한 변수 a가 가지고 있는 객체는 더이상 사용하지 않기 때문에 메모리 해제의 대상이 됩니다.

힙영역에 메모리가 계속 쌓이다 보면 특정 시점에서 Garbage collector에 의해 사용되지 않는 메모리(아래 그림에서 B, D)는 해제하게 된다.

Root Reference 메모리 영역에서 사용하는 메모리 영역을 관리하게 되고(아래 그림의 A와 C) 객체에서 할당한 객체도 존재(아래 그림에서 E)한다. Root Reference를 탐색하여 A와 C를 찾고 다시 A와 C를 검색하여 E를 찾아낸다.

그러면 그외에 메모리 영역인 B와 D는 사용하지 않는 메모리 영역으로보고 메모리를 해제한다.

그리고 남은 A, C, E를 다시 재배치 한다.

그리고 다음 객체를 할당할 메모리의 포인터의 위치도 재배치 한다.




여기까지가 간단하게 설명한 메모리 할당 및 해제 원리이다.

사실 가비지 컬렉션에 방식은 이외에도 상당히 복잡하다.


1. 세대별 가비지 컬렉션 방식 : http://hijuworld.tistory.com/41


2. 용량이 큰 객체에 메모리 할당 해제 방식 : http://hijuworld.tistory.com/46


3. 가비지 컬렉션의 모드에 따른 방식


따라서 이 3가지 방식에 대해서 다음 포스팅에서 설명하겠다.




참고 사이트 및 서적 

- c# GC.Collect() 정리 : http://helloit.tistory.com/40

- 유경상의 닷넷 블로그 : http://www.simpleisbest.net/post/2011/04/01/Review-NET-Garbage-Collection.aspx

- MSDN : https://docs.microsoft.com/en-us/dotnet/standard/garbage-collection/fundamentals

- 뇌를 자극하는 C# 4.0(한빛미디어, 박상현 지음)





Posted by 꿈만은공돌
,