2015-01-18 21 views
39

Sto eseguendo un programma Haskell di lunga durata che trattiene molta memoria. Correndo con +RTS -N5 -s -A25M (dimensioni del mio cache L3) Vedo:Ottimizza l'utilizzo del GC Haskell

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 

Il tempo di GC è l'87% del tempo totale di esecuzione! Sto eseguendo questo su un sistema con una quantità enorme di RAM, ma quando ho impostato un valore alto -H le prestazioni erano peggiori.

Sembra che sia -H e -A controlla la dimensione di gen 0, ma quello che mi piacerebbe davvero fare è aumentare le dimensioni del gen 1. Qual è il modo migliore per farlo?

+6

Generalmente accade quando molte cose sopravvivono inutilmente alla generazione vivaistica, rendendole più costose da raccogliere. La prima cosa da controllare è una perdita di spazio che impedisca la raccolta immediata di valori di breve durata. – Carl

+0

Correlati (una risposta può o non può aiutarti, a seconda di cosa sta succedendo nel tuo caso): http://stackoverflow.com/questions/27630833/is-it-possible-to-skip-the-neryery – dfeuer

+1

Start ottenendo un profilo heap. per esempio. http://stackoverflow.com/a/3276557/83805 –

risposta

1

Come suggerito da Carl, è necessario controllare il codice per individuare eventuali perdite di spazio. Immagino che il tuo programma richieda davvero molta memoria per una buona ragione.

Il programma ha impiegato 2820.18 facendo il GC principale. Puoi abbassarlo riducendo l'utilizzo della memoria (non a caso supponendo) o il numero delle raccolte principali. Hai un sacco di RAM libera, in modo da poter provare -Ffactoroption:

-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. 

Nel tuo caso non c'è ~ 3G di dati in tempo reale. Per impostazione predefinita, il GC principale viene attivato quando l'heap aumenta fino a 6G. Con -F3 verrà attivato quando l'heap cresce fino a 9G, risparmiando circa 1000 ore di CPU.

Se la maggior parte dei dati in tempo reale è statica (ad esempio, non cambia mai o cambia lentamente), allora sarà interessato a stable heap. L'idea è di escludere i dati a lunga vita dai principali GC. Può essere raggiunto per es. utilizzando compact normal forms, anche se è già not merged in GHC.