나는 아직도 이것에 대해 확신이 없다. 저는 7 년 동안 Application Server에서 일하고 있습니다. 우리의 더 큰 설치는 24GB 램을 사용합니다. GC.Collect ()에 대한 높은 멀티 스레드 및 모든 호출은 실제로 끔찍한 성능 문제를 일으켰습니다.
많은 타사 구성 요소가 현재이 작업을 영리하다고 생각했을 때 GC.Collect ()를 사용했습니다. 따라서 간단한 Excel 보고서가 분당 여러 번 모든 스레드에 대해 App Server를 차단했습니다.
GC.Collect () 호출을 제거하기 위해 모든 타사 구성 요소를 리팩터링해야 했으며이 작업을 수행 한 후에는 모두 정상적으로 작동했습니다.
그러나 Win32에서도 서버를 실행하고 있으며 OutOfMemoryException을 얻은 후 GC.Collect ()를 많이 사용하기 시작했습니다.
그러나 32 비트에서 OOM을 얻었을 때 GC.Collect ()를 호출하지 않고 동일한 작업을 다시 실행하려고하면 종종 잘 작동했기 때문에 이것에 대해 확신이 없습니다.
내가 궁금한 것 중 하나는 OOM 예외 자체입니다 ... .Net Framework를 작성하고 메모리 블록을 할당 할 수 없으면 GC.Collect (), 조각 모음 메모리 (??)를 사용하고 다시 시도하십시오. , 여전히 사용 가능한 메모리 블록을 찾을 수 없으면 OOM-Exception이 발생합니다.
또는 적어도 GC.Collect의 성능 문제로 인해이 동작을 구성 가능한 옵션으로 만드십시오.
이제 문제를 "해결"하기 위해 내 앱에 이와 같은 코드가 많이 있습니다.
public static TResult ExecuteOOMAware<T1, T2, TResult>(Func<T1,T2 ,TResult> func, T1 a1, T2 a2)
{
int oomCounter = 0;
int maxOOMRetries = 10;
do
{
try
{
return func(a1, a2);
}
catch (OutOfMemoryException)
{
oomCounter++;
if (maxOOMRetries > 10)
{
throw;
}
else
{
Log.Info("OutOfMemory-Exception caught, Trying to fix. Counter: " + oomCounter.ToString());
System.Threading.Thread.Sleep(TimeSpan.FromSeconds(oomCounter * 10));
GC.Collect();
}
}
} while (oomCounter < maxOOMRetries);
// never gets hitted.
return default(TResult);
}
(ORM 캐싱 서비스를 실행하고 있기 때문에 Thread.Sleep () 비헤이비어는 실제로 앱에 적합한 동작입니다. RAM이 미리 정의 된 값을 초과하면 서비스가 캐시 된 모든 객체를 해제하는 데 시간이 걸립니다. 처음 몇 초 동안 OOM이 발생할 때마다 대기 시간이 늘어났습니다.)