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


103

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

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

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

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

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

감사.


24
"프로그램 흐름을 조금만 변경해도 치명적인 결과를 초래할 수 있습니다. 누군가가 죽을 수 있습니다."-C # .NET이 귀하의 목적에 충분히 결정적이라고 확신합니까?
Steve Jessop

4
Windows 나 .NET은 실시간 플랫폼이 아니므로 최소한 인간의 생명을 위협 할 정도로는 성능 메트릭을 보장 할 수 없습니다. 나는 당신이 과장하거나 부주의하다는 것에 하나 하나 동의합니다.
Sergio Acosta

3
"존경하는 프로그래머가 사용하지 않을 이러한 것 중 하나, 그것이 무엇을위한 것인지조차 모르는 사람들도"에서 LOL! 왜 그런지 모르는 것을 사용하는 프로그래머는 내 책에서 가장 존경받는 사람이 아닙니다. :)
The Dag

답변:


87

Rico의 블로그에서 ...

규칙 # 1

하지마.

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

규칙 # 2

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

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

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

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

측정, 측정, 측정.


9
나는 이것이 단지 오래된 것이라고 말하고 싶습니다. 당신이 무엇을하고 있는지 알고 있고, 따라서 그것을하는시기와 방법, 그리고 부작용을 안다면 정말 나쁘거나 위험한 것은 없습니다. 상황이되지 않습니다 할 수없는 것처럼, 지금까지 사용 XXXX는 형편없는 프로그래머에서 세계를 보호하기 위해 거기에 넣어 : D
호르헤 코르도바


GC.Collect를 사용하는 것이 좋은 습관이라고 말하는 것이 아닙니다. 그러나 때로는 실제 원인을 모른 채 문제를 해결하는 빠른 방법입니다. 못 생겼지 만, 효과가 있고, 나에게 나쁜 접근 방식은 아닌 것 같습니다. 특히 문제의 근본 원인을 파악할 시간이 많지 않고 상사가 당신 뒤에 서있을 때 ...
Silent Sojourner

58

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


3
그것은 매우 사실이지만 그들이 모든 발전에 적용되는 가정을 할 수 있을지는 모르겠습니다.
MasterMastic

2
@Ken 아니, 그들은 할 수 없습니다. 하지만 그렇게하는 것이 더 나은 위치에 있습니까? 아니면 특정 하드웨어, 특정 OS 버전 등을 가정하여 코드를 작성 하시겠습니까? 통증 / 이득 비율이 너무 높습니다.
The Dag

2
@TheDag IMO는 물론입니다. 메모리를 해제 할 때 하드웨어에 대해서는 신경 쓰지 않습니다. 그게 OS 작업이기 때문입니다. 나는 또한 내가 프로그래밍하는 모든 것들에 공통된 인터페이스를 가지고 있기 때문에 OS에 대해 신경 쓰지 않는다. (예를 들어 Windows, Mac 또는 Linux인지 상관하지 않습니다. C / C ++에서 메모리를 할당 / 해제 할 때 new / delete malloc / dealloc입니다). 나는 항상 틀릴 수 있으므로 자유롭게 수정하십시오.
MasterMastic 2013 년

@MasterMastic malloc은 매우 간단한 인터페이스 만 가지고 있으며 구현은 중요 할만큼 다양 할 수 있습니다. 그것은 모두 당신이 해결하려는 문제의 종류에 달려 있습니다. 경우 malloc"충분히 좋은"했다, 당신은 당신 것, 풀링을 버퍼 필요하지 않을까요? C / C ++ 개발은 OS / 런타임 / 라이브러리를 더 잘 알고 있기 때문에 (때로는 실제로 알고 있기 때문에) 추측하려고하는 예제로 가득 합니다. 성능이 중요한 많은 응용 프로그램은 시스템 / 런타임 할당자를 완전히 사용하지 않습니다. 시작시 모든 메모리를 미리 할당하는 데 사용되는 게임 (일정 크기 배열 등).
Luaan

24

그렇다면 .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일까요?


3
이것은 새로운 StackOverflow 질문, 즉 GC를 호출하지 않고 COM 인스턴스를 근절하는 방법을 만들 것입니다. 특히 관리되지 않는 순환 참조와 관련하여. VB6 Outlook 추가 기능을 C #으로 업그레이드하는 것을 경계하게 만드는 문제 중 하나입니다. (우리는 더 이상 필요하지 않을 때 COM 참조가 결정 론적 방식으로 죽임을 보장하는 VB 측에서 코딩 패턴과 테스트 케이스를 개발하기 위해 많은 작업을 수행했습니다.)
rkagerer 2011

