Лінійний інженер Муфіз Амджад опублікував детальний звіт про те, як компанія переробила свій конвеєр безперервної інтеграції після того, як агенти кодування штучного інтелекту перетворили CI на її найгірше вузьке місце — скоротили час очікування запиту на отримання з шести хвилин до трохи більше п’яти, а її тестові набори зросли майже в чотири рази з початку року.

Публікація, опублікована в інженерному блозі Linear 21 вересня, починалася, як це часто буває, з короткого запиту згори. На початку цього року Амджад відкрив Linear і виявив, що Туомас, технічний директор компанії, поставив йому завдання під назвою «Витрати на CI високі» — і попросив його зробити CI швидшим, поки він це робить. Щоб дізнатися більше про цю історію, перегляньте наш поточний висвітлення індустрії ШІ.

Коли агенти випереджають перевірку

Проблема структурна, а не випадкова. «Агенти експоненціально пришвидшили надсилання коду, — написав Амджад, — але перевірка цих змін не продовжувалася з такою ж швидкістю». Кожен запит на отримання все ще має проходити через CI, тому, коли розробка прискорюється, CI стає перешкодою, що підвищує витрати на інфраструктуру та змушує розробників та їхніх агентів довше чекати відгуків.

Лінійний, оптимізований для двох показників: як довго PR чекає на CI та скільки часу виконання він споживає. Результати після місяців роботи: незважаючи на те, що набори тестів зросли майже в чотири рази з січня, час очікування запиту на підключення скоротився з понад шести хвилин до трохи більше п’яти, а час виконання тесту скоротився приблизно вдвічі.

Робота загалом поділялася на чотири категорії: модернізація інфраструктури та інструментів, оптимізація завдань, які обмежують іншу роботу, скорочення повторного налаштування та підвищення ефективності виконання тестів. Кодовою базою Linear є здебільшого TypeScript, але багато оптимізацій застосовуються до різних мов і інструментальних ланцюжків.

Швидші машини та власний компілятор

Деякі з найперших досягнень майже не вимагали оптимізації самої КІ. Перенесення робочих навантажень із GitHub Actions на сторонні програми із швидшими ЦП, високопродуктивним сховищем і кращою інфраструктурою кешу негайно окупилося: у порівнянні двох днів з обох сторін перемикання завдання виконувалися в середньому на 34% швидше, а деякі робочі навантаження, як-от `tsc`, впали на 52%.

Модернізація інструментального ланцюга додала перемоги. Перехід на `tsgo`, рідний компілятор TypeScript, скоротив тижневу медіану перевірки типу на 73% — достатньо, щоб повністю усунути вузьке місце з перевірки типу.

Лінтинг без графа типу

Лінтінґ був ще однією ранньою ціллю. Декілька користувацьких правил ESLint Linear залежали від інформації про тип TypeScript, що змушувало кожен запуск lint будувати повний графік типів перед їх оцінкою, що робило linting одним із завдань CI, які потребують найбільшої кількості пам’яті.

Команда переписала правила для використання статичного аналізу над абстрактним синтаксичним деревом, ідентифікуючи функціональні конструкції та захисні шаблони без будь-якої інформації про тип. Це дозволило ESLint повністю відмовитися від TypeScript, зменшивши час обробки API на 68% і час обробки повного сховища на 55%, при цьому використання пам’яті суттєво зменшилося. Це також спростило пізнішу міграцію на Oxlint, що ще більше скоротило хвилини CI runner, витрачені на лінтування.

Скорочення критичного шляху

Завдяки швидшим окремим перевіркам Linear зменшив масштаб і розглядав CI як систему. Це привернуло увагу до невеликих завдань, які стоять перед усім іншим — виявлення зміни шляху та перевірки кешу результатів тестування, які перебувають на рівні завдання, тобто жоден із восьми сегментів тестування API не може розпочатися, доки не завершиться.

Виправлення були детальними, але додатковими. Обмеження глибини отримання підняло найповільніший шлюз з 94 секунд до 20. Повністю вилучивши перевірку з завдань, які ніколи не потребували робочого дерева, скоротили їх з 27 секунд до 7. Розріджена перевірка без плям із обмеженою історією заощадила ще 11 з гаком секунд для подій надсилання та черги злиття. Загалом середня тривалість завдання виявлення змін впала з 26 секунд до 8, його p90 — з 31 до 12, а його найповільніший запуск — зі 138 секунд до 37.

Над надійністю Checkout теж потрібно було попрацювати: оскільки сторонні розробники перебувають поза мережею GitHub і покладаються на пряме IP-з’єднання, періодичне погіршення якості з’єднання час від часу призупиняло вибірку. Лінійно замінено `actions/checkout` на власну складену дію, яка повторює спробу з відстрочкою, встановлює `GIT_HTTP_LOW_SPEED_LIMIT` і `GIT_HTTP_LOW_SPEED_TIME`, тому з’єднання, що зупинилося, переривається приблизно через 30 секунд, а не зависає, і використовує кеш перевірки, який зберігає постійне дзеркало git на липкому диску.

Одне тонке виправлення усунуло зайвий час у черзі злиття: маркери кешу записувалися як частина остаточної перевірки перед злиттям, тому PR міг сидіти в черзі навіть після того, як його тести пройдено. Перенесення цього запису до завдання без шлюзу зменшило 42 секунди від шляху злиття для кожного запиту на отримання API та запису черги злиття. Разом ці зміни приблизно на хвилину скоротили обов’язкові перевірки API PR на промахи кешу, одночасно зменшивши кількість запусків бігунів.

Менше втрачених секунд на завдання

Налаштування останньої категорії атаки повторюються для кожного завдання. Кожен тестовий шард API витрачав від 7 до 8 секунд на встановлення того самого клієнта Postgres з apt під час кожного запуску; переміщення його в невелике базове зображення CI поряд із Node означало, що фрагменти могли почати бути готовими до запуску. Пізніше команда додала до зображення власні заголовки збірки після того, як виявила, що їх завантаження під час налаштування іноді може зависати.

Чому це викликало резонанс

Публікація вразила розробників: вона потрапила на першу сторінку Hacker News, зібравши приблизно 250 балів і близько 280 коментарів протягом дня. Реакцію легко пояснити — досвід Linear називає вартість розробки за допомогою ШІ, з якою більшість інженерних організацій стикаються лише зараз. Агенти, які генерують запити на отримання за лічені хвилини, все ще чекають на конвеєрах перевірки, розроблених для людського ритму, і кожна хвилина цього очікування множиться на кожного агента, що працює паралельно.

Урок із переробки Linear полягає в тому, що вузьке місце можна усунути, але лише завдяки непривабливому накопиченню багатьох дрібних виправлень — швидших бігунів, дешевших перевірок типів, правил лінту на рівні синтаксису, обмежених вибірок, стійких перевірок, попередньо зібраних зображень — а не будь-якої окремої срібної кулі.

---

Будьте попереду ШІ

Отримуйте останні новини штучного інтелекту, аналіз і прориви — усе в одному місці.

Читати більше новин AI →