Как отслеживать бенчмарки в CI с помощью Bencher


Большинство результатов тестов производительности являются эфемерными. Они исчезают, как только ваш терминал достигает предела прокрутки. Некоторые фреймворки для тестирования позволяют кешировать результаты, но большинство из них делают это только локально. Bencher позволяет отслеживать ваши тесты как с локальных, так и с CI-запусков и сравнивать результаты, при этом вы всё ещё можете использовать ваш любимый фреймворк для тестирования.

Существует три популярных способа сравнения результатов тестов производительности при непрерывном тестировании производительности, то есть тестировании производительности в CI:

  • Статистическое непрерывное тестирование
    1. Отслеживайте результаты тестов производительности с течением времени для создания базового уровня
    2. Используйте этот базовый уровень вместе с статистическими порогами для создания статистической границы
    3. Сравните новые результаты с этой статистической границей для обнаружения регрессий производительности
  • Относительное непрерывное тестирование
    1. Выполните тесты производительности для текущего базового кода
    2. Переключитесь на новую версию кода
    3. Выполните тесты производительности для новой версии кода
    4. Используйте процентные пороги для создания границы для базового кода
    5. Сравните результаты новой версии кода с результатами базового кода для обнаружения регрессий производительности
  • Обнаружение точек изменений
    1. Периодически выполняйте тесты производительности для новых версий кода
    2. Используйте алгоритм обнаружения точек изменений для выявления регрессий производительности
    3. Выполните бисекцию, чтобы найти коммит, который привёл к регрессии производительности

Статистическое непрерывное тестирование производительности

Продолжая с того места, где мы остановились в Быстром старте и Локальном использовании Docker, давайте добавим статистическое непрерывное тестирование производительности нашему проекту Save Walter White.

🐰 Перед продолжением убедитесь, что вы создали API токен и установили его в качестве переменной среды BENCHER_API_TOKEN!

Теперь мы готовы запускать наши тесты производительности в CI. Поскольку каждая среда CI немного отличается, следующий пример предназначен скорее для иллюстрации, чем для практического использования. Для более специфичных примеров смотрите Непрерывное тестирование производительности в GitHub Actions и Непрерывное тестирование производительности в GitLab CI/CD.

Во-первых, нам нужно создать и поддерживать историческую базовую линию для нашей ветви main, тестируя каждое изменение в CI:

Terminal window
bencher run \
--project save-walter-white-1234abcd \
--branch main \
--testbed ci-runner \
--threshold-measure latency \
--threshold-test t_test \
--threshold-max-sample-size 64 \
--threshold-upper-boundary 0.99 \
--thresholds-reset \
--err \
--adapter json \
bencher mock
  1. Используйте подкоманду CLI bencher run для запуска тестов производительности вашей ветви main. Полный обзор смотрите в подкоманде CLI bencher run. (например: bencher run)
  2. Установите опцию --project в проектный ярлык. Подробнее смотрите в документации по опции --project. (например: --project save-walter-white-1234abcd)
  3. Установите опцию --branch в имя базовой ветви. Полный обзор смотрите в документации по опции --branch. (например: --branch main)
  4. Установите опцию --testbed в название тестовой среды CI. Подробнее смотрите в документации по опции --testbed. (например: --testbed ci-runner)
  5. Установите порог для ветви main, тестовой среды ci-runner и измерения latency:
    1. Установите опцию --threshold-measure в встроенное измерение latency, создаваемое bencher mock. Подробнее смотрите в документации по опции --threshold-measure. (например: --threshold-measure latency)
    2. Установите опцию --threshold-test в тест Стьюдента (t_test). Полный обзор смотрите в документации по опции --threshold-test. (например: --threshold-test t_test)
    3. Установите опцию --threshold-max-sample-size на максимальный размер выборки 64. Подробнее смотрите в документации по опции --threshold-max-sample-size. (например: --threshold-max-sample-size 64)
    4. Установите опцию --threshold-upper-boundary на верхнюю границу 0.99. Подробнее смотрите в документации по опции --threshold-upper-boundary. (например: --threshold-upper-boundary 0.99)
    5. Установите флаг --thresholds-reset, чтобы только указанный порог был активен. Полный обзор смотрите в документации по флагу --thresholds-reset. (например: --thresholds-reset)
  6. Установите флаг --err для завершения команды в случае возникновения предупреждения. Полный обзор смотрите в документации по флагу --err. (например: --err)
  7. Установите опцию --adapter в формат Bencher Metric JSON (json), который создается bencher mock. Полный обзор смотрите в адаптеры теста. (например: --adapter json)
  8. Укажите аргументы команды тестирования. Полный обзор смотрите в команда тестирования. (например: bencher mock)

