[devel] atime-based "no need to rebuild"

Alexey Tourbin at на altlinux.ru
Чт Май 17 08:19:46 MSK 2012


Мужчины, у вас медленно задания собираются.  Потому что при повторном
запуске выполняется пересборка всех пакетов, а оптимизация "no need to
rebuild" срабатывает только при очень строгом условии: список пакетов
в чруте должен быть полностью идентичным, с точностью до конкретной сборки
каждого пакета (пересобранный пакет уже не идентичен).  Далее я обсуждаю
другие критерии для повторной пересборки и как их можно использовать для
дальнейшей оптимизации.

Есть два основных аспекта этой проблемы.

1) После повторной пересборки в пакете появляются новые значения st_mtime,
основанные на текущем времени; это в свою очередь запускает каскад
пересборок, даже если содержимое файлов в пакете не меняется.
Следовательно, чтобы остановить этот каскад, в качестве критерия
пересборки нужно учитывать только содержимое файлов (md5 суммы).

2) Некоторые пакеты во время сборки просто не используются.  Например,
пакет cpio редко используется при сборке, но он входит в базовую сборочную
среду; его обновление запустит лишнюю пересборку какого бы то ни было
пакета.  Такие ситуации возникают и за пределами базовой сборочной среды.
Следовательно, в качестве критерия пересборки нужно учитывать только
фактически используемые пакеты.

Исходя из этих соображений я реализовал альтернативный/дополнительный
критерий, который учитывает использование файлов в чруте.  В двух словах,
он работает так: при первой сборке отслеживаются фактически используемые
файлы (на основе разницы между st_mtime/st_ctime и st_atime).  Перед
началом повторной сборки используемые файлы проверяются: если они
совпадают (с точностью до md5 сумм), то пересборка не требуется.

http://git.altlinux.org/people/at/packages/girar-builder.git

Несколько точнее, перед самым началом сборки, когда все пакеты
BuildRequires уже установлены, запускается специальная программа, которая
"сбрасывает" st_atime у всех файлов в чруте.  Эту программу пришлось
написать на Си, потому что там есть тонкости.  Сбрасывать st_atime
требуется, чтобы он обновлялся на файловых системах, смонтированных с
опцией relatime (которая используется по умолчанию).  Затем запускается
сборка, и после ее завершения запускается другая программа, которая ищет
в чруте все "использованные" файлы (у которых st_atime > st_mtime/ctime).
Эта схема отслеживания достаточно надежна, поскольку псевдопользователь
builder не может изменить атрибуты запакованных файлов, принадлежащих
псевдопользователю rooter.

Некоторые файлы отслеживать не нужно.  Например, в базе /var/lib/rpm/
содержатся значения st_mtime всех файлов, которые как бы дублируют
значения st_mtime в реальной файловой системе (от которых мы как раз
пытаемся избавиться).  В /var/cache/ldconfig/ содержатся значения st_ctime
библиотек.  В /etc/passwd содержатся численные идентификаторы
псевдопользователей rooter и builder, которые отличаются на сборочных
нодах.  Самое спорное решение - не отслеживать файлы в /usr/share/doc/.
Я обосную его чуть ниже.

Список использованных файлов не может быть исчерпывающим критерием.
Например, при первой сборке в чруте может отсутствовать библиотека foo.
Скрипт configure скажет "checking for libfoo... no", т.е. программа
соберется в конфигурации без libfoo.  Если для повторной сборки установить
в чрут libfoo-devel, то ранее использованные файлы могут быть полностью
идентичны, но результат сборки изменится, поскольку в чруте появились
новые файлы.  Следовательно, полный критерий должен учитывать все файлы
в чруте, но для неиспользуемых файлов нужно учитывать только имя (без md5
суммы).  Теперь становится понятно, почему я предлагаю не отслеживать
содержимое /usr/share/doc/: каталоги в /usr/share/doc/ традиционно
включают в себя версию пакета, т.е. при сборке новой версии какого-либо
пакета будет срабатывать критерий изменения списка неиспользуемых файлов.
Если вернуться к примеру с cpio, это выглядит нежелательно.

Наконец, остается вопрос: нужно ли учитывать симлинки?  С одной стороны,
симлинки не содержат самостоятельных данных.  С другой стороны, легко
придумать контрпример: если симлинк 'gcc -> gcc4.5' заменить на 'gcc ->
gcc4.6', то результат сборки может серьезно измениться.  Короче, симлинки
"перекраивают" файловую систему, и их можно рассматривать как миниатюрные
конфигурационные файлы.  Пути симлинков учитываются наравне с md5 суммами
файлов.

Эти изменения привносит несколько новых файлов в задание: кроме
chroot_base и chroot_BR (списки пакетов), в каждом каталоге появятся
файлы chroot_fused и chroot_funused (списки использованных и
неиспользованных файлов).  Кроме того, если выполняется повторная сборка,
то добавляются файлы chroot_pdiff и chroot_fdiff, из которых можно понять
причину пересборки.

Насколько было возможно, я протестировал эти изменения.


Подробная информация о списке рассылки Devel