2
이것이 일반적으로 COM 개체에 적용되는 경우 이는 유효한 시나리오 일 수 있습니다. 그러나 문제는 대화 형 데스크톱 용으로 설계된 클라이언트 응용 프로그램을 COM 서버로 사용하고 있다는 것입니다. MSDN 지식 기반에서 : "Microsoft는 현재 무인 비대화 형 클라이언트 응용 프로그램 또는 구성 요소 (ASP, ASP.NET, DCOM 및 NT 서비스 포함)에서 Microsoft Office 응용 프로그램 자동화를 권장하지 않으며 지원하지 않습니다. 이 환경에서 Office를 실행하면 불안정한 동작 및 / 또는 교착 상태가 발생할 수 있습니다. "
The Dag

2
@TheDag-Microsoft는 권장하지 않을 수 있지만, 우리 중 많은 사람들은 Office interop을 사용하여 이전 VB6 코드를 .Net Windows 앱으로 이식해야했습니다. 나는 큰 VB6에서 .Net으로의 변환 프로젝트에 대한 보이지 않는 모든 매달린 참조를 제거 할 때까지 몇 달 동안 작업했습니다. 역 할당 순서로 릴리스하는 방법을 배우고 컬렉션을 포함하여 모든 단일 com 객체에 대한 로컬 참조를 보유하는 것이 도움이되었습니다.
Dib

15

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

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

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

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

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

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

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


범인은 종종 이벤트입니다. 인스턴스 메서드가 이벤트 처리기로 사용될 때마다 이벤트 게시자는 이벤트 대리자를 통해 구독자에 대한 참조를 갖게됩니다. 이 문제를 피할 수있는 유일한 "쉬운"방법은 구독자만큼 오래 지속되는 게시자 만 사용하는 것입니다 (예 : 포함 양식에 의해 처리되는 이벤트를 게시하는 TextBox는 텍스트 상자가 예상되지 않으므로 문제가되지 않습니다. 양식 밖에서 살기 위해). 예제 문제 시나리오 : 싱글 톤 모델, 모델 이벤트를 처리하는 임시 뷰.
The Dag

5
전체 기계를 어떻게 망칠 수 있습니까?
Adam R. Gray

13

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


12

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


10

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

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


9

물론 비 실시간 가비지 콜렉션 언어로 실시간 요구 사항이있는 코드를 작성해서는 안됩니다.

잘 정의 된 단계가있는 경우 가비지 수집기를 트리거하는 데 문제가 없습니다. 그러나이 경우는 극히 드뭅니다. 문제는 많은 개발자들이 이것을화물 컬트 스타일의 문제를 문서화하는 데 사용하려고 시도하고 무차별 적으로 추가하면 성능 문제가 발생한다는 것입니다.


진실. 그러나 "객체가 가비지 수집에 적합하지 않지만 그래야만한다"라는 오류 조건을 포착 할 수있는 자동화 된 테스트는 가치가 있습니다. 이것은 팩토리 로직, 소멸자 로직 및 GC.Collect의 조합을 통해 달성 될 수 있습니다. 예를 들어 Entity 클래스에는 IObjectTracker 속성이 있으며 일반적으로 null이지만 테스트 목적의 엔티티 팩토리에 의해 할당됩니다. 공장은 또한 추적자에게 개체 생성을 알리고 소멸자는 사망에 대해 (존재하는 경우) 알립니다. "소멸자가 모든 가비지 수집 가능한 개체에 대해 실행"을 알 수 있다면 추적기 상태를 확인하여 누수를 감지 할 수 있습니다.
The Dag

7

GC.Collect ()를 호출하면 CLR이 참조를 확인하여 각 개체를 실제로 해제 할 수 있는지 확인하기 위해 스택 워크를 수행합니다. 이는 개체 수가 많고 가비지 수집을 너무 자주 트리거하는 것으로 알려진 경우 확장성에 영향을줍니다. CLR을 신뢰하고 적절한 경우 가비지 수집기가 스스로 실행되도록합니다.


2
스택 워크를 유발할뿐만 아니라 애플리케이션 주 스레드 (및 생성 된 모든 하위 스레드)가 고정되어 GC 스택을 이동할 수 있습니다 . 앱이 GC에서 더 많은 시간을 보낼수록 더 많은 시간이 정지됩니다.
Scott Dorman

