Используя GHC 7.0.3, я могу воспроизвести ваше тяжелое поведение GC: * 1001 *
$ time ./A +RTS -s
%GC time 92.9% (92.9% elapsed)
./A +RTS -s 7.24s user 0.04s system 99% cpu 7.301 total
Я потратил 10 минут на просмотр программы.Вот что я сделал по порядку:
- Установить флаг -H GHC, увеличить пределы в GC
- Проверить распаковку
- Улучшить встраивание
- Отрегулируйте область выделения первого поколения
Получив 10-кратное ускорение, и GC примерно в 45% времени.
По порядку, используя магический флаг GHC -H
,мы можем немного сократить время выполнения:
$ time ./A +RTS -s -H
%GC time 74.3% (75.3% elapsed)
./A +RTS -s -H 2.34s user 0.04s system 99% cpu 2.392 total
Неплохо!
Прагмы UNPACK на узлах Tree
ничего не сделают, поэтому удалите их.
Inlining update
сокращает время выполнения:
./A +RTS -s -H 1.84s user 0.04s system 99% cpu 1.883 total
, как и Inline height
./A +RTS -s -H 1.74s user 0.03s system 99% cpu 1.777 total
Таким образом, пока GC все еще доминирует -- поскольку мы проверяем распределение, в конце концов.Одна вещь, которую мы можем сделать, это увеличить размер первого поколения:
$ time ./A +RTS -s -A200M
%GC time 45.1% (40.5% elapsed)
./A +RTS -s -A200M 0.71s user 0.16s system 99% cpu 0.872 total
И увеличение порога развертывания, как предположил ДжонЛ, немного помогает,
./A +RTS -s -A100M 0.74s user 0.09s system 99% cpu 0.826 total
, что в 10 раз быстреечем мы начали?Неплохо.
Используя ghc-gc-tune , вы можете видеть время выполнения как функцию -A
и -H
,
Интересно, что для лучшего времени работы используются очень большие значения -A
, например
$ time ./A +RTS -A500M
./A +RTS -A500M 0.49s user 0.28s system 99% cpu 0.776s