2011-01-27 20 views
10

Estoy perfilando la memoria en una aplicación C# utilizando un generador de perfiles de memoria, dotTrace y contadores de perfmon. La única pregunta que no he podido responder es: ¿Cuál es la latencia máxima que causa la recolección de basura en mi aplicación? Puedo obtener un valor aproximado para esto usando el% de tiempo en la recolección de elementos no utilizados, pero ¿hay alguna manera de cronometrar colecciones individuales?.NET Garbage Collection Latency

+1

¿Qué versión de .NET? ¿Cuántos hilos hay en tu aplicación? ¿Hace alguna E/S? Es posible que GC no le esté causando _any_ latencia. Supongo que, por "latencia", ¿te refieres a la cantidad de tiempo que tu programa no está haciendo nada útil porque está esperando que termine un GC? –

+0

Sí, eso es lo que quiero decir con latencia. No estoy realmente interesado en una respuesta teórica, sino en un método por el cual se puede medir. O más bien, ¿hay algún método mejor para medir la latencia de recolección de basura que (GCt1-GTt0) *% de tiempo en GC, donde t = tiempo? ¿O no es útil medir el gen # 0 de GC ya que la tasa de error es mayor que el valor? – Patrick

Respuesta

8

Parece que está haciendo 2 preguntas 1- ¿Hay una latencia máxima para el GC? 2- ¿Cómo se cronometra la recolección de GC individual?

Para el n. ° 1, el rendimiento del GC es de aproximadamente 200 MB/seg/montón. Esto significa que el GC puede recolectar un montón de tamaño de 100 MB en 1 segundo. La noción de Perheap es porque el servidor GC, ya que estamos creando 1 montón por CPU.

Por lo tanto, si tiene un gran montón, puede ver grandes latencias. Tenga en cuenta que cuando GC recolecta la memoria, lo hace de forma efímera, por lo que las colecciones Gen0/Gen1 son muy económicas en comparación con las colecciones completas de GC.

En .NET 4.0 agregamos una función para minimizar la latencia del GC para aplicaciones cliente, esta característica está habilitada de forma predeterminada en el modo concurrente GC. En este modo, tratamos de recolectar el montón en un hilo de fondo mientras la aplicación se está ejecutando. Esto da como resultado un mejor tiempo de pausa para aplicaciones cliente

Para # 2: Tenemos un rastreo muy poderoso en el framework .net llamado ETW (está disponible en Windows, y lo aprovechamos en el CLR). ETW significa Event Tracing For Windows (. Lanzamos eventos ETW cuando un GC está a punto de comenzar, y cuando termina un GC. usando estos eventos ETW, puede calcular el tiempo que se pasa en cada GC.Para obtener más información, puede consultar el CLR ETW reference. Además, para una buena biblioteca administrada que le permite lidiar con eventos ETW, consulte TraceEvent

Espero que esta ayuda. Gracias

+0

En realidad, solo una pregunta. ¿Cómo puedo determinar la latencia máxima para cualquier recolección de basura en una aplicación? Pero su información adicional es muy bienvenida y puedo agregar el ETW a mi lista de funciones nuevas e importantes de .NET 4.0. Gracias. – Patrick

2

No creo que haya una "latencia máxima". La GC se dispara cuando tiene que hacerlo, cuando hay presión de memoria. La misma aplicación que se ejecuta en una máquina con 2 GB verá colecciones más frecuentes que la misma aplicación en una máquina de 4 GB.

una cosa que tuve un momento realmente difícil cuando comencé con .NET estaba viendo crecer la memoria. Hombre, eso fue aterrador porque pensé que tenía filtraciones. Pero con el tiempo, ves que la GC se calma y todo funciona a la perfección.

Si obtiene excepciones de OOM u otro mal comportamiento, es entonces cuando se preocupa. de lo contrario, deje que GC haga lo suyo.

EDIT: zneak hace un gran comentario - Puede que haya entendido mal su pregunta.

El tiempo pasado en GC también depende de muchos factores, ¿Qué generación se está recopilando? Los Gen0 son muy rápidos. Gen1 tarda más y Gen2 es aún más. Con una buena utilización de la memoria busco 10 colecciones Gen1 por cada Gen2 y 10 Gen0 por cada Gen1. En el transcurso de un día en nuestro sitio web muy usado, puedo ver 10,000 Gen0's, 1000 Gen1's y 100 Gen2's. YMMV.

+1

Creo que más bien quiso decir '¿cómo puedo saber cuánto tiempo fue el peor momento' que 'cuánto tiempo puede tomar teóricamente'? – zneak

4

Es posible sincronizar las colecciones gen # 2 (las lentas) con el método GC.RegisterForFullGCNotification(). Sin embargo, eso requiere la versión del servidor del recopilador (elemento <gcserver> en el archivo .config).

Classic Heisenbergian, no sirve para nada, ya que solo la versión de estación de trabajo admite colecciones concurrentes gen # 2, pueden mejorar significativamente la latencia. La latencia real que produce es muy muy impredecible, depende en gran medida de a qué velocidad los hilos de su programa están asignando y llenando gen # 0 y # 1 mientras se está llevando a cabo una recolección concurrente. No tener que hacer esta pregunta es muy recomendable.