je suis encore assez incertain à ce sujet. Je travaille depuis 7 ans sur un serveur d'application. Nos plus grandes installations utilisent 24 Go de RAM. Ses appels extrêmement multithread et ALL pour GC.Collect () se sont heurtés à des problèmes de performances vraiment terribles.
De nombreux composants tiers ont utilisé GC.Collect () alors qu'ils pensaient que c'était intelligent de le faire maintenant. Ainsi, un simple tas de rapports Excel bloquait le serveur d'applications pour tous les threads plusieurs fois par minute.
Nous avons dû refactoriser tous les composants tiers afin de supprimer les appels GC.Collect (), et tout a bien fonctionné après cela.
Mais j'utilise également des serveurs sur Win32, et ici j'ai commencé à utiliser beaucoup GC.Collect () après avoir obtenu une OutOfMemoryException.
Mais je suis également assez incertain à ce sujet, car j'ai souvent remarqué que lorsque j'obtiens un MOO sur 32 bits et que je réessaye d'exécuter à nouveau la même opération, sans appeler GC.Collect (), cela fonctionnait très bien.
Une chose que je me demande est l'exception OOM elle-même ... Si j'avais écrit le .Net Framework et que je ne peux pas allouer un bloc de mémoire, j'utiliserais GC.Collect (), défragmenter la mémoire (??), réessayer , et si je ne trouve toujours pas un bloc de mémoire libre, alors je lancerais l'exception OOM.
Ou du moins, faites de ce comportement une option configurable, en raison des inconvénients du problème de performances avec GC.Collect.
Maintenant, j'ai beaucoup de code comme celui-ci dans mon application pour "résoudre" le problème:
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);
}
(Notez que le comportement Thread.Sleep () est un comportement vraiment spécifique à l'application, car nous exécutons un service de mise en cache ORM, et le service prend un certain temps pour libérer tous les objets mis en cache, si la RAM dépasse certaines valeurs prédéfinies. quelques secondes la première fois et a augmenté le temps d'attente à chaque occurrence de MOO.)