[.net] GC.Collect ()를 사용하면 무엇이 그렇게 잘못 되었습니까?

이 기능을 사용하는 것의 심각한 의미를 이해하고 있지만 (적어도 그게 제 생각입니다) 존경하는 프로그래머가 사용하지 않는 것 중 하나가되는 이유를 알지 못합니다. 그것은 무엇을위한 것입니다.

사용자가 수행하는 작업에 따라 메모리 사용량이 크게 달라지는 애플리케이션을 개발하고 있다고 가정 해 보겠습니다. 응용 프로그램 수명주기는 편집과 실시간 처리의 두 가지 주요 단계로 나눌 수 있습니다. 편집 단계에서 수십억 또는 수조 개의 개체가 만들어 졌다고 가정합니다. 일부는 작지만 일부는 그렇지 않으며 일부는 종료자를 가질 수 있고 일부는 그렇지 않을 수 있으며 수명이 매우 몇 밀리 초에서 긴 시간까지 다양하다고 가정합니다. 다음으로 사용자는 실시간 단계로 전환하기로 결정합니다. 이 시점에서 성능이 근본적인 역할을하고 프로그램의 흐름을 조금만 변경해도 치명적인 결과를 초래할 수 있다고 가정합니다. 그런 다음 개체 풀 등을 사용하여 개체 생성을 가능한 최소한으로 줄 였지만 GC가 예기치 않게 소리를 내며 모든 것을 버리고 누군가가 죽습니다.

질문 :이 경우 두 번째 단계에 들어가기 전에 GC.Collect ()를 호출하는 것이 현명하지 않습니까?

결국,이 두 단계는 서로 시간이 겹치지 않으며 GC가 수집 할 수있는 모든 최적화 및 통계는 여기서 거의 사용되지 않습니다.

참고 : 여러분 중 일부가 지적했듯이 .NET은 이와 같은 응용 프로그램에 가장 적합한 플랫폼이 아닐 수 있지만이 질문의 범위를 벗어납니다. 의도는 GC.Collect () 호출이 애플리케이션의 전반적인 동작 / 성능을 향상시킬 수 있는지 여부를 명확히하는 것입니다. 우리 모두는 당신이 그런 일을 할 상황이 극히 드물다는 데 동의하지만 다시 한번 GC는 추측을 시도하고 대부분의 경우 완벽하게 잘 수행하지만 여전히 추측에 관한 것입니다.

감사.



답변

Rico의 블로그에서 …

규칙 # 1

하지마.

이것은 정말로 가장 중요한 규칙입니다. GC.Collect ()의 대부분의 사용은 나쁜 생각이라고 말하는 것이 타당합니다. 그리고 여기에서 모든 것을 반복하지는 않겠습니다. 그럼 다음으로 넘어 갑시다 …

규칙 # 2

반복되지 않는 이벤트가 방금 발생했고이 이벤트로 인해 많은 오래된 객체가 죽을 가능성이 높은 경우 GC.Collect () 호출을 고려하십시오.

이에 대한 고전적인 예는 클라이언트 애플리케이션을 작성하고 관련 데이터가 많은 매우 크고 복잡한 양식을 표시하는 경우입니다. 사용자가이 양식과 상호 작용하여 잠재적으로 XML 문서 나 한두 개의 큰 데이터 세트 같은 큰 개체를 만들 수 있습니다. 양식이 닫히면 이러한 객체는 죽어서 GC.Collect ()는 객체와 관련된 메모리를 회수합니다.

따라서이 상황이 규칙 # 2에 해당 할 수있는 것처럼 들립니다. 오래된 물체가 많이 죽는 순간이 있고 반복적이지 않다는 것을 알고 있습니다. 그러나 Rico의 이별의 말을 잊지 마십시오.

규칙 # 1은 강력한 증거없이 규칙 # 2보다 우선해야합니다.

측정, 측정, 측정.


답변

프로덕션 코드에서 GC.Collect ()를 호출하면 기본적으로 GC 작성자보다 더 많이 알고 있다고 선언하는 것입니다. 그럴 수도 있습니다. 그러나 일반적으로 그렇지 않으므로 강력히 권장하지 않습니다.


답변

그렇다면 .NET에서 MS Word 또는 MS Excel과 같은 COM 개체를 사용할 때는 어떻습니까? GC.CollectCOM 개체를 해제 한 후 호출하지 않고 Word 또는 Excel 응용 프로그램 인스턴스가 여전히 존재하는 것을 발견했습니다.

실제로 우리가 사용하는 코드는 다음과 같습니다.

Utils.ReleaseCOMObject(objExcel)

