2015-01-18 11 views
39

Używam długowiecznego programu Haskell, który ma dużo pamięci. Biegając z +RTS -N5 -s -A25M (wielkość mojej pamięci podręcznej L3) Widzę:Optymalizacja użycia Gask 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 

Czas GC wynosi 87% całkowitego czasu pracy! Używam tego w systemie z dużą ilością pamięci RAM, ale kiedy ustawiłem wysoką wartość -H, wydajność była gorsza.

Wydaje się, że oba -H i -A kontroluje wielkość gen 0, ale to, co naprawdę chciałbym zrobić, to zwiększyć rozmiar gen 1. Jaki jest najlepszy sposób na zrobienie tego?

+6

Zwykle dzieje się tak, gdy niepotrzebnie wiele rzeczy przeżyje w przedszkolu, co sprawia, że ​​są droższe do zbierania. Pierwszą rzeczą, którą sprawdziłbym, jest natychmiastowy wyciek przestrzeni zapobiegający krótkotrwałym wartościom. – Carl

+0

Powiązane (odpowiedź może Ci pomóc lub nie, w zależności od tego, co się dzieje w twoim przypadku): http://stackoverflow.com/questions/27630833/is-it-possible-to-skip-the-nursery – dfeuer

+1

Uruchom przez uzyskanie profilu sterty. na przykład http://stackoverflow.com/a/3276557/83805 –

Odpowiedz

1

Zgodnie z sugestią Carla należy sprawdzić kod pod kątem wycieków przestrzeni. Zakładam, że twój program naprawdę wymaga dużo pamięci z ważnego powodu.

Program spędził 2820.18s wykonując duże GC. Można go obniżyć, zmniejszając użycie pamięci (nie przez przypadek) lub liczbę głównych kolekcji. Masz dużo wolnej pamięci RAM, więc można spróbować -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. 

W twoim przypadku nie ma ~ 3G danych na żywo. Domyślnie główny GC zostanie wyzwolony, gdy sterty wzrosną do 6G. Z -F3 zostanie wyzwolony, gdy stertka zostanie powiększona do 9G, oszczędzając Ci czas procesora ~ 1000s.

Jeśli większość danych na żywo jest statyczna (np. Nigdy się nie zmienia lub powoli się zmienia), to interesuje Cię stable heap. Chodzi o to, aby wykluczyć dane dotyczące długiego życia z głównych szkół podstawowych. Można to osiągnąć np. przy użyciu compact normal forms, ale jest jeszcze not merged w GHC.