Первый запуск этой команды в CI создаст ветвь main, если она еще не существует. Новая main не будет иметь начальной точки или существующих данных. Для ветви main, тестовой среды ci-runner и измерения latency будет создан порог. На последующих запусках новые данные будут добавляться в ветвь main. Указанный порог будет использоваться для обнаружения регрессий производительности.

Теперь мы готовы выявлять регрессии производительности в CI. Вот как мы будем отслеживать производительность новой ветви функций в CI, именуемой feature-branch:

Terminal window
bencher run \
--project save-walter-white-1234abcd \
--branch feature-branch \
--start-point main \
--start-point-hash 32aea434d751648726097ed3ac760b57107edd8b \
--start-point-clone-thresholds \
--start-point-reset \
--testbed ci-runner \
--err \
--adapter json \
bencher mock
  1. Используйте подкоманду CLI bencher run для запуска тестов производительности вашей ветви feature-branch. Полный обзор смотрите в подкоманде CLI bencher run. (например: bencher run)
  2. Установите опцию --project в проектный ярлык. Подробнее смотрите в документации по опции --project. (например: --project save-walter-white-1234abcd)
  3. Установите опцию --branch в имя ветви функции. Полный обзор смотрите в документации по опции --branch. (например: --branch feature-branch)
  4. Установите начальную точку для ветви feature-branch:
    1. Установите опцию --start-point на начальную точку ветви функции. Полный обзор смотрите в документации по опции --start-point. (например: --start-point main)
    2. Установите опцию --start-point-hash на хэш git начальной точки ветви функции. Полный обзор смотрите в документации по опции --start-point-hash. (например: --start-point-hash 32ae...dd8b)
    3. Установите флаг --start-point-clone-thresholds для клонирования порогов из начальной точки. Полный обзор смотрите в документации по флагу --start-point-clone-thresholds. (например: --start-point-clone-thresholds)
    4. Установите флаг --start-point-reset для постоянного сброса ветви к начальной точке. Это предотвратит смещение данных тестирования. Полный обзор смотрите в документации по флагу --start-point-reset. (например: --start-point-reset)
  5. Установите опцию --testbed в название тестовой среды. Подробнее смотрите в документации по опции --testbed. (например: --testbed ci-runner)
  6. Установите флаг --err для завершения команды в случае возникновения предупреждения. Полный обзор смотрите в документации по флагу --err. (например: --err)
  7. Установите опцию --adapter в формат Bencher Metric JSON (json), который создается bencher mock. Полный обзор смотрите в адаптеры теста. (например: --adapter json)
  8. Укажите аргументы команды тестирования. Полный обзор смотрите в команда тестирования. (например: bencher mock)

Первый запуск этой команды в CI заставит Bencher создать ветвь feature-branch, поскольку она пока не существует. Новая ветвь feature-branch будет использовать ветвь main с хэшем 32aea434d751648726097ed3ac760b57107edd8b в качестве начальной точки. Это означает, что feature-branch будет иметь копию всех данных и порогов из ветви main для сравнения результатов bencher mock. На всех последующих запусках Bencher сбросит ветвь feature-branch к начальной точке, и будет использовать данные и пороги ветви main для обнаружения регрессий производительности.

Относительное Непрерывное Бенчмаркинг

