web-dev-qa-db-fra.com

Empêcher la collecte des ordures .NET pendant une courte période

J'ai une application hautes performances qui gère une très grande quantité de données. Il reçoit, analyse et rejette d'énormes quantités d'informations sur de très courtes périodes. Cela provoque une bonne quantité de désabonnement d'objets que j'essaie actuellement d'optimiser, mais cela provoque également un problème secondaire. Lorsque Garbage Collection entre en action, il peut entraîner de longs retards car il nettoie les choses (j'entends par 10 à 100 secondes de millisecondes). 99% du temps, cela est acceptable, mais pour de brèves périodes de temps d'environ 1 à 2 minutes, je dois être absolument sûr que Garbage Collection ne provoque pas de retard. Je sais quand ces périodes se produiront à l'avance et j'ai juste besoin d'un moyen de m'assurer que la collecte des ordures ne se produit pas pendant cette période. L'application est écrite en C # à l'aide de .NET 4.0 Framework et utilise du code managé et non managé si cela est important.

Mes questions sont;

  1. Est-il possible de suspendre brièvement la récupération de place pour l'ensemble du programme?
  2. Est-il possible d'utiliser System.GC.Collect () pour forcer le garbage collection avant la fenêtre dont j'ai besoin sans Garbage Collection et si je fais combien de temps vais-je être libre de Garbage Collection?
  3. Quels conseils les gens ont-ils pour minimiser le besoin global de ramasser les ordures?

Remarque - ce système est assez complexe avec de nombreux composants différents. J'espère éviter d'aller vers une approche où je dois implémenter une interface IDisposable personnalisée sur chaque classe du programme.

60
drobertson

.NET 4.6 a ajouté deux nouvelles méthodes: GC.TryStartNoGCRegion et GC.EndNoGCRegion juste pour cela.

79
xanatos
GCLatencyMode oldMode = GCSettings.LatencyMode;

// Make sure we can always go to the catch block, 
// so we can set the latency mode back to `oldMode`
RuntimeHelpers.PrepareConstrainedRegions();

try
{
    GCSettings.LatencyMode = GCLatencyMode.LowLatency;

    // Generation 2 garbage collection is now
    // deferred, except in extremely low-memory situations
}
finally
{
    // ALWAYS set the latency mode back
    GCSettings.LatencyMode = oldMode;
}

Cela vous permettra de désactiver le GC autant que possible. Il ne fera pas de grandes collections d'objets jusqu'à ce que:

  • Vous appelez GC.Collect()
  • Vous définissez GCSettings.LatencyMode Sur autre chose que LowLatency
  • Le système d'exploitation envoie un signal de mémoire faible au CLR

Soyez prudent lorsque vous faites cela, car l'utilisation de la mémoire peut grimper extrêmement rapidement lorsque vous êtes dans ce bloc try. Si le GC collecte, il le fait pour une raison, et vous ne devriez sérieusement considérer cela que si vous avez une grande quantité de mémoire sur votre système.

En référence à la question trois, vous pouvez peut-être essayer de réutiliser des objets comme des tableaux d'octets si vous recevez des informations via les E/S du système de fichiers ou un réseau? Si vous analysez ces informations dans des classes personnalisées, essayez de les réutiliser aussi, mais je ne peux pas donner trop de bons conseils sans en savoir plus sur ce que vous faites exactement.

Voici quelques articles MSDN qui peuvent également vous aider:

Remarque: GCSettings.LatencyMode = GCLatencyMode.LowLatency Ne peut être défini que si GCSettings.IsServerGC == false. IsServerGC peut être modifié dans App.config:

  <runtime>
    <gcServer enabled="false" />
  </runtime>
75
user153498