Empêcher le ramassage des ordures .NET pour une courte période

J’ai une application très performante qui gère une très grande quantité de données. Il reçoit, parsing et élimine d’énormes quantités d’informations sur de très courtes périodes. Cela provoque une quantité importante de perte d’objects que j’essaie actuellement d’optimiser, mais cela cause également un problème secondaire. Lorsque le nettoyage de la mémoire entre en jeu, cela peut entraîner de longs retards car il nettoie les choses (de 10 à 100 secondes). 99% du temps, cela est acceptable, mais pour des fenêtres de courte durée, environ 1 à 2 minutes, je dois être absolument certain que le nettoyage de la mémoire ne cause pas de retard. Je sais quand ces périodes se produiront à l’avance et j’ai juste besoin d’un moyen de s’assurer que la collecte des ordures ne se produise pas pendant cette période. L’application est écrite en C # à l’aide de .NET Framework 4.0 et utilise du code managé et non géré si cela est important.

Mes questions sont:

  1. Est-il possible de suspendre brièvement le ramassage des ordures pour l’ensemble du programme?
  2. Est-il possible d’utiliser System.GC.Collect () pour forcer le nettoyage de la mémoire avant la fenêtre dont je n’ai pas besoin en ce qui concerne la récupération de la mémoire et, si je le fais, pendant combien de temps serai-je gratuit?
  3. Quels conseils les gens ont-ils sur la nécessité de réduire le besoin global de collecte des déchets?

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

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

 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 vous le pouvez. Il ne fera pas de grandes collections d’objects jusqu’à ce que:

  • Vous appelez GC.Collect()
  • Vous définissez GCSettings.LatencyMode à autre chose que LowLatency
  • Le système d’exploitation envoie un signal à faible mémoire 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. Si le CPG est en train de collecter, il le fait pour une raison, et vous ne devriez envisager cela sérieusement que si vous avez une grande quantité de mémoire sur votre système.

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

Voici quelques articles MSDN qui peuvent aussi vous aider:

  • Modes de latence
  • Régions d’exécution contraintes (c’est pourquoi nous appelons PrepareConstrainedRegions() )

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