Продолжая с того места, где мы остановились в Руководствах Быстрого Старта и Docker для Самостоятельного Развертывания, давайте добавим Относительное Непрерывное Бенчмаркинг в наш проект Save Walter White.

🐰 Убедитесь, что вы создали токен API и установите его в качестве переменной окружения BENCHER_API_TOKEN перед продолжением!

Относительное Непрерывное Бенчмаркинг выполняет сравнительный анализ двух версий вашего кода. Это может быть полезно при работе с шумными средами CI/CD, где доступные ресурсы могут быть высоко изменчивыми между запусками. В этом примере мы будем сравнивать результаты запуска на ветке main с результатами запуска на отдельно взятой ветке, подходяще названной feature-branch. Поскольку каждая среда CI немного отличается, следующий пример предназначен скорее для иллюстрации, чем для практического применения. Для более конкретных примеров см. Непрерывное Бенчмаркинг в GitHub Actions и Непрерывное Бенчмаркинг в GitLab CI/CD.

Сначала нам нужно переключиться на ветку main с помощью git в CI:

Terminal window
git checkout main

Затем нам нужно запустить наши бенчмарки на ветке main в CI:

Terminal window
bencher run \
--project save-walter-white-1234abcd \
--branch main \
--start-point-reset \
--testbed ci-runner \
--adapter json \
bencher mock
  1. Используйте bencher run команду CLI, чтобы запустить ваши бенчмарки для ветки main. Смотрите команду bencher run CLI для полного обзора. (например: bencher run)
  2. Установите опцию --project на слаг Проекта. Смотрите документацию по --project для более подробной информации. (например: --project save-walter-white-1234abcd)
  3. Установите опцию --branch на имя основной ветки. Смотрите документацию по --branch для полного обзора. (например: --branch main)
  4. Установите флаг --start-point-reset для всегда сбрасываемой основной ветки. Это обеспечит, что все данные бенчмарка будут получены с текущего CI-раннера. Смотрите документацию по --start-point-reset для полного обзора. (например: --start-point-reset)
  5. Установите опцию --testbed на имя Testbed CI-раннера. Смотрите документацию по --testbed для более подробной информации. (например: --testbed ci-runner)
  6. Установите опцию --adapter на Bencher Metric Format JSON (json), который генерируется bencher mock. Смотрите адаптеры для бенчмаркинга для полного обзора. (например: --adapter json)
  7. Укажите аргументы команды бенчмарка. Смотрите документацию команды бенчмарка для полного обзора. (например: bencher mock)

Первый раз, когда эта команда будет выполнена в CI, она создаст ветку main, так как она еще не существует. Новая main не будет иметь начальной точки, существующих данных или Порогов. При последующих запусках старая main Head будет заменена, а новая main Head будет создана без начальной точки, существующих данных или Порогов.

Далее, нам нужно переключиться на ветку feature-branch с помощью git в CI:

Terminal window
git checkout feature-branch

Теперь мы готовы выполнить наши бенчмарки для feature-branch в CI:

