В современном мире разработки программного обеспечения скорость и качество релизов играют ключевую роль в конкурентоспособности компаний. Особенно это касается крупных технологических корпораций, где сотни инженеров параллельно вносят изменения в огромнейшие кодовые базы. Компания Uber, развивающая один из крупнейших в мире сетевых сервисов, сталкивается с серьезными вызовами, связанными с управлением непрерывной интеграцией (CI) и оптимизацией связанных с ней затрат. В стремлении сделать процессы разработки более эффективными, Uber внедрил уникальное решение под названием SubmitQueue, которое сократило расходы на CI почти наполовину и ускорило время ожидания в очереди на более трети. Непрерывная интеграция позволяет объединять изменения разработчиков в общий основной код с минимальными задержками и конфликтами.
В крупных организациях, подобных Uber, где используется монорепозиторий с миллионами строк кода и сотнями микросервисов, поддержание стабильной главной ветки (mainline) становится колоссальной задачей. Главная ветка считается «зеленой», если все сборки, юнит-тесты и UI-тесты проходят успешно для каждого коммита, позволяя оперативно выпускать обновления и исправления. Однако с ростом масштаба проектов и увеличением количества одновременных изменений возникают проблемы, связанные с конфликтами, потерей времени и чрезмерным расходом вычислительных ресурсов для сборок. В Uber SubmitQueue служит фундаментом, который обеспечивает одновременную обработку десятков тысяч изменений ежемесячно, используя шесть крупных монорепозиториев и семь языков программирования. Ключевой особенностью SubmitQueue стала способность предугадывать результаты сборок благодаря построению так называемого дерева спекуляций.
В этой структуре отражаются все возможные варианты сборок для текущих изменений, которые могут конфликтовать или быть независимыми. На базе машинного обучения и вероятностных моделей система определяет, какие сборки наиболее вероятно приведут к успешному результату, и запускает их параллельно. Это помогает минимизировать время ожидания и гарантирует попадание в основную ветку только качественного и проверенного кода. До внедрения улучшений SubmitQueue сталкивался с двумя значительными проблемами, влиявшими на эффективность и стоимость интеграции. Во-первых, при появлении новых изменений, система могла прерывать уже выполняющиеся сборки в пользу тех, у которых вероятность успеха выше по прогнозу.
На практике такой подход приводил к тому, что от 40% до 65% сборок завершались преждевременно, что вынуждало планировать повторные сборки и увеличивало расход ресурсов. Во-вторых, очередь обрабатывала изменения строго в порядке их поступления, из-за чего мелкие и быстрые изменения иногда надолго задерживались за крупными, ресурсоемкими, что негативно сказывалось на скорости релизов. Для решения второй проблемы была внедрена концепция BLRD — Bypassing Large Diffs, что можно трактовать как обход больших изменений. Суть BLRD состоит в том, что если небольшое изменение в обход крупного изменения может быть проверено и подтвердить стабильность, то оно допускается к релизу без необходимости ожидать завершения более длинной и тяжелой сборки. Это стало возможно благодаря анализу коммутативности — свойству, при котором порядок применения изменений не влияет на итоговое состояние кода.
Если результаты сборок для мелкого изменения и его вариаций с большим изменением совпадают, значит их можно смело менять местами без риска поломки. Это значительно сокращает время ожидания для большинства мелких коммитов. Однако даже с BLRD оставалась проблема приоритетов сборок. Старые вероятностные модели SubmitQueue предполагали, что для решения вопроса нужен всего один билд на изменение, а также обрабатывали их по очереди поступления, что не позволяло должным образом учитывать специфику больших и мелких изменений с точки зрения времени и рисков. В следствие этого часть мелких изменений по-прежнему простаивала в очереди, даже имея возможность быть быстро и безопасно интегрированными.
Новая версия SubmitQueue получила обновленную вероятностную модель, которая учитывает множественные сборки на каждое изменение, равномерно приоритезирует все спекулятивные сборки, необходимые для выявления возможности обхода больших изменений, и одновременно присваивает приоритет на основании вероятности успешного прохождения и времени завершения. В частности, для оценки вероятности того, какая сборка будет завершена раньше, применена продвинутая модель NGBoost — технология прогноза с учётом неопределённости и вариативности прошлого опыта сборок Uber. Эта модель учитывает как среднее время сборки, так и дисперсию, что позволяет принимать более точные решения, минимизируя ненужные простои и излишние вычисления. Чтобы не тратить ресурсы впустую, в SubmitQueue введен параметр порога спекуляции. Это минимальное значение вероятности того, что сборка действительно понадобится, ниже которого задания не ставятся в очередь.
Балансировка этого порога крайне важна: слишком высокий порог снижает количество параллельных сборок и скорость обхода крупных изменений, слишком низкий — приводит к неэффективному расходу ресурсов. Основанный на данных мониторинга и особенностях каждого монорепозитория, порог помогает оптимизировать нагрузку. Подробный анализ эффективности данной стратегии был проведен на крупнейших монорепозиториях Uber для языков Go, iOS и Android, насчитывающих сотни миллионов строк кода и тысячи ежедневных изменений. В течение двадцати одной недели велось отслеживание ключевых метрик — соотношения количества сборок к изменениям, расхода CPU и времени ожидания в п95 перцентиле, до и после внедрения новой модели. Результаты пересмотренного SubmitQueue впечатляют.
Соотношение сборок к изменениям снизилось почти вдвое: для Go монорепозитория на 45%, для iOS почти на 48%, а для Android более чем на 64%. Потребление CPU при этом упало пропорционально — от 35% до 52%, позволяя экономить значительные средства на инфраструктуре. Одновременно, p95 время ожидания изменения в очереди во всех случаях уменьшилось примерно на треть. Это означает, что разработчики получили возможность быстрее интегрировать свои изменения, не теряя при этом качества и стабильности кода. Нововведения SubmitQueue подтверждают, что сочетание машинного обучения, продвинутых вероятностных моделей и глубокого понимания процессов разработки позволяет создавать CI-системы, готовые к масштабированию и будущим вызовам.
В условиях постоянно растущего числа изменений и усложнения кодовой базы стремление к уменьшению временных и ресурсных затрат становится не просто желанием, а необходимостью. Uber наглядно демонстрирует, что крупные и сложные проекты можно интегрировать и тестировать быстро, эффективно и даже с сокращением затрат, если применять системный и научный подход. Использование таких методов и алгоритмов, как BLRD и NGBoost, позволяет не просто оптимизировать, а переосмыслить существующие процессы CI и вывести их на новый уровень. В заключение стоит подчеркнуть, что усилия Uber по совершенствованию SubmitQueue не только направлены на снижение затрат и поддержку стабильности основного кода, но и обеспечивают лучшую разработческую культуру, позволяя инженерам быстрее видеть результаты своей работы и стимулируя общую продуктивность. В будущем команда Uber планирует продолжать совершенствовать SubmitQueue, разрабатывая новые алгоритмы и подходы к планированию сборок, чтобы еще более совершенствовать скорость, качество и масштабируемость разработки.
Такой опыт и подход к управлению CI-системами представляют огромный интерес для большинства технологических компаний, стремящихся к масштабируемому и экономичному развитию своих продуктов. Uber показал, что даже в масштабах многомиллионного кода и тысяч разработчиков можно оставаться “зелеными” и быстрыми — и этот опыт задает ориентир всему сообществу разработчиков.