GC.Collect()메서드의 효용성

현재 주소 복사
트랙백 주소 복사
방실이님의 글 (9/15/2006 11:12:01 AM) Viewing : 3110

GC.Collect()

이런 저런 게시판에 글을 보다 보면.
메모리 문제때문에 고생 하는 개발자들을 종종..볼수 있다.

가비지컬렉터에 대한 이해가 부족한 탓일까.
GC.Collect()를 남발 하고 있어..답변을 달때 항상..Collect()메소드를 호출 하지 말라고 하곤 한다.

왜 그런지..간단히 소개를 해 볼까 한다..
사실..
가비지 컬렉터 메커니즘에 대해서 이해 하고 있다면 아래 예제를 보지 않아도...이해한다..ㅡ.ㅡ;
당연한 얘기인가..@.@

먼저 아래 예제를 이해 하기 위해서는 기본적은 가비지 컬렉터 메커니즘에 대해서 알아야 한다.
세대(Generation) 메커니즘을 알아야 하는데.
가비지 컬렉터는 이 메커니즘(이게 전부는 아니다..)에 의해..메모리를 회수 하게 된다.
세대는 0세대 1세대 2세대가 있으며 0세대가 최근에 생긴 데이터이며 가장 빨리 회수될수 있는 가능성을 가진 개체이다.
2세대는 가장 오래전에 생성되어 현재 사용되고 있는(혹은 최근에 사용되지 않았지만 아직 수집되지 않은) 개체들이 위치한다.
당연한 얘기가 되겠지만 메모리를 회수 하기 위해 컬렉터는 0세대를 검사하고 종료 하는게 가장 빠르다..
1세대와 2세대까지 검사하게 된다면 당연히 느려질 것이다.

이 말이 이해 안가는가??

더 자세한 사항은 유경상님의 블로그를 참조 하기 바란다..아주..대단하신 분이다...어투를 약간 흉내를 내자면..숏잡고 봐라..ㅡ.ㅡ;;;

일단 예제 나간다.

[소스코드]

using System;
using System.Collections.Generic;
using System.Text;

namespace ConsoleApplication3
{
    class Program
    {
        static void Main(string[] args)
        {
            object test = "TEST";
            Console.WriteLine("MaxGen : "+GC.MaxGeneration.ToString());
            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.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());
        }
    }
}

먼저 프라퍼티와 메소드를 소개 하겠다.
MSDN보면 다 나와 있지만..ㅡ.ㅡ;


GC.MaxGeneration 이라는 프라퍼티는 항상 2를 반환한다.
앞서 말했듯이 0세대 1세대 2세대까지 밖에 없기 때문이다..

GC.GetGeneration(object obj) 메서드는 obj개체의 현재 세대를 반환한다.
기본적으로 방금 생성한 개체는 무조껀 0세대이다.

GC.CollectionCount(int generationCount) 메서드는 파라메터로 받은 세대의 수집 횟수이다.
Collect메서드를 호출 할때마다 혹은 가비지 컬렉터에 의해 호출 될때마다 1씩 증가한다.

GC.Collect() 메서드는 모든 세대(0세대~2세대까지)를 수집한다..
GC.Collect(int generationCount) 메서드는 파라메터로 받은 세대를 수집한다.

일단 이것만 봐도 Collect()라는 메서드는 문제가 있어 보인다..아직 이해가 안가나??
위 유경상님 블로그를 다시 봐라..ㅡ.ㅡ;

Collect()메서드를 호출 할때마다 승급이 일어난다..
0세대의 개체가 1세대로 1세대의 개체가 2세대로..2세대의 개체는???
할당된 메모리가 확장된다..

물론 가비지로 판단이 되지 않는 개체의 경우만 그렇다는 얘기다.
위 예제의 test라는 개체는 사용되고 있다고 판단하여
Collect()메서드가 호출 될때마다 계속 승급이 되어 종착에는 2세대가 되었다.

게다가 마지막의 3라인의 출력결과를 보면..
2세대 1세대 0세대가 모두 3번씩 수집되었다.

지금 예에서는 개체가 1개이지만 실제 응용 프로그램에서는 수십 수백개가 될수 있다.
이것을들 특정때마다 수집을 하게 되면 이런 승급 현상때문에 컬렉터가 하는 일이 더 많아진다.

가장 좋은 현상은 작은 공간을 자주 컬렉터가 수집하여 메모리를 회수 하는 것이다.
그러나 이런 수동적은 Collect()메서드의 호출은 이에 반하게 된다.

이제..대충..이해가 되는가??

왜 Collect()메서드를 쓰면..손해가 나는지???
덧 붙이지만..항상 손해가 나는것은 아니다..ㅡ.ㅡ;
Collect()메서드로 수집을 해야 할때도 있을지도 모른다..
과연 그럴때가 있을지??

Dispose()만 잘 해 주어도 훌륭하게 동작한다..
믿고 써보자...



구현환경
.NET Framework 2.0
Microsoft Visual Studio.NET 2005
Microsoft Windows XP SP2



마지막 업데이트 : (9/15/2006 11:12:01 AM)

TAG : 없음



Trackback 보기 (0)
댓글 보기 (0)
댓글 쓰기



<< < 1 2 3 > >>