Prevenir la recolección de basura .NET durante un corto período de tiempo

Tengo una aplicación de alto rendimiento que maneja una gran cantidad de datos. Está recibiendo, analizando y descartando enormes cantidades de información en períodos de tiempo muy cortos. Esto causa una buena cantidad de abandono de objetos que actualmente estoy tratando de optimizar, pero también causa un problema secundario. Cuando la recolección de basura entra en acción puede causar largas demoras ya que limpia todo (por mucho tiempo quiero decir 10 a 100 segundos de milisegundos). El 99% de las veces esto es aceptable, pero para ventanas de tiempo breves de aproximadamente 1-2 minutos de duración, necesito estar absolutamente seguro de que Garbage Collection no causa un retraso. Sé cuándo ocurrirán estos períodos de tiempo antes y solo necesito una forma de asegurarme de que la recolección de basura no ocurra durante este período. La aplicación está escrita en C # usando .NET 4.0 Framework y usa código administrado y no administrado si eso es importante.

Mis preguntas son;

  1. ¿Es posible detener brevemente Garbage Collection para todo el progtwig?
  2. ¿Es posible usar System.GC.Collect () para forzar la recolección de basura antes de la ventana que necesito libre de recolección de basura y si lo hago, ¿cuánto tiempo estaré libre de basura?
  3. ¿Qué consejos tienen las personas para minimizar la necesidad de recolección de basura en general?

Nota: este sistema es bastante complejo con muchos componentes diferentes. Espero evitar un enfoque en el que tenga que implementar una interfaz IDisposable personalizada en cada clase del progtwig.

.NET 4.6 agregó dos métodos nuevos: GC.TryStartNoGCRegion y GC.EndNoGCRegion solo por esto.

 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; } 

Eso le permitirá desactivar el GC tanto como pueda. No hará grandes colecciones de objetos hasta que:

  • GC.Collect() a GC.Collect()
  • Establece GCSettings.LatencyMode en algo distinto a LowLatency
  • El sistema operativo envía una señal de baja memoria a la CLR

Tenga cuidado al hacer esto, porque el uso de la memoria puede subir extremadamente rápido mientras se encuentra en ese bloque de try . Si el GC se está recolectando, lo hace por una razón, y solo debes considerarlo seriamente si tienes una gran cantidad de memoria en tu sistema.

En referencia a la pregunta tres, ¿quizás puede intentar reutilizar objetos como matrices de bytes si está recibiendo información a través de la E / S del sistema de archivos o una red? Si está analizando esa información en clases personalizadas, intente reutilizarlas también, pero no puedo dar demasiados buenos consejos sin saber más acerca de lo que está haciendo exactamente.

Aquí hay algunos artículos de MSDN que también pueden ayudar:

  • Modos de latencia
  • Regiones de ejecución PrepareConstrainedRegions() es por eso que llamamos PrepareConstrainedRegions() )

Nota: GCSettings.LatencyMode = GCLatencyMode.LowLatency solo se puede establecer si GCSettings.IsServerGC == false . IsServerGC se puede cambiar en App.config :