' Call the Garbage Collector twice. The GC needs to be called twice in order to get the
' Finalizers called - the first time in, it simply makes a list of what is to be finalized,
' the second time in, it actually does the finalizing. Only then will the object do its 
' automatic ReleaseComObject. Note: Calling the GC is a time-consuming process, 
' but one that may be necessary when automating Excel because it is the only way to 
' release all the Excel COM objects referenced indirectly.
' Ref: http://www.informit.com/articles/article.aspx?p=1346865&seqNum=5
' Ref: http://support.microsoft.com/default.aspx?scid=KB;EN-US;q317109
GC.Collect()
GC.WaitForPendingFinalizers()
GC.Collect()
GC.WaitForPendingFinalizers()

그렇다면 가비지 수집기를 잘못 사용하는 것입니까? 그렇다면 Interop 개체를 어떻게 죽일 수 있습니까? 또한 이렇게 사용하기위한 것이 아니라면 GCCollect방법 이 왜 짝수 Public일까요?


답변

글쎄, GC는 내가 사랑 / 증오 관계가있는 것들 중 하나입니다. 우리는 과거에 VistaDB를 통해 그것을 깨고 블로그에 올렸습니다. 그들은 그것을 고쳤지만 이와 같은 문제를 해결하는 데 오랜 시간이 걸립니다.

GC는 복잡하고 모든 접근 방식에 맞는 하나의 크기는 이렇게 큰 것을 끌어 내기가 매우 어렵습니다. MS는 꽤 잘 해냈지만 때때로 GC를 속일 수 있습니다.

일반적으로 Collect메모리를 엄청나게 버리고 GC가 지금 정리하지 않으면 중년 위기에 빠진다는 사실을 알지 못하는 한 추가해서는 안됩니다 .

일련의 잘못된 GC.Collect진술로 전체 기계를 망칠 수 있습니다 . collect 문에 대한 필요성은 거의 항상 더 큰 기본 오류를 가리 킵니다. 메모리 누수는 일반적으로 참조 및 작동 방식에 대한 이해 부족과 관련이 있습니다. 또는 IDisposable필요하지 않은 객체를 사용 하고 GC에 훨씬 더 많은 부하를가합니다.

시스템 성능 카운터를 통해 GC에 소요 된 시간의 %를 자세히 살펴보십시오. GC에서 앱이 시간의 20 % 이상을 사용하는 것을 발견하면 심각한 개체 관리 문제 (또는 비정상적인 사용 패턴)가있는 것입니다. GC가 전체 앱의 속도를 높이기 때문에 항상 GC가 소비하는 시간을 최소화하려고합니다.

GC는 워크 스테이션과 서버에서 다르다는 점도 중요합니다. 나는 둘 다 테스트하지 않는 사람들 (또는 그들 둘이 둘이라는 사실조차 알지 못함)과 함께 문제를 추적하기 어려운 작은 여러 가지를 보았습니다.

그리고 가능한 한 내 대답을 최대한으로 작성하려면 해당 플랫폼을 대상으로하는 경우 Mono에서 테스트해야합니다. 완전히 다른 구현이므로 MS 구현과 완전히 다른 문제가 발생할 수 있습니다.


답변

유용한 상황이 있지만 일반적으로 피해야합니다. GOTO 또는 오토바이를 타는 것과 비교할 수 있습니다. 필요할 때 할 수 있지만 친구에게 그것에 대해 말하지는 않습니다.


답변

내 경험상 프로덕션 코드에서 GC.Collect ()를 호출하는 것이 바람직하지 않았습니다. 디버깅시에는 잠재적 인 메모리 누수를 명확히하는 데 도움이되는 이점이 있습니다. 내 근본적인 이유는 GC가 프로그래머에 의해 작성되고 최적화 되었기 때문이라고 생각합니다. GC.Collect ()를 호출해야한다고 느끼는 지점에 도달하면 경로를 벗어났다는 단서입니다. 어딘가에. 귀하의 상황에서는 실제로 메모리 문제가있는 것처럼 들리지 않고 컬렉션이 프로세스에 가져올 불안정성을 염려하는 것입니다. 아직 사용중인 물체를 청소하지 않고 수요 증가 및 감소에 매우 빠르게 적응하므로 걱정할 필요가 없다고 생각합니다.


답변

GC.Collect ()를 호출하는 가장 큰 이유 중 하나는 설명하는 것과 같이 많은 쓰레기를 생성하는 중요한 이벤트를 방금 수행했을 때입니다. 여기에서 GC.Collect ()를 호출하는 것이 좋습니다. 그렇지 않으면 GC가 ‘일회성’이벤트임을 이해하지 못할 수 있습니다.

물론 프로필을 작성하고 직접 확인해야합니다.