[devel] Мухи и котлеты: основная ошибка дизайна сборочницы.

Igor Vlasenko vlasenko на imath.kiev.ua
Вс Авг 30 02:03:00 MSK 2020


Мухи и котлеты: Основная ошибка дизайна сборочницы.
___________________________________________________

Тема улучшения сборочницы почему-то пугает народ.
Что же это такое страшное и непонятное?

Попробую объяснить на пальцах.

Основная ошибка дизайна еще той, первой, последовательной
сборочницы была в том, что для и репозиториев, и для task'ов
использовался один и тот же ID.
ID репозитория можно увидеть через симлинк:
/ALT/repo/sisyphus/release/latest -> ../task/257002/
Удобная экономия на метаданных:
По одному ID можно определить, что репозиторий ID 257002
сделан из репозитория ID 257001 и task'а ID 257002.

Но task'и и репозитории --- это разные сущности.
Их смешивать --- это как смешивать мухи и котлеты.

Из-за смешения понятий в нашей сборочнице
появилось удивительное ограничение: на одну котлету
(репозиторий) может сесть только одна муха (task).

Другими словами, к каждому task'у жестко прибит
выпуск отдельного репозитория.

Это ограничение и не дало впоследствии переделать нашу
сборочницу в по настоящему параллельную.

Рассмотрим на примере.
Пусть человек1 ... человекN работали с утра
до обеда и перед уходом на обеденный перерыв
одновременно залили в Сизиф (репозиторий1500000)
пакет1... пакет256 в виде task'ов таск1500001...таск1500256
(порядок получился случайным)
со средним временем сборки task'а 5 минут.
Выпуск репозитория -- процесс не быстрый
(genbasedir c с кешем 10+секунд, потом mkaptbox, 10+секунд,
еще другие тесты. для простоты положим 0.5 минуты).

Во времена последовательной сборочницы эти task'и
выстроились бы в очереди, и окончания их сборки
пришлось бы ждать сутки (256*5.5, 23 с половиной часа).

С другой стороны, в параллельной сборочнице,
за которую я агитирую, каждый task собирался бы
параллельно на своем ядре, и на отдельном ядре
работал бы процесс выпуска репозитория,
который выпустил бы не 256 новых репозиториев,
а 5-10, пока task'и не кончились бы.
Среднее время ожидания выхода нового сизифа с task'ом --
5.5 минуты. Это хорошая иллюстрация,
зачем нужна производительная сборочница.
Сделал что-то и изменения почти сразу вступают в силу,
не нужно ждать до суток, как у последовательной сборочницы.

Разница всего лишь в параллельных алгоритмах --
железо используется на два порядка эффективнее.

Теперь вернемся к той сборочнице, которая есть сейчас.

На картинке
https://pbs.twimg.com/media/CPGh7UvUEAAcaAB.jpg:large
изображена основная проблема многопроцессорных кластеров --
однопоточные приложения. На картинке один поток работает
с лопатой в яме, а вокруг целая бригада потоков в режиме
ожидания его морально поддерживает.

Это хорошая иллюстрация к нашей сборочнице.
Ее можно описать моделью чайной. В ней работает 256 поваров,
которые заваривают чай со всеми тонкостями чайной церемонии.
Потребители --- огромное море-репозиторий туристов на
зимней морозной площади, которое выпьет
любое количество горячего чая.

Однако поварам работать на площади запрещено,
они работают в отдельном комфортном чайносборочном цеху,
а для продажи чая отсылают стаканы с готовым горячим чаем
через парнишку-официанта (процесс выпуска репозитория).

Итак, как работает модель нашей сборочницы.

Поставщики человек1 ... человекN одновременно поставили в цех
пакет_чая1... пакет_чая256. Повар1 ... повар256 одновременно
начали чайную церемонию, проверили пакеты (негодные в FAILED)
через 5 минут заварили горячий чай и ... выстроились в очередь
(AVAITING 1.2) к парнишке-официанту!

Ведь по правилу "одна муха на одну котлету" официанту брать
более одного стакана на доставку запрещено, а путь к площади
не близкий!

Что делать поварам, когда их очередь не подошла?
Раньше они стояли с термометром и когда чай остынет, то
время от времени подогревали его заново (AVAITING 1.3, 1.4, 1.5, ...)
Помню, своими глазами видел AVAITING 1.27. AVAITING 1.3х? Не помню.
Но Дмитрий со временем навел порядок в этом безобразии.
Лишние печи для подогрева были проданы, и теперь ими
пользоваться могут лишь первые 6(?) поваров ближе всех
в очереди к официанту. Остальные повара просто стоят в очереди
без дела, держа свой остывающий чай.

Реформа параллелизма -- это выдать парнишке корзинку или тележку
на 16x16=256 стаканов, чтобы у поваров очередь просто не могла возникнуть.
Очевидная реформа, почему ее воспринимают в штыки?

Конечно, эта модель не точная.

Во первых, есть еще архитектуры, и на разных архитектурах
разное количество поваров.

Во вторых, в нашей сборочнице официант не выделен в отдельную
должность, и на самом деле бегает на площадь официантом тот
повар, которому пришла очередь. Это решение по ряду причин
хуже решения с явно выделенными официантами.
К примеру, сейчас на редких архитектурах повара, похоже,
тоже бегают официантами, а ведь их зарплата выше.
Если разделить процессы BUILD и MERGE, то выпуск репозитория
для всех, в т. ч. экзотических архитектур,
можно поручить более дешевым x86_64 узлам,
тем самым увеличив общую скорость работы по всем архитектурам.

В третьих, если собрать 256 стаканов на тележку,
то ее с малой вероятностью может заклинить пакетами,
нарушившими обратную совместимость. Поэтому одного официанта мало,
см. https://www.altlinux.org/Girar/Parallel,
для сохранения производительности можно, к примеру,
набрать Log2(256)=8 официантов, каждый копирует (магия software)
стаканы в свою конфигурацию,
к примеру, они берут 1 стакан, 2, 4, 8, 16, 32, 64, 128 и 256 стаканов,
и гарантированно хотя бы один донесет свою тележку.
В самом худшем случае будет производительность сегодняшней сборочницы,
но обычно будет на порядки быстрее.

Ранее я неудачно сравнил модернизацию сборочницы с постройкой шоссе.
потому что слово постройка вызвало реакцию лишними расходами.
К примеру Антон Фарыгин не принял аналогию -
AF> не надо строить <в сборочнице> хайвей.

По моему опыту, скорректировать дизайн --- проблема не слишком затратная.
По железу наш сборочный кластер тянет на шестиполосную магистраль,
но дорожная разметка (софт) там рисует лишь велосипедную дорожку
и пешеходные зоны. Чтобы получить магистраль, достаточно
перерисовать разметку.

Я не понимаю этого мазохизма. Деды часами таски ждали
и мы часами будем ждать?

Когда я начинал autoimports, то сборки обновлений тянулись сутками.
Сел за матчасть, распараллелил и оптимизировал сборочный процесс,
и теперь у меня сборка обновлений на тысячи пакетов занимает пол часа- час.

А наша сборочница меня просто раздражает своей медлительностью.
При чем это та проблема, которая не решается деньгами.
К примеру, купим мы кластер на 4196 поваров.
Будет ли сборочница работать в 16 раз быстрее? Нет,
будет тормозить как и раньше. Разве что в новом железе
удельная производительность на одно ядро должна быть на 10-15% больше,
следовательно, наш парнишка официант может бегать на 10-15%
быстрее. А может и нет, в процессе выпуска репозитория I/O играет роль
большую, чем CPU.

-- 

I V


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