nadal nie jestem tego pewien. Pracuję od 7 lat na serwerze aplikacji. Nasze większe instalacje korzystają z 24 GB pamięci RAM. Jest bardzo wielowątkowy, a WSZYSTKIE wywołania GC.Collect () napotkały naprawdę straszne problemy z wydajnością.
Wiele komponentów innych firm korzystało z GC.Collect (), gdy uważali, że jest to sprytne, aby zrobić to teraz. Tak więc prosta grupa raportów programu Excel blokowała serwer aplikacji dla wszystkich wątków kilka razy na minutę.
Musieliśmy refaktoryzować wszystkie składniki innych firm, aby usunąć wywołania GC.Collect (), i po wykonaniu tej czynności wszystko działało dobrze.
Ale używam serwerów również na Win32 i tutaj zacząłem intensywnie używać GC.Collect () po otrzymaniu OutOfMemoryException.
Ale nie jestem też tego pewien, ponieważ często zauważyłem, że kiedy dostaję OOM na 32-bitowym, i ponownie próbuję uruchomić tę samą operację, bez wywoływania GC.Collect (), po prostu działało dobrze.
Jedną rzeczą, nad którą się zastanawiam, jest sam wyjątek OOM ... Gdybym napisał .Net Framework i nie mogę przydzielić bloku pamięci, użyłbym GC.Collect (), defragmentacji pamięci (??), spróbuj ponownie , a jeśli nadal nie mogę znaleźć wolnego bloku pamięci, wyrzuciłbym wyjątek OOM.
Lub przynajmniej uczyń to zachowanie jako konfigurowalną opcją, ze względu na wady problemu z wydajnością w GC.Collect.
Teraz w mojej aplikacji jest mnóstwo kodu, który „rozwiązuje” problem:
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);
}
(Zwróć uwagę, że zachowanie Thread.Sleep () jest w rzeczywistości zachowaniem specyficznym dla aplikacji, ponieważ uruchamiamy usługę buforowania ORM, a usługa zajmuje trochę czasu, aby zwolnić wszystkie buforowane obiekty, jeśli pamięć RAM przekracza niektóre wstępnie zdefiniowane wartości. kilka sekund za pierwszym razem i wydłużał czas oczekiwania przy każdym wystąpieniu OOM.)