9

¿Qué tipo de patrones de optimización se pueden usar para mejorar el rendimiento del recolector de basura?¿Cómo mejorar el rendimiento de la recolección de basura?

Mi razón para preguntar es que hago un montón de software integrado usando Compact Framework. En dispositivos lentos, la recolección de basura puede convertirse en un problema, y ​​me gustaría reducir las veces que el recolector de basura entra en funcionamiento, y cuando lo haga, quiero que termine más rápido. También puedo ver que trabajar con el recolector de basura en lugar de en contra de él podría ayudar a mejorar cualquier aplicación .NET o Java, especialmente las aplicaciones web de servicio pesado.

Éstos son algunos de mis pensamientos, pero no he hecho ningún punto de referencia.

  • reutilización de clases/matrices temporales (mantener bajo recuento de la asignación)
  • mantener la cantidad de objetos vivos al mínimo (colecciones más rápido)
  • intenta utilizar estructuras en lugar de clases
+0

Sugeriría cambiar el título para "... mejorar .NET compact frameworok ..." para que los resultados de búsqueda sean un poco menos engañosos. – cdiggins

Respuesta

12

La clave es entender cómo funciona el CF GC para las asignaciones. Se trata de un GC no generacional de marcado y barrido simple con algoritmos específicos para lo que activará un GC, y lo que causará la compactación y/o cabeceo después de la recolección. No hay casi nada que pueda hacer a nivel de aplicación para controlar el GC (el único método disponible es Recolectar, y su uso es bastante limitado, ya que no puede forzar la compactación de todos modos).

La reutilización de objetos es un buen comienzo, pero mantener el número de objetos bajo es probablemente una de las mejores herramientas, ya que todas las raíces se deben recorrer para cualquier operación de recolección. Mantener esa caminata corta es una buena idea. Si la compactación te está matando, entonces prevenir la fragmentación del segmento te ayudará. Los objetos> 64k pueden ser útiles en ese sentido, ya que obtienen su propio segmento y se tratan de manera diferente que los objetos más pequeños.

Para entender realmente cómo funciona el CF GC, recomendaría ver el MSDN Webcast on CF memory management.

2

Uno un hecho importante es mantener la vida de sus objetos lo más corta posible.

+1

No necesariamente. Muchos objetos pequeños y de vida corta harán que el GC sea mucho peor que solo unos pocos objetos grandes y longevos, y de hecho agravará su problema. Esta es * no * una máquina de escritorio con memoria de escritorio y recursos de procesador – ctacke

+0

Me parece recordar que el consejo de MS es mantener los objetos lo más efímeros posible. Los objetos que sobreviven a la generación 0 son más problemáticos. –

+0

Encontré una referencia a un artículo de MSDN sobre esto. Parece ser una disminución de x10 por generación de memoria. El artículo está en: http://msdn.microsoft.com/en-us/magazine/dd882521.aspx#id0400035 –

2

La cuestión de la estructura frente a la clase es compleja ... por ejemplo, puede terminar fácilmente utilizando un lote más espacio de pila. Y ciertamente no quieres estructuras mutables. Pero los otros puntos parecen razonables, siempre y cuando no estés doblando el diseño fuera de forma para acomodarlo.

[editar] Otro problema común es la concatenación de cadenas; si está haciendo una concatenación en un bucle, use StringBuilder, que eliminará un lote de cadenas intermedias. ¿Podría ser que GC está ocupado recogiendo todas las tensiones abandonadas de tus hilos?

2

Otra opción sería recolectar manualmente la basura durante horas no pico en su aplicación usando GC.Collect() (suponiendo que esté disponible en CF). Esto podría reducir los objetos necesarios para la limpieza más adelante en su aplicación.

0

Escuché un show .NET Rocks en Rotor 2.0. Si eres realmente hardcore, puedes descargar Rotor, modificar la fuente y usar tu propio recolector de basura modificado.

En cualquier caso, ese podcast tiene buena información sobre el GC. Recomiendo escucharlo.

3

El aspecto más importante es minimizar la tasa de asignación. Cada vez que se asigna un objeto, necesita GC más tarde. Ahora, por supuesto, si el objeto es small o shortlived se clavará en la generación joven (siempre que el GC sea generacional). Los objetos grandes tienden a ir directamente a la arena de tenencia. Pero evitar tener que recolectar es aún mejor.

Además, si puede tirar cosas en la pila, disfrutará de mucha menos presión en el GC. Podría intentar jugar con las opciones de GC, pero creo que sería mucho mejor que lo ayudara con un generador de perfiles de asignación, para que pueda encontrar los puntos que generan los problemas.

Lo que se debe tener en cuenta es el peso de las bibliotecas y marcos estándar. Envuelve un par de objetos y se llenará bastante rápido. Recuerde, cada vez que algo sucede en el GC-Heap, usualmente usa un poco más de espacio para la contabilidad del GC.Por lo tanto, sus 1000 punteros asignados individualmente son mucho más grandes que una matriz/vector de los mismos punteros ya que estos últimos pueden compartir la contabilidad del GC. Por otro lado, este último probablemente permanecerá vivo por mucho más tiempo.

+2

El CF es no generacional, es puramente marca y barrido. – ctacke

Cuestiones relacionadas