Перейти к основному контенту
Tech Path Finder
КурсыИнтервьюКод-ревьюБлог
Tech Path Finder

Персонализированный путеводитель в IT. Квизы, мок-интервью, код ревью и аналитика прогресса.

@potapov_me

Платформа

  • Курсы
  • Прогресс
  • Мок-интервью
  • Код ревью
  • Живое ревью с ИИ
  • Тренажёр переговоров
  • Закладки

Контент

  • Блог
  • Главная
  • Обратная связь

Компания

  • О проекте
  • Тарифы
  • Условия использования
  • Конфиденциальность
  • Согласие на обработку данных
  • Cookie
  • Реквизиты

Аккаунт

  • Войти
  • Зарегистрироваться
  • Профиль

© 2026 Tech Path Finder. Все права защищены.

·ИП Потапов К.С.·Политика конфиденциальности·
Сделано с ❤️ в России
  1. Параллелизация и оптимизация
parallel_execution

Параллелизация и оптимизация

Распараллеливание тестов, оптимизация времени выполнения пайплайна.

Параллелизация и оптимизация

Параллельное выполнение job и тестов — мощный способ ускорения CI/CD. Правильная параллелизация сокращает время пайплайна в 3–10 раз.

#Зачем нужна параллелизация?

Последовательный пайплайн:

lint (2 мин) → test (10 мин) → build (5 мин) → deploy (3 мин)
Итого: 20 минут

Параллельный пайплайн:

lint (2 мин) ─┐
test (10 мин) ─┤ 2 мин (параллельно)
build (5 мин) ─┘
     ↓
deploy (3 мин)
Итого: 8 минут

#Matrix Strategy в GitHub Actions

#Базовый matrix

jobs: test: runs-on: ubuntu-latest strategy: matrix: node-version: [18, 20, 22] os: [ubuntu-latest, windows-latest] steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version: ${{ matrix.node-version }} - run: npm test

Что происходит:

  • Создаётся 6 комбинаций (3 версии × 2 ОС)
  • Все 6 job запускаются параллельно
  • Каждый job получает свою комбинацию параметров

#Ограничение параллелизма

jobs: test: runs-on: ubuntu-latest strategy: max-parallel: 2 # Максимум 2 job одновременно matrix: node-version: [18, 20, 22, 24]

Зачем ограничивать:

  • Квоты параллелизма (20 для бесплатных аккаунтов)
  • Ограниченные ресурсы (self-hosted runners)
  • Лимиты внешних API (база данных, сервисы)

#fail-fast стратегия

jobs: test: runs-on: ubuntu-latest strategy: fail-fast: false # Не отменять остальные job при ошибке matrix: node-version: [18, 20, 22]

fail-fast: true (по умолчанию):

  • При ошибке одного job остальные отменяются
  • Экономит ресурсы при явной поломке
  • Не показывает полную картину ошибок

fail-fast: false:

  • Все job выполняются до конца
  • Видны все ошибки одновременно
  • Полезно для матриц тестирования

#Исключение из matrix

jobs: test: runs-on: ubuntu-latest strategy: matrix: node-version: [18, 20, 22] exclude: - node-version: 18 include: - node-version: 24 experimental: true

exclude — убирает комбинации из matrix. include — добавляет дополнительные комбинации.

#Параллелизация тестов внутри job

#Проблема

Шаги внутри job выполняются последовательно:

jobs: test: runs-on: ubuntu-latest steps: - run: pytest tests/unit/ # 5 минут - run: pytest tests/integration/ # 5 минут # Итого: 10 минут последовательно

#Решение: тестовый раннер с параллелизмом

pytest с pytest-xdist:

jobs: test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - run: pip install pytest pytest-xdist - run: pytest -n auto # auto = количество CPU # Или явно: pytest -n 4

jest с maxWorkers:

jobs: test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - run: npm test -- --maxWorkers=4

Go с параллельными пакетами:

jobs: test: runs-on: ubuntu-latest steps: - run: go test -p 4 ./... # 4 пакета параллельно

#Sharding тестов

#Что такое sharding?

Sharding — разделение тестов на группы (шарды), каждая выполняется на отдельном job.

Все тесты (1000 тестов, 30 минут)
         ↓
Шард 1: тесты 1–333   ─┐
Шард 2: тесты 334–666  ┤ 10 минут параллельно
Шард 3: тесты 667–1000 ┘

#Реализация через matrix

jobs: test: runs-on: ubuntu-latest strategy: matrix: shard: [1, 2, 3, 4] steps: - uses: actions/checkout@v4 - run: npm install - name: Run tests shard ${{ matrix.shard }} run: | # Разделение тестов по shard npm test -- --shard=${{ matrix.shard }}/4

#CircleCI-style sharding

jobs: test: runs-on: ubuntu-latest strategy: matrix: shard: [1, 2, 3, 4] steps: - uses: actions/checkout@v4 - name: Get test files id: tests run: | ALL_TESTS=$(find tests -name '*.py' | sort) TOTAL_SHARDS=4 SHARD=${{ matrix.shard }} # Разделение на шарды echo "$ALL_TESTS" | \ awk -v shard=$SHARD -v total=$TOTAL_SHARDS \ 'NR % total == shard - 1' > tests_to_run.txt echo "files=$(cat tests_to_run.txt | tr '\n' ' ')" >> $GITHUB_OUTPUT - name: Run tests run: pytest ${{ steps.tests.outputs.files }}

