[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