3
앱 / GC가 더 이상 필요하지 않은 것을 버리고 있기 때문에 느린 성능보다 메모리 부족 예외로 인한 앱 충돌에 대해 더 걱정합니다. Microsoft가 먼저 쓰레기를 버리지 않고 OOM 예외를 던지는 이유를 아는 사람이 있습니까? (이 눈에 띄는 단계가 없거나 OOM 예외를 발생시키기 전에이 단계가 시도되지 않는 것으로 보이는 이유에 대한 설명이 없으면 "자동으로"발생하는 일이 "원하는 방식"에 대한 믿음이 있는지 잘 모르겠습니다.
Wonderbird

6

사실, GC.Collect에 전화하는 것은 매우 나쁜 습관이라고 생각하지 않습니다.
필요한 경우가있을 수 있습니다. 예를 들어, 데이터베이스에서 다른 테이블을 열고 BLOB 필드의 내용을 임시 파일로 추출하고 파일을 암호화 한 다음 파일을 바이너리 스트림으로 읽어서 BLOB로 다시 읽는 스레드를 실행하는 양식이 있습니다. 다른 테이블의 필드.

전체 작업에는 많은 메모리가 필요하며 테이블에있는 파일 내용의 행 수와 크기가 확실하지 않습니다.

나는 종종 OutofMemory Exception을 얻었고 카운터 변수를 기반으로 GC.Collect를 주기적으로 실행하는 것이 현명하다고 생각했습니다. 카운터를 증가시키고 지정된 레벨에 도달하면 GC가 호출되어 생성되었을 수있는 가비지를 수집하고 예기치 않은 메모리 누수로 인해 손실 된 메모리를 회수합니다.

이 후, 나는 그것이 잘 작동하고 있다고 생각합니다.
다음과 같은 방식으로 전화합니다.

var obj = /* object utilizing the memory, in my case Form itself */
GC.Collect(GC.GetGeneration(obj ,GCCollectionMode.Optimized).

5

.net에서 가비지 수집을 수행하는 데 필요한 시간은 쓰레기가 아닌 물건의 양보다 쓰레기가 아닌 물건의 양과 훨씬 더 밀접하게 관련되어 있습니다. 실제로 객체가 Finalize(명시 적으로 또는 C # 소멸자를 통해) 재정의하지 않는 한 WeakReference, 큰 개체 힙에 있거나 다른 gc 관련 방식에서 특수한 경우에만 위치하는 메모리를 식별합니다. 객체라는 것은 그것에 대한 뿌리 참조의 존재입니다. 그렇지 않으면 GC의 작업은 가치있는 모든 것을 건물에서 가져와 건물을 동적으로 만들고 이전 건물 부지에 새 건물을 짓고 모든 귀중한 항목을 그 안에 넣는 것과 유사합니다. 건물을 다이너마이트하는 데 필요한 노력은 건물 내부의 쓰레기 양과는 완전히 무관합니다.

결과적으로 호출 GC.Collect은 시스템이 수행해야하는 전체 작업량을 증가시키는 경향이 있습니다. 그것은 다음 수집의 발생을 지연시킬 것이지만 아마도 다음 수집이 발생했을 때 필요했던만큼의 작업을 즉시 수행 할 것입니다. 다음 수집이 발생했을 때 수집에 소요 된 총 시간은 GC.Collect호출되지 않은 것과 거의 같지만 시스템에 일부 가비지가 축적되어 후속 수집이 필요 GC.Collect하지 않은 것보다 더 빨리 필요합니다. 호출되었습니다.

내가 GC.Collect정말로 유용하다는 것을 알 수있는 시간 은 일부 코드의 메모리 사용량을 측정해야 할 때 (메모리 사용량 수치는 컬렉션 다음에 실제로 의미가 있기 때문에) 또는 여러 알고리즘 중 어느 것이 더 나은지 프로파일 링해야 할 때입니다 (GC.Collect () 호출). 여러 코드를 각각 실행하기 전에 일관된 기준 상태를 유지할 수 있습니다. GC가 모르는 것을 알 수있는 몇 가지 다른 경우가 있지만, 단일 스레드 프로그램을 작성하지 않는 한 GC.Collect한 스레드의 데이터 구조가 "중년의 위기를 피하는 데 도움 이되는 호출"을 알 수있는 방법이 없습니다. "다른 스레드의 데이터가 그렇지 않으면 피할 수 있었던"중년 위기 "를 일으키지 않을 것입니다.


5

루프에서 이미지 만들기-dispose를 호출하더라도 메모리는 복구되지 않습니다. 쓰레기는 매번 수집합니다. 사진 처리 앱의 1.7GB 메모리에서 24MB로 성능이 뛰어났습니다.

GC.Collect에 전화 할 시간이 절대적으로 필요합니다.


2
호출 Dispose은 관리되는 메모리 해제 하도록되어 있지 않습니다 . .NET의 메모리 모델이 어떻게 작동하는지 모르는 것 같습니다.
Andrew Barber

4

우리는 가비지 수집기가 가비지를 수집하지 않고 메모리를 확보하는 것과 비슷한 문제가있었습니다.

우리 프로그램에서는 OpenXML을 사용하여 적당한 크기의 Excel 스프레드 시트를 처리했습니다. 스프레드 시트에는 약 1000 개의 행에 14 개 열이있는 5-10 개의 "시트"가 포함되어 있습니다.

32 비트 환경 (x86)의 프로그램은 "메모리 부족"오류와 함께 충돌합니다. x64 환경에서 실행할 수 있었지만 더 나은 솔루션을 원했습니다.

하나를 찾았습니다.

다음은 삭제 된 개체에서 메모리를 해제하기 위해 Garbage Collector를 명시 적으로 호출 할 때 작동하지 않은 것과 작동 한 것에 대한 간단한 코드 조각입니다.

서브 루틴 내부에서 GC 호출이 작동하지 않았습니다. 기억은 되찾지 못했습니다 ...

For Each Sheet in Spreadsheets
    ProcessSheet(FileName,sheet)
Next

Private Sub ProcessSheet(ByVal Filename as string, ByVal Sheet as string)
    ' open the spreadsheet 
    Using SLDoc as SLDocument = New SLDocument(Filename, Sheet)
        ' do some work....
        SLDoc.Save
    End Using
    GC.Collect()
    GC.WaitForPendingFinalizers()
    GC.Collect()
    GC.WaitForPendingFinalizers()
End Sub

GC 호출을 서브 루틴 범위 외부로 이동하여 가비지가 수집되고 메모리가 해제되었습니다.

For Each Sheet in Spreadsheets
    ProcessSheet(FileName,sheet)
    GC.Collect()
    GC.WaitForPendingFinalizers()
    GC.Collect()
    GC.WaitForPendingFinalizers()
Next

Private Sub ProcessSheet(ByVal Filename as string, ByVal Sheet as string)
    ' open the spreadsheet 
    Using SLDoc as SLDocument = New SLDocument(Filename, Sheet)
        ' do some work....
        SLDoc.Save
    End Using
End Sub

.NET 가비지 수집이 .NET에 대한 호출을 무시하는 것처럼 보일 때 .NET 가비지 수집에 불만이있는 다른 사용자에게 도움이되기를 바랍니다 GC.Collect().

폴 스미스


4

컬렉션을 명시 적으로 호출하는 데 아무런 문제가 없습니다. 어떤 사람들은 그것이 벤더가 제공하는 서비스라면 의심하지 마십시오. 아, 그리고 이러한 모든 임의의 인터랙티브 응용 프로그램의 잘못된 순간에 정지합니까? 다음 버전은 더 나아질 것입니다!

백그라운드 프로세스가 메모리 조작을 처리하도록하는 것은 사실을 직접 처리 할 필요가 없다는 것을 의미합니다. 그러나 이것은 논리적으로 우리가 모든 상황에서 스스로 처리하지 않는 것이 최선임을 의미하지는 않습니다. GC는 대부분의 경우에 최적화되어 있습니다. 그러나 이것은 논리적으로 모든 경우에 최적화된다는 것을 의미하지는 않습니다.

확실한 답변으로 '가장 좋은 정렬 알고리즘은 무엇입니까'와 같은 공개 질문에 답한 적이 있습니까? 그렇다면 GC를 만지지 마십시오. 조건을 요청했거나 '이 경우'유형의 답변을 제공 한 분들은 GC에 대해 알아보고 언제 활성화해야할지 알 수 있습니다.

크롬과 파이어 폭스에서 응용 프로그램이 중단되어 저를 좌절 시켰습니다. 그리고 어떤 경우에는 메모리가 방해받지 않고 증가합니다. 가비지 수집기를 호출하는 법을 배우거나 버튼을 눌러 페이지의 텍스트를 읽기 시작하면 페이지를 눌러 다음 20 분 동안 멈출 수 있습니다.


2

시나리오에 대해서는 옳다고 생각하지만 API에 대해서는 잘 모르겠습니다.

Microsoft는 이러한 경우 GC가 곧 수집을 수행해야한다는 힌트로 메모리 압력추가 해야한다고 말합니다 .


2
흥미롭지 만 문서에 따르면 '작은 관리 개체가 관리되지 않는 많은 양의 메모리를 할당'할 때 AddMemoryPressure를 사용해야합니다. (강조 내)
Robert Paulson

2

뭐가 잘못 됐나요? 가비지 수집기와 메모리 할당자를 두 번째로 추측하고 있다는 사실은 그 사이에서 런타임에 애플리케이션의 실제 메모리 사용량에 대해 훨씬 더 잘 알고 있습니다.


1
가비지 수집기의 경험적 특성과이 기능이 외부 세계에 노출되었다는 사실로 인해 필요한 곳에 사용하면 유용한 것으로 생각하게됩니다. 문제는 그것을 사용하는 것이 아니라 그것을 사용하는 방법, 장소,시기를 아는 것입니다.
Trap

GC는 다른 모든 응용 프로그램과 메모리 요구 사항에 대해 더 잘 알고 있습니다. GC는 OS와 메모리를 협상하므로 사용 가능한 물리적 메모리와 관리 및 관리되지 않는 머신의 다른 모든 프로세스의 영향을받습니다. GC가 "사례 별"기준으로 "수집하기에 좋은시기"를 실제로 알고 있는지 의심 스럽지만, 단일 응용 프로그램보다 전반적으로 더 나은 전략을 가질 가능성이 매우 높습니다. ;)
The Dag

2

GC.Collect ()를 호출하려는 욕구는 일반적으로 다른 곳에서 만든 실수를 은폐하려는 것입니다!

더 이상 필요하지 않은 물건을 버리는 것을 잊은 곳을 찾으면 더 좋을 것입니다.


5
아마도 일반화 이잖아
MickyD

1

결론적으로 애플리케이션을 프로파일 링하고 이러한 추가 컬렉션이 사물에 어떤 영향을 미치는지 확인할 수 있습니다. 프로필을 작성하지 않는 한 멀리 떨어져있는 것이 좋습니다. GC는 자체적으로 관리하도록 설계되었으며 런타임이 발전함에 따라 효율성이 증가 할 수 있습니다. 작업을 방해하고 이러한 개선 사항을 활용하지 못할 수있는 코드 묶음을 원하지 않습니다. for 대신 foreach를 사용하는 것에 대한 유사한 주장이 있습니다. 즉, 향후 개선 사항이 foreach에 추가 될 수 있고 코드를 활용하기 위해 변경할 필요가 없다는 것입니다.


1

.NET Framework 자체는 실시간 환경에서 실행되도록 설계되지 않았습니다. 실시간 처리가 정말로 필요한 경우 .NET을 기반으로하지 않는 포함 된 실시간 언어를 사용하거나 Windows CE 장치에서 실행되는 .NET Compact Framework를 사용합니다.


그는 실시간 환경을 위해 WAS가 설계 한 .Net Micro Framework를 사용할 수 있습니다.
TraumaPony

@TraumaPony :이 페이지 하단의 차트를 확인 하십시오 . msdn.microsoft.com/en-us/embedded/bb278106.aspx : 분명히 Micro Framework는 실시간 환경을 위해 설계되지 않았습니다. 그러나 WinCE와 같은 임베디드 환경을 위해 설계되었지만 전력 요구 사항이 낮습니다.
Scott Dorman

1

최악의 경우 프로그램을 잠시 정지시키는 것입니다. 그러니 괜찮다면 그렇게하세요. 일반적으로 사용자 상호 작용이 대부분인 씩 클라이언트 또는 웹 앱에는 필요하지 않습니다.

장기 실행 스레드 또는 배치 프로그램이있는 프로그램은 개체를 제대로 처리하더라도 OutOfMemory 예외가 발생하는 경우가 있습니다. 내가 기억하는 하나는 LOB (기간 업무) 데이터베이스 트랜잭션 처리였습니다. 다른 하나는 씩 클라이언트 앱의 백그라운드 스레드에 대한 인덱싱 루틴이었습니다.

두 경우 모두 결과는 간단했습니다. No GC.Collect, 메모리 부족, 일관되게; GC. 수집, 완벽한 성능.

나는 기억 문제를 해결하기 위해 여러 번 시도했지만 아무 소용이 없습니다. 나는 그것을 꺼냈다.

요컨대, 오류가 발생하지 않는 한 입력하지 마십시오. 삽입했는데 메모리 문제가 해결되지 않으면 다시 꺼내십시오. 릴리스 모드에서 테스트하고 사과와 사과를 비교하는 것을 잊지 마십시오.

이것에 대해 일이 잘못 될 수있는 유일한 시간은 그것에 대해 도덕적 일 때입니다. 가치 문제가 아닙니다. 많은 프로그래머가 죽었고 불필요한 GC를 가지고 천국으로 곧장갔습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.