non sono ancora abbastanza sicuro di questo. Lavoro da 7 anni su un Application Server. Le nostre installazioni più grandi utilizzano Ram da 24 GB. È fortemente multithread e TUTTE le chiamate per GC.Collect () hanno riscontrato problemi di prestazioni davvero terribili.
Molti componenti di terze parti hanno utilizzato GC.Collect () quando hanno pensato che fosse intelligente farlo proprio ora. Quindi un semplice gruppo di Excel-Reports ha bloccato l'App Server per tutti i thread più volte al minuto.
Abbiamo dovuto riformattare tutti i componenti di terze parti per rimuovere le chiamate GC.Collect () e tutti hanno funzionato bene dopo averlo fatto.
Ma sto eseguendo Server anche su Win32, e qui ho iniziato a fare un uso intensivo di GC.Collect () dopo aver ottenuto OutOfMemoryException.
Ma non sono abbastanza sicuro di questo, perché ho notato spesso, quando ottengo una OOM a 32 bit, e riprovo a eseguire di nuovo la stessa Operazione, senza chiamare GC.Collect (), ha funzionato bene.
Una cosa che mi chiedo è l'eccezione OOM stessa ... Se avessi scritto .Net Framework e non potessi allocare un blocco di memoria, userei GC.Collect (), deframmenta memoria (??), riprova e se ancora non riesco a trovare un blocco di memoria libero, allora lancerei l'eccezione OOM.
O almeno rendere questo comportamento come opzione configurabile, a causa degli svantaggi del problema di prestazioni con GC.Collect.
Ora ho un sacco di codice come questo nella mia app per "risolvere" il problema:
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);
}
(Si noti che il comportamento Thread.Sleep () è un comportamento davvero app-app, perché stiamo eseguendo un servizio di memorizzazione nella cache ORM e il servizio impiega del tempo per rilasciare tutti gli oggetti memorizzati nella cache, se la RAM supera alcuni valori predefiniti. pochi secondi la prima volta e ha aumentato il tempo di attesa ogni occorrenza di OOM.)