[devel] IХ. Алгоритмы работы сборочницы. O commit. ч.1

Alexey Tourbin alexey.tourbin на gmail.com
Вс Мар 24 03:40:02 MSK 2019


On Sat, Mar 23, 2019 at 1:17 PM Igor Vlasenko <vlasenko на imath.kiev.ua> wrote:
> task merge - это операция, которая получает из репозитория R_n
> и собранного таска B новый репозиторий R_{n+1}.
>
> R_n + B -> R_{n+1}
>
> На этапе task merge в параллельной сборочнице у нас
> возникает проблема, которой в последовательной сборочнице не было.
> Таск B был, вообще говоря, собран не с текущим репозиторием R,
> а с каким-то более старым репозиторием R_k,  k <=n.
> Таск B прошел проверки целостности для R_k,
> но у нас теперь R_n и B может иметь, к примеру, unmets.
>
> Что наша сборочница должна делать на этапе task merge?
> Она должна повторить проверки целостности для B, но
> уже на R_n. Если B проходит проверку, делаем commit
> и получаем новый репозиторий R_{n+1}.
> Иначе возвращаем B в очередь build, на пересборку с R_{n+}.

Ну это большой отход от того, как сейчас сборочная система работает.
Она работает как последовательная серия стадий, последняя стадия -
commit (отсюда и название "task run", проиграть все стадии). При такой
схеме сначала идет сборка пакетов, а потом - генерация нового
репозитория и проверка на unmets. А при вашей схеме получается
шиворот-навыворот: сначала надо сгенерировать репозиторий и проверить
unmets, а потом только собирать пакеты, а потом еще раз сгенерировать
репозиторий и проверить unmets. Не то чтобы это очень серьезный
аргумент против, но это уже как-то по другому мыслится. Также эта
схема более капризна/требовательна к валидности предыдущих результатов
сборки. Сейчас кеширование работает локально, "по месту" (в случае
чего пойдет повторная сборка). В новой схеме надо управлять
суперпозицией состояния "какие сабтаски собрались и прошли все
проверки, чтобы их второй раз не песочить" (напр. если какой-то
сабтаск добавился посередине, то последующие сабтаски надо
сбрасывать). Либо же может быть упрощенный вариант: более или менее
любое изменение в конфигурации сабтасков сбрасывает имеющиеся
результаты сборки у всех сабтасков.

> Что наша сборочница делает, но делать этого не должна,
> против чего я выступаю?
>
> Сборочница просто берет и принудительно пересобирает B на R_n.
> Да, там есть оптимизация - если сборочное окружение пакета
> не изменилось, то его пересборка очевидно избыточна,
> и тогда B коммитится без пересборки, что иногда ускоряет
> сборочницу.
> Однако по сути для не test-only пакетов это та же последовательная
> сборочница. Привязка commit к повторной пересборке
> является в ней узким местом.
>
> И не просто узким в процентах, а узким местом в абсолютных
> величинах, т.е. есть определенный порог, число пакетов,
> которые такая сборочница способна обработать в сутки.
>
> По достижении этого порога сборочница просто захлебнется.
> Но сначала резко увеличится среднее время ожидания
> до попадания пакета в сизиф, пакеты начнут стоять в очередь
> на commit часами, потом сутками,
> появятся AWAITING 1.12, AWAITING 1.18 ...
> начнется грызня, обвинения, что кто-то заливает слишком много пакетов,
> придирки, что пакет залит по недостаточно важной причине,
> рулеж очередью пакетов вручную,
> попытки усложнить майнтайнерам доступ к commit
> (сейчас вот появилась опция --commit, однако ее
> легко заскриптовать; скоро против этого, боюсь, в сборочницу
> и ssh капчу начнут встраивать :)
>
> Если не прекратить это безобразие, и не исправить проблему
> в корне, т.е. не распрямить кривизну в алгоритмах,
> то мы скоро придем к тому, что на доступ к сборочнице
> талоны будут выдавать.

Вы преувеличиваете. Сборочница не захлебнется. Прогресс гарантируется
тем, что один из контендеров всегда коммитится. Остальные уходят на
второй круг. В старых книжках про Unix именно так описан планировщик
процессов: пробуждается несколько процессов, один идет на исполнение,
остальные засыпают до следующего раза. Аналогично pthread_cond_signal
может разбудить несколько тредов (поэтому pthread_cond_wait надо
заворачивать в цикл). В общем, вы жалуетесь на схему, когда ресурс
достается только одному, а остальным - на колу мочало. Но это
распространенная схема.

Теперь поближе к цифрам. Стоимость повторного проигрывания задания на
самом деле состоит из двух частей: константная цена для любого
задания, порядка минуты, плюс переменная цена в зависимости от
количества пакетов, по несколько секунд на пакет. Если в задании много
пакетов, то переменная цена доминирует, и шансы такого задания
закоммититься резко падают (любое другое задание с одним пакетом его
обгонит). Старвейшон это называется по-научному (несправедливое
лишение доступа к ресурсу). Можно попытаться защитить ресурс для
заданий, которые слишком много раз подряд уходят на второй круг.
Например, можно взять эксклюзивный лок на репозиторий. Но если
начинается повторная сборка пакетов, то эксклюзивный лок надо
отпустить! Потому что остальные задания стопорятся на неопределенно
долгое время, а не "несколько секунда на пакет". Справедливость - дело
такое. (Тут часть проблемы чисто техническая - сложно это на шелле
изобразить, взять лок в одном скрипте и отпустить его в другом.)

В общем мне конечно не нравится что большие задания тяжело
закоммитить. Но это не значит, что вся схема негодная. Мне кажется,
что по крайней мере для маленьких заданий пропускной способности
должно хватать. Зачем рекордных показателей добиваться мне не понятно.

> К примеру, по такой логике такие пакеты, как
> янв  4 2005 xlhtml-0.5.1-alt2.src.rpm
> десятилетиями каждый день получают новые поводы, чтобы
> пересобраться, но почему-то до сих пор не пересобраны.
>
> Чем 2 пакета, собранные за 5 минут до прихода в Сизиф
> новой libfoo, хуже, чем 200 пакетов, собранных еще раньше?
> Ничем не хуже. Даже лучше с точки зрения необходимости
> пересборки, так как собраны на более свежем Сизифе.

Вы (в частности) хотите сказать, что вот мы так скрупулезно
отслеживаем влияние пакетов в пределах задания, а когда пакеты все же
попадают в репозиторий, то последующие потенциальное влияние на
пересборку пакетов уже никак не отслеживается. У меня когда-то была
идея сделать "метарепозиторий", в котором как раз бы отслеживались все
промежуточные состояние тестовых пересборок, даже если результат
пересборки отбрасывается. Но что-то до ума я это дело не довел, может
потому что выпивал много. Эх, как там писал Ерофеев, вставай Модест
Петрович, садись дописывать свою божественную оперу Хованщина. А
Модесту Петровичу без выпивки оперу писать вдохновения нету. А как
выпьет, так уж не до оперы.

Все-таки слабое место в вашей схеме -  это суперпозиция валидности при
кешировании. Вы вот пишете, что таск может собираться на каком-либо
старом состоянии репозитория R_k. Если максимально кешировать
результаты сборки, то получится, что таск собирался на состояниях
$R_{k_1},$R{k_2},\ldots$. То есть таск может видеть разные состояние
репозитория. В результате пакеты в таске могут собраться с разными
версиями библиотек!


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