Hasher на tmpfs¶
Перенос hasher-chroot на tmpfs — файловую систему Linux в памяти — делает сборку примерно в 7 раз быстрее, чем на том же оборудовании с SSD, и, что не менее важно, бережёт диск: иначе каждая сборка в hasher писала бы гигабайты короткоживущих данных (распакованные исходники, объектные файлы, деревья %install, RPM, кэши apt), которые через несколько минут удаляются. Держать эту круговерть в RAM — это прямое продление ресурса SSD/HDD для всех, кто собирает пакеты регулярно. Цена — оперативная память: chroot, распакованные исходники, промежуточный %install-корень и все RPM, произведённые в ходе сборки, живут в RAM до тех пор, пока не отработает cleanup hasher'а.
Главное удобство со стороны zoryn — то, что делает этот сценарий практичным на каждый день: если hasher_dir — это симлинк на несуществующий каталог, zoryn создаёт целевой каталог перед каждой сборкой. Поэтому симлинк на путь внутри /tmp «самовосстанавливается» после каждой перезагрузки — не нужна запись в fstab, не нужен mkdir в .profile, вообще ничего не нужно помнить.
Почему tmpfs¶
Две причины, и обе важные:
Скорость. Сборка в hasher — это много мелких записей: тысячи файлов в %install, сотни проб configure, постоянная установка/удаление BuildRequires через apt. На SSD всё это упирается в IOPS и fsync; на tmpfs это просто memcpy. Итоговое ускорение на типичных пакетах ALT (shell, python, небольшие C-библиотеки) — около 7×. Тяжеловесы, упирающиеся в компиляцию (chromium, ядро, LLVM), ускоряются заметно меньше — но даже там только %install и cleanup вместе экономят минуты на каждой сборке.
Износ диска. Каждая сборка в hasher пишет несколько гигабайт и тут же удаляет почти всё: chroot распаковывается, используется и сносится; деревья %install собираются и запаковываются в RPM; кэши apt переписываются при каждом изменении конфигурации. На SSD это десятки ГБ TBW в день у активного мейнтейнера, на жёстком диске — часы движения головок. Перенос всего этого в RAM означает, что на постоянный носитель ложатся только финальные SRPM/RPM, которые вы действительно хотите сохранить — ресурс диска перестаёт зависеть от того, как часто вы собираете.
Компромиссы¶
- Бюджет RAM. База sisyphus x86_64 hasher — ~1,2 ГБ после установки; плюс исходники, объектные файлы, дерево
%installи готовые RPM — рабочий набор среднего пакета 3–5 ГБ. Столько свободной RAM должно быть сверх того, что потребляет сам процесс сборки. Память сама между сборками не освобождается — см. Освобождение RAM ниже. - Большие пакеты не поместятся. Chromium, LLVM, webkit, libreoffice — всё, что производит десятки ГБ промежуточного вывода, — выест память и получит OOM на tmpfs. Правильный ответ — держать второй билдер на диске специально для тяжеловесов и собирать такие пакеты на нём: tmpfs-билдер остаётся дефолтом для 95% пакетов, а редкие великаны уезжают на дисковый слот явным флагом. См. Двухуровневая схема ниже.
- Состояние не переживает перезагрузку.
/tmpочищается при загрузке. Для самого chroot это безвредно (hasher всё равно пересобирает его с нуля), но кэш apt и ранее собранные RPM в локальном репозитории hasher теряются. С apt-конфигурацией разберётся штатная синхронизация zoryn.
Настройка¶
1. Убедитесь, что /tmp — это tmpfs¶
На современной установке ALT это по умолчанию — /tmp монтируется через tmp.mount из systemd (или через /etc/fstab) как tmpfs с лимитом размера примерно в половину RAM. Проверка:
Если нет — включите:
Размер по умолчанию обычно достаточен. Если вы знаете свой рабочий набор — поднимите его в /etc/systemd/system/tmp.mount.d/override.conf, например Options=size=16G.
2. Сделайте ~/hasher симлинком на путь в tmpfs¶
В ALT для приватного пользовательского tmp принят каталог /tmp/.private/$USER/ — с правами 0700, создаётся автоматически при входе в систему и очищается при перезагрузке. Это и есть правильный родительский каталог для hasher:
Создавать /tmp/.private/$USER/hasher руками не нужно — ради этого и следующий шаг.
3. Доверьте восстановление после перезагрузки zoryn¶
После перезагрузки /tmp (а с ним и /tmp/.private/$USER/hasher) исчезают, и ~/hasher становится «висящим» симлинком.
Делать ничего не нужно. Перед каждой сборкой zoryn build / zoryn builder status / любая команда, которой нужен каталог hasher, выполняет шаг «ensure», который:
- Замечает, что
~/hasher— симлинк. - Разрешает цель (
/tmp/.private/$USER/hasher). - Делает
mkdir -pпо этому пути.
Та же самая логика работает и по SSH для удалённых билдеров — скрипт улетает одним round-trip'ом вместе с проверкой занятости hasher'а. Таким образом любой билдер, у которого hasher_dir — симлинк в tmpfs, самовосстанавливается после перезагрузки и на локальной, и на удалённой стороне.
4. Настройте билдер (необязательно)¶
У встроенного билдера local уже прописан ~/hasher, так что если вы собираете только локально — настраивать ничего не нужно, вся настройка заканчивается шагом 2.
Для дополнительных локальных слотов или удалённых билдеров оставляйте ~/hasher (или его нумерованных соседей) в качестве каталога hasher. Пример на четыре параллельных локальных слота на tmpfs:
ln -s /tmp/.private/$USER/hasher1 ~/hasher_1
ln -s /tmp/.private/$USER/hasher2 ~/hasher_2
ln -s /tmp/.private/$USER/hasher3 ~/hasher_3
ln -s /tmp/.private/$USER/hasher4 ~/hasher_4
zoryn builder add --name local --type local --multi-add 4 \
--hasher-dir='~/hasher_{hasher_number}' \
--repo /srv/repo/sisyphus -y
Шаблон {hasher_number} раскрывается отдельно для каждого слота; все симлинки живут под одним tmpfs-родителем, поэтому четыре слота делят общий лимит /tmp, а не борются за фиксированный бюджет каждый по своему каталогу.
Если хочется обойтись без индиректа через симлинк — указывайте --hasher-dir прямо на путь в tmpfs: функционально это то же самое, просто без одного readlink:
Двухуровневая схема: tmpfs по умолчанию, диск для тяжеловесов¶
На практике хорошо работает схема из двух локальных билдеров: основной на tmpfs (быстрый, на каждый день) и второй на SSD/HDD — для тех немногих пакетов, которые не помещаются в RAM. Выбор, на чём собирать, в такой схеме сводится к явному флагу -b в этих редких случаях — в остальных 95% сборок об этом не нужно думать.
Настраивается один раз:
# Основной tmpfs-билдер (штатный `local` — замените его hasher_dir на
# симлинк в tmpfs по шагу 2 выше, больше ничего настраивать не нужно).
# Второй локальный билдер на настоящем диске:
mkdir -p ~/hasher_disk
zoryn builder add --name disk --type local --number 2 \
--hasher-dir=~/hasher_disk \
--repo /srv/repo/sisyphus -y
Два разных hasher_number позволяют обоим слотам сосуществовать; ~/hasher_disk — обычный каталог в домашней файловой системе, поэтому он не упирается в лимит /tmp и не ест RAM.
Далее на каждый день:
zoryn build # tmpfs — быстрый путь для почти любого пакета
zoryn build -b disk # очередной chromium / LLVM / webkit
Совет: если у вас есть список известных тяжеловесов — достаточно маленького shell-алиаса, прописывать его в конфиге zoryn смысла нет. Настройка билдеров — единственное постоянное изменение.
Освобождение RAM¶
На tmpfs «дисковое место, занятое chroot» — это и есть оперативная память, удерживаемая вашим процессом. С hsh --lazy-cleanup (значение по умолчанию в zoryn) chroot сохраняется между сборками, чтобы прогреть кэши apt и ускорить повторные запуски; прерванные и упавшие сборки тоже оставляют после себя рабочее дерево. После серии сборок легко обнаружить, что /tmp занят на несколько ГБ.
Освободить — так:
zoryn builder clean --all # все билдеры, локальные и удалённые — правильный дефолт
zoryn builder clean --all --dry-run # предпросмотр перед удалением
zoryn builder clean local # конкретный — если нужно очистить только этот слот
--all захватывает все настроенные билдеры, локальные и удалённые; на tmpfs RAM освобождают только локальные слоты, но попутно вычистить удалённые chroot'ы — безобидно и полезно: так и на удалённой стороне /tmp (или SSD) остаётся в порядке. Оснований избегать --all нет.
Каждый clean удаляет hasher-chroot, вспомогательные каталоги и оставшиеся тарболлы, после чего заново создаёт (теперь пустой) каталог hasher — включая авто-создание цели у «висящего» симлинка из шага 3, так что ~/hasher сразу готов к следующей сборке.
Возьмите за привычку: zoryn builder clean --all в конце сборочной сессии или тогда, когда free -h показывает, что RAM опустилась ниже рабочего набора следующей сборки. Автоматического освобождения нет — ядро само не выгружает файлы под смонтированным tmpfs.
Диагностика¶
Failed to create hasher_dir. Родитель целевого пути симлинка не существует, и у zoryn нет прав его создать. Проверьтеls -ld /tmp/.private/$USER— каталог должен существовать и принадлежать вам. Если его нет — перелогиньтесь (PAM создаст его заново) илиsudo install -d -m 0700 -o "$USER" /tmp/.private/$USER.- Chroot переживает перезагрузку. Симлинк указан на каталог не в tmpfs (например,
/home/...). Проверьтеmount | grep tmpfsиreadlink -f ~/hasher. - OOM в середине большой сборки. Рабочий набор пакета превышает размер tmpfs. Не боритесь — пересоберите на дисковом билдере (
zoryn build -b diskиз двухуровневой схемы выше). Повышениеsize=у/tmp— последнее средство: он делится со всем остальным в/tmp, и этот трюк перестаёт работать, как только следующий пакет окажется ещё больше.
См. также¶
- Сборочная ферма — параллельные и удалённые конфигурации.
zoryn builder— справочник команды.