가비지 컬렉션

2015. 7. 28. 04:55프로그래밍/C#

728x90
728x90

정의

C#은 CLR이 자동 메모리 관리 기능(Automatic Memory Management) 기능을 제공한다. 이 자동 메모리 관리 기능의 중심이 가비지 컬렉션(Garbage Collection)이다. 


프로그래머로 하여금 무한한 메모리를 사용할 수 있도록 코드를 작성하게 할 수 있다.
가비지 컬렉션을 담당하는 것이 가비지 컬렉터(Garbage Collector)라 한다.
가비지 컬렉터는 객체 중에 사용하는 것과 사용하지 않는 것을 분리하여 쓰레기들만 조용히 수거한다.
가비지 컬렉터도 CPU와 메모리 같은 컴퓨팅 자원을 소모하므로 이 자원을 최소한으로 사용하게 하는 것이 프로그램의 성능을 향상시킬 수 있다.
 
가비지 컬렉터가 지우지 못하는 메모리
C#에서 작성된 모든 코드는 관리형 코드(Managed Code)에 속한다.
CLR은 실행되는 코드에 메모리 할당, 보안, 스레딩 등을 하면서 이를 치우는 업무(가비지 컬렉션)을 수행한다.

C#에서 비관리형 코드(Unmanaged Code)를 작성할 수 있다.
unsafe 키워드를 사용하면 되며 CLR이 제공하는 서비스를 받을 수 없다.(가비지 컬렉션도 포함)

가비지 컬렉션 과정



세대관리



2세대로 옮겨간 객체들은 더 이상 다른 곳으로 옮겨지지 않고 그 곳에 정착한다.

2세대가 포화되어 2세대 가비지 컬렉션이 수행되면, 가비지 컬렉터는 동시에
1세대와 0세대에 대해서도 컬렉션을 수행한다.
이것을 전체 가비지 컬렉션 (Full Garbage Collection)이라 부른다.

가비지 컬렉션 주의사항
많은 객체 할당을 자제한다.
CLR의 객체 할당 속도가 빠르긴 하지만 너무 많은 수의 객체는 관리되는 힙의 각 세대에 대해 메모리 포화를 초래한다. 빈번한 가비지 컬렉션을 부르면 프로그램의 성능이 저하될 수 있다.

너무 큰 객체를 만들지 않는다.
CLR은 보통 크기의 객체를 할당하는 힙과는 별도로 85KB 이상의 
대형 객체를 할당하기 위한 대형 객체 힙(LOH:Large Object Heap)이 있다. 
CLR은 LOH를 메모리 공간 효율이 크게 떨어지며 2세대 힙으로 간주하여 
LOH의 객체가 수거되려면 2세대 가비지 컬렉션을 수행하는데, 이는 응용 프로그램의 정지를 초래한다.

복잡한 참조 관계를 만들지 않는다.
가비지 컬렉터는 가비지 컬렉션 후에 살아남는 객체의 세대를 옮기기 위한 메모리 복사를 수행한다.
참조관계가 복잡할 경우 단순 메모리 복사에 그치지 않고 객체를 구성하는 참조 관계를 조사해 일일이 메모리 주소 전부를 수정하여 오버헤드가 심해진다.

많은 루트를 만들지 않는다.
루트 목록이 작아지면 그만큼 가비지 컬렉터가 검사를 수행하는 횟수가 줄어들기 때문에 
더 빨리 가비지 컬렉션을 끝낼 수 있습니다.

정리
가비지 컬렉션으로 인한 성능 저하를 막기 위한 지침을 따르지 않는다고 해서 개발 중인 
프로그램에서 갑자기 문제가 튀어나오거나 하지는 않는다.
잘못된 코딩 습관 몇 가지가 누적되다 보면 언제가 골치 아픈 문제가 될 수 있으니 
이러한 지침들을 지식에서 습관으로 바꾸는 것이 좋다.

예제

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
using System;
using System.Collections.Generic;
using System.Text;
 
namespace ConsoleApplication3
{
    class Program
    {
        static void Main(string[] args)
        {
            
            object test = "TEST";
            // 최대 세대 수이므로 2를 반환한다.
            Console.WriteLine("MaxGen : " + GC.MaxGeneration.ToString());
            // test의 현재 세대를 반환한다. 일단 0세대
            Console.WriteLine("Current Object Gen : " + GC.GetGeneration(test));
 
            // CollectionCount(int generationCount)로 받은 세대의 수집 횟수를 의미한다,
            Console.WriteLine("Current GenCount : " + GC.CollectionCount(0).ToString());
            Console.WriteLine("Current GenCount : " + GC.CollectionCount(1).ToString());
            Console.WriteLine("Current GenCount : " + GC.CollectionCount(2).ToString());
 
 
            //GC.Collect() 메서드는 모든 세대(0세대~2세대까지)를 수집한다..
            //GC.Collect(int generationCount) 메서드는 파라메터로 받은 세대를 수집한다.
            GC.Collect();
            Console.WriteLine("Current Object Gen : " + GC.GetGeneration(test));
 
            Console.WriteLine("Current GenCount : " + GC.CollectionCount(0).ToString());
            Console.WriteLine("Current GenCount : " + GC.CollectionCount(1).ToString());
            Console.WriteLine("Current GenCount : " + GC.CollectionCount(2).ToString());
 
            GC.Collect();
            Console.WriteLine("Current Object Gen : " + GC.GetGeneration(test));
 
            Console.WriteLine("Current GenCount : " + GC.CollectionCount(0).ToString());
            Console.WriteLine("Current GenCount : " + GC.CollectionCount(1).ToString());
            Console.WriteLine("Current GenCount : " + GC.CollectionCount(2).ToString());
 
            GC.Collect();
            Console.WriteLine("Current Object Gen : " + GC.GetGeneration(test));
 
            Console.WriteLine("Current GenCount : " + GC.CollectionCount(0).ToString());
            Console.WriteLine("Current GenCount : " + GC.CollectionCount(1).ToString());
            Console.WriteLine("Current GenCount : " + GC.CollectionCount(2).ToString());
 
            // 가비지 컬렌션이 객체를 해제할때까지 대기 상태로 유지
            GC.WaitForPendingFinalizers();
        }
    }
}
cs




728x90
반응형

'프로그래밍 > C#' 카테고리의 다른 글

[.NET, C#] 비동기 네트워크 API  (0) 2016.02.14
직렬화  (0) 2015.08.03
Delegate  (2) 2015.08.03
데이터 보관하기  (0) 2015.08.03
C#이란?  (0) 2015.08.03
ref와 out 차이  (0) 2015.06.23
처음만드는 C# 기초 입출력  (0) 2015.06.22