2011-03-21 11 views
9

Duplicar posibles:
When is it acceptable to call GC.Collect?Cuándo usar GC.Collect() en .NET?

Por lo que sé el CLR hace todo esto recolección de basura para usted, pero hay una razón para llamar manualmente GC.Collect()?

¿Es para casos en que cierre un archivo, deseche un recurso de imagen o un recurso no administrado, que debe llamar al GC.Collect() para limpiar rápidamente la memoria no utilizada inmediatamente?

+4

http://stackoverflow.com/questions/478167/when-is-it-acceptable-to-call-gc-collect, http://stackoverflow.com/questions/1149197/gc-collect, http://stackoverflow.com/questions/5248838/to-gc-collect-or-not, etc ..... – Cocowalla

Respuesta

5

¿Es para casos cuando cierra un archivo, desecha un recurso de imagen o un recurso no administrado, que debe llamar a GC.Collect() para limpiar rápidamente la memoria no utilizada inmediatamente?

No, realmente no. Esto normalmente se maneja a través del IDisposable.

Existen muy pocas razones para llamar directamente al GC.Dispose(), y hacerlo a menudo causa mucho daño, ya que interfiere con la heurística interna del GC en .NET. Sin embargo, hay casos raros cuando es útil.

Por ejemplo, si tiene una operación que es una operación poco común que utiliza un gráfico de objetos grandes, y sabes que vas a estar "inactivo" después, que puede desee llamar a GC.Collect inmediatamente después de liberar el memoria utilizada por los objetos. Una vez dicho esto, a menudo esto es mejor dejarlo en manos del sistema.

En su mayor parte, he encontrado que el escenario más útil para GC.Collect() es para la depuración. Puede ayudarlo a garantizar que no tenga una fuga, ya que le permite forzar una colección completa de Gen2.

+0

También esto era otra cosa que me preguntaba. ¿Se memorizará inmediatamente la memoria GC cuando se llame al método Dispose? –

+1

@Joan: Dispose realmente no está relacionado con la memoria (administrada). Libera (inmediatamente) la memoria ** asignada de manera nativa asociada con la imagen, así como su control de sistema operativo, pero no la memoria administrada. –

3

Normalmente utilizo GC.Collect() para llevar el montón a un estado más conocido. Por ejemplo, cuando se realiza una evaluación comparativa, debe asegurarse de iniciar cada ejecución desde un estado conocido, y GC.Collect() ayuda con esto.

Debe no usarse para disponer de los recursos no administrados - para la que se debe utilizar using o manualmente llamar Dispose.

+0

Gracias, ¿puedes decirme qué quieres decir con "estado mayormente conocido"? –

+1

Quiero decir que el montón está compactado y no contiene objetos sin referencia. En otras palabras, cada ejecución de referencia debe ser interrumpida por la recolección de basura por aproximadamente la misma cantidad de tiempo. – Gabe

1

La única vez que he usado en el código que no era específicamente para comparar el uso de memoria de dos o más diferentes enfoques para algo tenía el siguiente escenario:

En una aplicación web (y por lo tanto, a largo -rutamiento), había algunas colecciones muy grandes que generalmente se reconstruirían unas pocas veces al día, a menudo con mucha menos frecuencia.

Varios objetos dentro de esa colección serían equivalentes, y por lo tanto se podría ahorrar mucha memoria reemplazando las referencias de un objeto por una referencia a la otra (después de compilar la colección era de solo lectura, y por lo tanto aliasing involucrado era seguro).Entonces, primero se construiría la colección, pero luego se reduciría su tamaño, matando a muchos objetos.

Esto significa que hubo un aumento repentino en la cantidad de objetos destruidos por segundo, que luego no volvería a suceder durante varias horas como mínimo. Como tal, el GC no juzgaría correctamente la cantidad de recolección necesaria, y ese recuerdo estaba a punto de ser necesario para construir la segunda gran colección. Por lo tanto, hacer una recolección manual de cada mil operaciones de limpieza tuvo un efecto positivo en el rendimiento (lo suficiente como para pasar de la falla de la aplicación a la tercera colección, a que sea confiable).

Se realizó una gran cantidad de medidas para asegurarse de que fuera beneficioso en este caso.

Los dos factores que hicieron de este beneficiosos fueron:

  1. Una gran cantidad de muertes de objetos que pasó.
  2. El evento que causa esto fue raro durante la vida de la aplicación.

Sin que ambos sean ciertos, la llamada manual sería innecesaria. Sin muchas muertes de objetos, no tiene sentido, y si no fuera raro en la vida útil de la aplicación, el GC se habría autoajustado para hacer frente.

3

sólo puedo pensar en dos casos en los que GC.Collect() podría ser de utilidad:

  • En las pruebas unitarias. Llame al GC.Collect() antes y después de algunas pruebas para encontrar posibles fugas de memoria. En este caso, considere usar GC.WaitForPendingFinalizers(), porque los finalizadores se ejecutan en una secuencia separada. Esto significa que las clases con finalizadores no liberan inmediatamente todos los recursos después de llamar al GC.Collect().

  • En procesos de larga vida como Servicios de Windows donde hay un largo tiempo de inactividad. Llame al GC.Collect() antes de que permanezca inactivo. Motivo: si un proceso está inactivo, el recolector de basura no se activará, por lo que la memoria no utilizada no se liberará durante el tiempo de inactividad.

GC.Collect() no debería ser llamado con el fin de "limpiar rápidamente la memoria no utilizada de inmediato". Tener una versión forzada de la memoria no compensa el rendimiento general causado por una recolección de basura activa.