#Использование готовых решений

pytest-shard:

steps: - run: pip install pytest-shard - run: pytest --shard-id=${{ matrix.shard }} --shard-count=4

jest-circleci:

steps: - run: npm install jest-circleci - run: npx jest --shard=${{ matrix.shard }}/${{ strategy.job-total }}

#DAG (Directed Acyclic Graph) в GitHub Actions

#Зависимости между job

jobs: lint: runs-on: ubuntu-latest steps: - run: npm run lint test: runs-on: ubuntu-latest needs: lint # Ждёт завершения lint steps: - run: npm test build: runs-on: ubuntu-latest needs: [lint, test] # Ждёт оба job steps: - run: npm run build deploy: runs-on: ubuntu-latest needs: build steps: - run: ./deploy.sh

#Параллельные ветки DAG

jobs: lint: runs-on: ubuntu-latest steps: - run: npm run lint test-unit: runs-on: ubuntu-latest needs: lint steps: - run: npm run test:unit test-integration: runs-on: ubuntu-latest needs: lint steps: - run: npm run test:integration test-e2e: runs-on: ubuntu-latest needs: lint steps: - run: npm run test:e2e build: runs-on: ubuntu-latest needs: [test-unit, test-integration, test-e2e] steps: - run: npm run build

Выполнение:

lint (2 мин)
   ↓
test-unit ─┐
test-integration ─┤ 5 мин (параллельно)
test-e2e ──┘
   ↓
build (3 мин)
Итого: 10 минут

#Параллелизация в GitLab CI

#parallel keyword (GitLab 15.3+)

# .gitlab-ci.yml test: stage: test image: node:20 parallel: matrix: - NODE_VERSION: ['18', '20', '22'] OS: ['ubuntu-latest', 'windows-latest'] script: - echo "Testing with Node $NODE_VERSION on $OS" - npm test

#Ручное создание параллельных job

test-node-18: stage: test image: node:18 script: - npm test test-node-20: stage: test image: node:20 script: - npm test test-node-22: stage: test image: node:22 script: - npm test

#DAG в GitLab CI через needs

lint: stage: test script: - npm run lint test-unit: stage: test needs: [] # Выполняется сразу, игнорируя стадии script: - npm run test:unit test-integration: stage: test needs: [] script: - npm run test:integration build: stage: build needs: [lint, test-unit, test-integration] script: - npm run build

Преимущество DAG:

  • Job выполняются сразу после готовности зависимостей
  • Не нужно ждать завершения всей стадии
  • Ускорение пайплайна на 30–50%

#resource_group для ограничения

deploy: stage: deploy resource_group: production # Только один deploy одновременно script: - ./deploy.sh deploy-staging: stage: deploy resource_group: staging # Отдельный ресурс для staging script: - ./deploy-staging.sh

#Оптимизация времени выполнения

#Анализ времени job

GitHub Actions:

  • Вкладка Actions → выбор workflow → просмотр времени каждого job
  • Использование actions/github-script для сбора метрик

GitLab CI:

  • CI/CD → Pipelines → анализ времени стадий

#Приоритизация оптимизации

  1. Самые долгие job — оптимизация даёт максимальный эффект
  2. Часто выполняемые — кэш и параллелизм для частых сценариев
  3. Критический путь — job, от которых зависит деплой

#Уменьшение времени setup

# До оптимизации steps: - uses: actions/checkout@v4 # 10 сек - uses: actions/setup-node@v4 # 15 сек - run: npm install # 2 мин без кэша # После оптимизации steps: - uses: actions/checkout@v4 with: fetch-depth: 1 # Быстрее checkout - uses: actions/setup-node@v4 with: node-version: '20' cache: 'npm' # Кэш зависимостей - run: npm ci # 20 сек с кэшем

#Параллелизация по типам тестов

jobs: test-unit: runs-on: ubuntu-latest steps: - run: npm run test:unit # 2 минуты test-integration: runs-on: ubuntu-latest steps: - run: npm run test:integration # 5 минут test-e2e: runs-on: ubuntu-latest steps: - run: npm run test:e2e # 10 минут # Параллельное выполнение: 10 минут вместо 17

#Оптимизация Docker-сборок

# До оптимизации steps: - run: docker build -t myapp . # 10 минут # После оптимизации steps: - uses: docker/setup-buildx-action@v3 - run: docker buildx build \ --cache-from type=gha \ --cache-to type=gha,mode=max \ -t myapp . # 3 минуты с кэшем

#Квоты и ограничения

#GitHub Actions

ПланПараллельные jobMinutes / месяц
Free202000
Pro403000
Team6050000
Enterprise180500000

#GitLab CI

ПланПараллельные jobCI/CD minutes
Free10400 / месяц
Premium1010000 / месяц
Ultimate5050000 / месяц

#Лучшие практики

  1. Используйте matrix для тестирования на разных версиях и ОС
  2. Применяйте fail-fast: false для полной картины ошибок
  3. Разделяйте тесты на шарды при времени выполнения >10 минут
  4. Используйте DAG для ускорения критического пути
  5. Кэшируйте зависимости для ускорения setup
  6. Параллельте внутри job через тестовые раннеры
  7. Мониторьте время job для выявления узких мест
  8. Ограничивайте max-parallel при квотах или contention

Далее: Оптимизация затрат