Closed antonkalinin-ml closed 3 years ago
О, вот это хороший поинт. На самом деле мне пока вариант с настройкой чисто для докера нравится больше, а для глобальных конфигов мы можем в README добавить пару строчек — новички оттуда могут узнать и каждый для себя по желанию сам настроит :)
Протестировал с разными опциями. Похоже, ничего делать не надо, настройки по умолчанию оптимальны (если не считать stack build --fast
), а я себе сделал только хуже :).
Опция ghc -j
для сборки зависимостей это какая-то катастрофа (не путать со stack build -j
). С ней процессор отлично загружен на 100% на всех ядрах, зато зависимости билдятся в 4 раза дольше.
В докере этап stack build --only-dependencies
раньше занимал 8 минут:
real 8m13.865s
user 25m33.870s
sys 2m0.827s
После добавления строчки RUN /bin/echo -e 'ghc-options:\n "$everything": -j' >> "$(stack path --stack-root)"/config.yaml
стало 30 минут:
real 29m51.011s user 348m2.216s sys 91m54.456s
Железо: AMD 4750U, 8 ядер, 16 потоков, 32 Гб RAM. Без докера тоже воспроизводится. SMT отключал, скорость немного подросла - чем меньше потоков, тем быстрее. Абсурд какой-то.
На сборке самого проекта польза от опции есть, но очень незначительная, в районе 10-20%. Больше толку от stack build --fast
.
Сохраню ссылку для истории, как немного ускорить многопоточную сборку: https://rybczak.net/2016/03/26/how-to-reduce-compilation-times-of-haskell-projects/ . Действительно помогает, но при сборке большого количества мелких пакетов (160 зависимостей) однопоточный режим все равно быстрее. Эта ссылка пригодится для подкручивания опций сборки одного большого проекта.
Как минимум можно в Makefile
добавить шорткат для stack build --test --file-watch --fast --pedantic
, чтобы те кто не знали, сразу его увидели в файле и заюзали :)
Проект билдится в докере слишком медленно, в один поток. Сейчас это не так важно, но со временем станет важно, когда вырастут производные проекты. Стек умеет параллельно билдить много пакетов, но каждый пакет по умолчанию собирается в один поток. Это можно исправить, если добавить опцию
-j
в вызовghc
, например, при помощи stack.yaml:Тогда сборка ускорится и в докере, и на ручном вызове
stack build
. К сожалению, это перебьет ghc-options, установленные глобально в~/.stack/config.yaml
, если они там есть (у меня есть), и все зависимости числом 170 штук перебилдятся. Но если этим пользуюсь только я, то нестрашно, сделаю как у всех.Другой вариант - положить эту настройку в глобальный конфиг стека в образе докера, но это повлияет только на докер, а не на
stack build
вручную. Чтобыstack build
билдил параллельно, придется править глобальный конфиг на своей машине, что, наверное, более правильно, но новички об этом не не знают.Что думаете, какой вариант лучше?
Еще вопрос на подумать: stack по умолчанию билдит все с опцией оптимизации
-O
. Слишком долго для отладочных билдов - опция-O0
билдит в 2-3 раза быстрее, недостаточно оптимально для продакшена - есть еще-O2
(хотя пишут, что-O2
от-O
мало отличается). Я себе поставил в глобальном конфиге-O2
для$everything
и-O0
для$locals
. Так зависимости, которые билдятся и меняются редко, оптимизируются по максимуму, а проект, который меняется часто, билдится максимально быстро.stack build --fast
также активирует-O0
, но сколько людей знают эту опцию и не поленятся ее вводить? Мне видится, что дефолтный режим должен быть без оптимизации как самый простой, а релизные сборки можно сделать и с дополнительным ключом, все равно это делает пайплайн и разная автоматика. Как вы обычно делаете в других проектах?