Подтвердить что ты не робот

Оптимизация использования GC Haskell

Я запускаю долговременную программу Haskell, которая хранит много памяти. Запуск с +RTS -N5 -s -A25M (размер моего кеша L3) я вижу:

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

Время GC составляет 87% от общего времени работы! Я запускаю это в системе с огромным количеством ОЗУ, но когда я установил высокое значение -H, производительность была хуже.

Кажется, что как -H, так и -A управляет размером gen 0, но мне бы очень хотелось увеличить размер gen 1. Каков наилучший способ сделать это?

4b9b3361

Ответ 1

Как предложил Карл, вы должны проверить код на утечку пространства. Я предполагаю, что ваша программа действительно требует большой памяти по уважительной причине.

Программа потратила 2820.18s на выполнение основного GC. Вы можете снизить его, уменьшив использование памяти (не по предположению) или количество основных коллекций. У вас много свободной памяти, поэтому вы можете попробовать -Ffactor option:

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

В вашем случае есть ~ 3G живых данных. По умолчанию основной GC будет срабатывать, когда куча вырастет до 6G. С помощью -F3 он будет срабатывать, когда куча вырастет до 9G, экономя ваше процессорное время ~ 1000.

Если большинство живых данных являются статическими (например, никогда не меняются или меняются медленно), вас будет интересовать стабильная куча. Идея состоит в том, чтобы исключить длительные данные о жизни из основного ГК. Это может быть достигнуто, например, используя компактные нормальные формы, хотя не объединяется в GHC пока.