haskell memory-management garbage-collection profiling

Optimizar el uso de Haskell GC



memory-management garbage-collection (1)

Estoy ejecutando un programa Haskell de larga vida que se aferra a mucha memoria. Corriendo con +RTS -N5 -s -A25M (tamaño de mi caché L3) veo:

715,584,711,208 bytes allocated in the heap 390,936,909,408 bytes copied during GC 4,731,021,848 bytes maximum residency (745 sample(s)) 76,081,048 bytes maximum slop 7146 MB total memory in use (0 MB lost due to fragmentation) Tot time (elapsed) Avg pause Max pause Gen 0 24103 colls, 24103 par 240.99s 104.44s 0.0043s 0.0603s Gen 1 745 colls, 744 par 2820.18s 619.27s 0.8312s 1.3200s Parallel GC work balance: 50.36% (serial 0%, perfect 100%) TASKS: 18 (1 bound, 17 peak workers (17 total), using -N5) SPARKS: 1295 (1274 converted, 0 overflowed, 0 dud, 0 GC''d, 21 fizzled) INIT time 0.00s ( 0.00s elapsed) MUT time 475.11s (454.19s elapsed) GC time 3061.18s (723.71s elapsed) EXIT time 0.27s ( 0.50s elapsed) Total time 3536.57s (1178.41s elapsed) Alloc rate 1,506,148,218 bytes per MUT second Productivity 13.4% of total user, 40.3% of total elapsed

¡El tiempo de GC es el 87% del tiempo de ejecución total! Estoy ejecutando esto en un sistema con una gran cantidad de RAM, pero cuando configuré un alto valor de -H , el rendimiento fue peor.

Parece que tanto -H como -A controlan el tamaño de gen 0 , pero lo que realmente me gustaría hacer es aumentar el tamaño de gen 1 . ¿Cuál es la mejor manera de hacer esto?


Como Carl sugirió, debería verificar el código de fugas de espacio. Asumiré que su programa realmente requiere mucha memoria por una buena razón.

El programa gastó 2820.18s haciendo GC mayor. Puede reducirlo reduciendo el uso de memoria (no es un caso según la suposición) o el número de colecciones principales. Tiene mucha RAM libre, por lo que puede probar la option -Ffactor :

-Ffactor [Default: 2] This option controls the amount of memory reserved for the older generations (and in the case of a two space collector the size of the allocation area) as a factor of the amount of live data. For example, if there was 2M of live data in the oldest generation when we last collected it, then by default we''ll wait until it grows to 4M before collecting it again.

En tu caso, hay ~ 3G de datos en vivo. Por defecto, el GC principal se activará cuando el montón crezca a 6G. Con -F3 se activará cuando el montón crezca hasta 9G, lo que le ahorrará ~ 1000s de tiempo de CPU.

Si la mayoría de los datos en vivo son estáticos (por ejemplo, nunca cambia o cambia lentamente), entonces estará interesado en un montón estable . La idea es excluir los datos de larga vida del GC principal. Se puede lograr, por ejemplo, usando formas compactas normales , aunque todavía no se ha fusionado en GHC.