C #의 GC.Collect 메서드에 대한 내 2 센트

GC.Collect () 메서드는 오랫동안 .Net 개발자들 사이에서 인기가있었습니다. 그러나 실제로 어떻게 작동하는지 또는 전화가 필요한지 아는 사람은 거의 없습니다.

CLR (공용 언어 런타임)은 애플리케이션에서 사용하는 리소스를 정리하는 메커니즘으로 가비지 수집을 채택합니다. .Net에서 개체를 만들면 관리되는 힙에 저장되며 사용이 끝나면 정리에 대해 걱정할 필요가 없습니다. 런타임이 자동으로 처리합니다.

CLR은 관리되는 힙을 여러 세대로 구성합니다. 관리되는 힙이 구성되는 세 세대는 0 세대, 1 세대 및 2 세대입니다. GC는 관리 대상 개체가 차지하는 메모리를 재 확보하는 데 능숙합니다. 그러나 애플리케이션의 성능을 향상시키기 위해 더 빠른 가비지 콜렉션을 용이하게하려면 특정 지침을 따라야합니다.

GC.Collect () 메서드를 사용해야합니까?

먼저 애플리케이션 코드에서 GC.Collect를 호출해야합니까? 대부분의 경우 대답은 아니오입니다. 이제이 메서드의 기능과 대부분의 경우이 메서드를 호출하지 않아야하는 이유를 설명하겠습니다.

GC.Collect () 메서드를 호출하면 런타임이 스택 워크를 수행하여 도달 가능한 객체와 도달 할 수없는 객체를 결정합니다. 또한 응용 프로그램의 기본 스레드 (및 생성 한 모든 자식 스레드)를 고정합니다. 즉, GC.Collect () 메서드가 호출되면 런타임은 모든 세대의 차단 가비지 수집을 수행합니다.

나는 그것을 사용하는 특별한 이유가 없다면 항상 GC.Collect ()를 사용하지 않는 것을 선호합니다. GC는 일반적으로 Mark 및 Sweep 단계와 압축 단계로 구성됩니다. 런타임에서 GC를 수행하는 데 소요되는 시간은 병목 현상이 될 수 있으므로 매우 드물게 사용하고 실제로 필요한 경우에만 사용하십시오. Rico Mariani는 "일부 반복되지 않는 이벤트가 방금 발생했고이 이벤트로 인해 많은 오래된 개체가 죽을 가능성이 높은 경우 GC.Collect () 호출을 고려하십시오."

GC.Collect () 메서드 사용

코드에서 GC.Collect () 메서드를 호출하는 방법은 다음과 같습니다.

GC.Collect();

특정 세대와 관련된 개체를 수집 할 수도 있습니다.

GC.Collect() – 0, 1, 2 세대에 존재하는 물건을 수집하는 데 사용

GC.Collect(0) – 0 세대에 존재하는 개체를 수집하는 데 사용

GC.Collect(1) – 0 세대와

GC.Collect () 메서드를 호출하여 해제 된 메모리 양을 확인할 수도 있습니다. 이렇게하려면 아래 코드 조각에 표시된 System.GC.GetTotalMemory () 메서드를 활용할 수 있습니다.

//Write code to create some large objects here

Console.WriteLine("Total available memory before collection: {0:N0}", System.GC.GetTotalMemory(false));

System.GC.Collect();

Console.WriteLine("Total available memory collection: {0:N0}", System.GC.GetTotalMemory(true));

GC.GetGeneration () 메서드를 사용하여 객체가 속한 세대를 알 수 있습니다. 아래의 코드 목록을 참조하십시오.

static void Main(string[] args)

       {

           List obj = new List() { "Joydip", "Steve" };

           Console.WriteLine(System.GC.GetGeneration(obj));

           System.GC.Collect();

           Console.WriteLine(System.GC.GetGeneration(obj));

           System.GC.Collect();

           Console.WriteLine(System.GC.GetGeneration(obj));

           Console.Read();

       }

위의 프로그램을 실행하면 콘솔 창에 출력되는 내용이 있습니다.

0

1

2

보시다시피 GC.Collect () 메서드를 호출 할 때마다 "obj"객체가 다음 상위 세대로 승격됩니다. 이는 객체 "obj"가 두 경우 각각에서 가비지 수집에서 살아 남기 때문입니다. 즉, GC.Collect () 메서드에 대한 두 번의 호출에서 회수되지 않기 때문입니다.

GC.Collect () 메서드를 사용하여 세 세대 모두 또는 특정 세대로 가비지 수집을 강제 할 수 있습니다. GC.Collect () 메서드는 오버로드됩니다. 매개 변수없이 또는 수집 할 가비지 수집기에 세대 번호를 전달하여 호출 할 수도 있습니다.

종료자가있는 객체 (및 SuppressFinalize 메서드를 호출하지 않은 경우)는 GC.Collect () 메서드를 호출 할 때 수집되지 않습니다. 오히려 이러한 개체는 종료 대기열에 배치됩니다. 이러한 객체도 수집하려면 다음 GC주기가 실행될 때 해당 객체가 정리되도록 GC.WaitForPendingFinalizers () 메서드를 호출해야합니다. 본질적으로 종료자가 구현 된 객체가 차지하는 메모리를 회수하려면 가비지 수집기가 실행될 때 첫 번째 패스에서 회수되는 것이 아니라 종료 대기열에 배치되기 때문에 두 번의 패스가 필요합니다.