Terminal window
bencher run \
--project save-walter-white-1234abcd \
--branch feature-branch \
--start-point main \
--start-point-reset \
--testbed ci-runner \
--threshold-measure latency \
--threshold-test percentage \
--threshold-upper-boundary 0.25 \
--thresholds-reset \
--err \
--adapter json \
bencher mock
  1. Используйте bencher run команду CLI, чтобы запустить ваши бенчмарки для feature-branch. Смотрите команду bencher run CLI для полного обзора. (например: bencher run)
  2. Установите опцию --project на слаг Проекта. Смотрите документацию по --project для более подробной информации. (например: --project save-walter-white-1234abcd)
  3. Установите опцию --branch на имя ветки feature-branch. Смотрите документацию по --branch для полного обзора. (например: --branch feature-branch)
  4. Установите начальную точку для ветки feature-branch:
    1. Установите опцию --start-point на начальную точку ветки feature. Смотрите документацию по --start-point для полного обзора. (например: --start-point main)
    2. Установите флаг --start-point-reset, чтобы всегда сбрасывать ветку к начальному пункту. Это позволит использовать только самые последние результаты относительного бенчмарка. Смотрите документацию по --start-point-reset для полного обзора. (например: --start-point-reset)
  5. Установите опцию --testbed на имя Testbed CI-раннера. Смотрите документацию по --testbed для более подробной информации. (например: --testbed ci-runner)
  6. Установите Порог для ветки feature-branch, Testbed ci-runner и Меры latency:
    1. Установите опцию --threshold-measure на встроенную Меру latency, которая генерируется bencher mock. Смотрите документацию по --threshold-measure для более подробной информации. (например: --threshold-measure latency)
    2. Установите опцию --threshold-test на основной процент (percentage). Смотрите документацию по --threshold-test для полного обзора. (например: --threshold-test percentage)
    3. Установите опцию --threshold-upper-boundary на Верхнюю Границу 0.25. Смотрите документацию по --threshold-upper-boundary для более подробной информации. (например: --threshold-upper-boundary 0.25)
    4. Установите флаг --thresholds-reset, так чтобы был активен только указанный Порог. Смотрите документацию по --thresholds-reset для полного обзора. (например: --thresholds-reset)
  7. Установите флаг --err, чтобы команда завершалась с ошибкой, если генерируется Предупреждение. Смотрите документацию по --err для полного обзора. (например: --err)
  8. Установите опцию --adapter на Bencher Metric Format JSON (json), который генерируется bencher mock. Смотрите адаптеры для бенчмаркинга для полного обзора. (например: --adapter json)
  9. Укажите аргументы команды бенчмарка. Смотрите документацию команды бенчмарка для полного обзора. (например: bencher mock)

Каждый раз, когда эта команда выполняется в CI, она сравнивает результаты feature-branch только с самыми последними результатами main. Указанный Порог используется для обнаружения регрессий производительности.

Обнаружение точек изменений

Обнаружение точек изменений использует алгоритм обнаружения изменений для оценки большого окна недавних результатов. Это позволяет алгоритму игнорировать выбросы как шум и снижать количество ложноположительных срабатываний. Хотя обнаружение точек изменений считается непрерывным сравнительным анализом, оно не позволяет обнаруживать регрессии производительности в CI. То есть, вы не можете обнаружить регрессию производительности до слияния ветки функции. Это иногда называют “внесистемным” обнаружением.

Например, если у вас есть тест bench_my_critical_path, и у него были следующие исторические задержки: 5 ms, 6 ms, 5 ms, 5ms, 7ms.

Если следующий результат теста составил 11 ms, то порог статистического непрерывного сравнительного анализа и алгоритм обнаружения точек изменений интерпретировали бы это по-разному. Порог, вероятно, был бы превышен, и было бы сгенерировано предупреждение. Если этот прогон теста был связан с pull-запросом, сборка, вероятно, была бы помечена как неудачная из-за этого предупреждения. Однако, алгоритм точек изменений не сделал бы ничего… пока. Если бы в следующий прогон результаты вернулись к 5 ms, то, вероятно, предупреждение не было бы сгенерировано. Наоборот, если бы один-два следующих прогона дали результаты 10 ms и 12 ms, только тогда алгоритм точек изменений сгенерировал бы предупреждение.

Заинтересованы в использовании обнаружения точек изменений с Bencher? Если да, оставьте комментарий по трековому вопросу или свяжитесь с нами напрямую.



🐰 Поздравляем! Вы научились отслеживать бенчмарки в CI с помощью Bencher! 🎉


Добавить Bencher в GitHub Actions ➡

Добавить Bencher в GitLab CI/CD ➡

🤖 Этот документ был автоматически создан OpenAI GPT-4. Оно может быть неточным и содержать ошибки. Если вы обнаружите какие-либо ошибки, откройте проблему на GitHub.


Published: Fri, October 27, 2023 at 8:40:00 AM UTC | Last Updated: Mon, November 11, 2024 at 7:45:00 AM UTC