Что такое перформанс тестирование

29.09.2025

Попытка простыми словами рассказать о перформанс-тестировании: зачем оно нужно, как помогает находить узкие места, определять capacity и проверять, готов ли прод.

теория

🐏

Введение

Если спросить у разработчика или тестировщика: «Что такое перформанс-тестирование?», часто можно услышать: «Запускаем кучу юзеров и смотрим, что будет».

Да, в этом есть доля правды, но это только верхушка айсберга. Настоящее перф-тестирование — это не просто про «сломать систему».
Это исследование, которое показывает:

  • где у системы узкие места (bottlenecks),
  • как она ведёт себя под нагрузкой,
  • на каком числе пользователей система подходит к пределу.

Графики без анализа не дают понимания, почему растёт время ответа, что это значит для бизнеса и как это исправить.
Перформанс тестирование — это уверенность в том, что прод выдержит реальную нагрузку.

Содержание


Зачем это нужно

Чтобы понять, зачем нам перф-тесты, нужно посмотреть на три фактора, с которыми сталкивается любая система на проде:

  • Юзеры.
    Они приходят хаотично: утром может быть всего 10, вечером нагрузка вырастает до 500, а в «чёрную пятницу» — это уже цунами. Поведение разное: кто-то кликнул один раз и ушёл, а кто-то за несколько минут отправил десятки запросов.

  • Лимиты.
    У серверов, баз данных, внешних API — у всего есть предел. Capacity не бесконечен даже в облаке. Всегда найдётся общий ресурс, в который система упрётся.

  • Время.
    Чем дольше работает система, тем больше в ней накапливается технический мусор: утечки памяти, переполненные кеши, висящие сессии и т.д. Сначала это незаметно, но через часы или дни начинает сильно влиять на производительность.

📌 Перф-тестирование отвечает на вопрос: выдержит ли система все эти факторы одновременно. Например, в кафе всё идёт гладко, когда сидит пара человек. Но только полный зал во время обеда показывает, справится ли кухня и официанты.


Время ответа и капасити системы

Когда мы получили первые результаты тестов, возникает вопрос – как их правильно анализировать. Обычно многие смотрят только на response time. Если он вырос с 1 до 2 секунд, кажется, что система стала в два раза хуже. Но это лишь симптом, а не диагноз.

  • Response time отражает опыт одного пользователя или группы в конкретный момент.
  • Capacity описывает способность системы выдерживать общее число запросов/юзеров в секунду.

Эти вещи связаны, но не одинаковы.

Например:

  • Очередь запросов растёт, пул соединений приближается к лимиту.
    → Ответы замедляются, но throughput ещё может расти или держаться на плато.

    Пример 1

  • Лимит пула уже достигнут.
    → Throughput выходит на потолок, а response time продолжает расти из-за очереди.

    Пример 2

Это bottleneck. Его природа может быть конфигурационной (размер пула), а не исчерпанием всей системы.

⚡ Поэтому вместе с response time нужно смотреть на другие показатели:

  • throughput
  • CPU
  • память
  • GC
  • состояние очередей

История про овец

Эту метафору однажды рассказал Андрей Апарович, и она очень точно описывает суть bottleneck.

Представьте дорогу и мост:

  • Одна овца пробежала туда и обратно за час. Фермер доволен, всё отлично.
  • Но когда по той же дороге пустили тысячу овец, всё изменилось. На пути оказался узкий мост, по которому могла пройти только одна овца одновременно. В итоге всё стадо застряло, а время прохождения выросло в разы. Bottleneck оказался не в овцах, а в ограниченной пропускной способности моста.

Теперь добавим сложности:

  • Пошёл дождь, мост стал скользким, и каждая овца тратит в три раза больше времени на переход. Для одной овцы это мелочь, но для тысячи — катастрофа. Очередь растёт, задержки увеличиваются, и система из овец и моста перестаёт справляться.
  • А если вдруг дорогу перегородил трактор или кто-то погнал овец обратно, даже маленькая помеха создаёт пробку, которая растягивается на километры.

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


Типы тестов

Прежде чем переходить к серьёзным видам нагрузочного тестирования, всегда начинают с самого простого шага:

1. Smoke test 🚬

Он нужен, чтобы убедиться:

  • скрипты действительно запускаются,
  • сервис откликается,
  • инфраструктура настроена правильно.

Такой тест даёт базовую уверенность, что система жива и можно двигаться дальше.

2. Baseline 📊

Бэйзлайн полезен в двух случаях:

  1. В CI. Небольшой тест на десяток пользователей помогает проверить, не изменился ли response time после коммита.
  2. Для сравнения. Снимаем текущее состояние, делаем замеры после исправлений и видим, стало лучше или хуже.

Таким образом, бэйзлайн позволяет отслеживать тренды.
Но если задача — определить пределы системы, baseline недостаточен. Тогда нужны полноценные load и stress тесты.

3. Load test ⚡

Проверяет систему на фиксированном уровне RPS и сравнивает результат с SLA.

4. Capacity / Stress test 🚦

Постепенное увеличение нагрузки до тех пор, пока не станет ясно, где предел системы.

5. Longevity (Soak) test ⏳

Долгий прогон — несколько часов или дней.
Он помогает выявить:

  • утечки памяти,
  • переполнение кешей,
  • деградацию, которая не проявляется в коротких тестах.

6. Scalability test 📈

Показывает, помогает ли добавление ресурсов.
Если нет, значит система упирается в общий лимит и масштабировать её в лоб нельзя.

Эти виды тестов образуют логичную лестницу и вместе дают полное представление о системе.


Мнения коллег

  • Иван Зарубин отмечал, что внутри команды нужно договориться о терминологии. Для кого-то load и stress — одно и то же, для кого-то это принципиально разные вещи. Если этого не сделать, отчёты будут интерпретироваться по-разному и могут запутать ситуацию.

  • Надежда Тамела подчёркивала: в требованиях важно фиксировать не только функциональные сценарии, но и нефункциональные ожидания. Нужно заранее определить: какие типы тестов будут проводиться, какие метрики ключевые и как их проверять. По её словам, именно требования должны отвечать на вопрос нужен ли longevity тест, стоит ли проверять scalability или достаточно базового load.

  • Сергей Пашкевич добавил важный слой — client-side метрики. Пользователи оценивают не только скорость API, но и то, как быстро и плавно грузится интерфейс. Иногда именно клиентская часть первой показывает деградацию, и без этого картинка неполная.

Если объединить все эти мысли, то можно сказать так: типы тестов — это не жёсткий список, а набор инструментов, который нужно настраивать под конкретный проект.

Главное:

  • команда говорит на одном языке,
  • требования задают рамки,
  • результат отражает как серверную, так и клиентскую стороны.

Bottleneck

Все описанные тесты в итоге ведут нас к одной цели — найти bottleneck.

Он может быть где угодно:

  • в базе данных,
  • в thread pool,
  • в GC,
  • во внешнем API.

Иногда это мелочь, например, диск, который не успевает записывать логи. А иногда это фундаментальная архитектурная проблема, например монолитная база, которую невозможно масштабировать.

Важно помнить, что узкое место не всегда там, где его ждут. Иногда тормозит фронтенд, а не база. В других случаях проблемой становится очередь сообщений. Поэтому так важно смотреть на всю систему целиком и не ограничиваться одним сервисом.


Кейсы из практики

Чтобы показать, как теория работает на практике, приведу несколько историй.

🏦 Банк

  • Симптом: на тестах логин занимал 2 секунды, а на проде — 12.
  • Причина: на тестовом энве не было достаточно большой нагрузки, и проблемное место не проявлялось.
    В реальности библиотека шифрования блокировала работу при сотнях одновременных подключений.
  • Решение: после исправления библиотеки время логина снова стало около 2 секунд.

🛒 E-commerce

  • Симптом: запустили longevity-тест на 24 часа. Первые часы всё нормально, но через 12 часов система упала.
  • Причина: незакрытые соединения с базой. Короткие тесты этого не выявили.

🏬 Ритейл

  • Симптом: сервис постоянно падал во время распродаж.
    Трафик рос лавинообразно: десятки тысяч запросов одновременно, система переставала отвечать.
  • Предположение команды: не хватает ресурсов, нужно добавить больше серверов.
  • Реальность: перф-тесты показали, что настоящая причина в SQL-запросе с full scan по большой таблице.
  • Решение: оптимизация индексов и переписывание запроса.
  • Результат: capacity вырос в 3 раза, сервис выдержал пиковые часы продаж.

🚀 Стартап

  • Симптом: система работала идеально при 10 RPS, но при 50 RPS начали появляться лаги.
  • Причина: bottleneck оказался во внешнем (third-party) API.
  • Решение: внедрили кеш и очереди.
  • Результат: система выдержала нагрузку в 5 раз больше.

Теория важнее инструментов

Всеми этими историями я пытаюсь подвести вас к одному простому, но важному выводу: одних только инструментов недостаточно.
JMeter, Gatling, k6 и любые другие тулы — это всего лишь способ запустить load и собрать цифры. Настоящее мастерство перф-аналитика/инженера — увидеть за графиками суть:

  • уметь различать, рост response time связан с реальным исчерпанием capacity или это побочный эффект (например, блокировки, конфигурационные лимиты);
  • понимать, что throughput и utilization нужно рассматривать вместе, а не по отдельности;
  • помнить: без знаний все эти графики легко превращаются в шум и создают иллюзию анализа.

Важно не только запускать тесты и строить красивые дашборды, но и глубоко анализировать результаты:

  • связывать показатели между собой (response time ↔ throughput ↔ CPU/Memory/GC/очереди);
  • искать закономерности и проверять гипотезы по шагам;
  • отличать симптом от настоящей причины;
  • и в итоге подсказывать команде, что именно требует исправления и почему.

Рекомендации

В завершение стоит дать несколько практических советов:

  • Начинайте с малого.
    Тестируйте десятки пользователей, а не тысячи.
    Маленький тест быстрее запускается и сразу показывает, живы ли скрипты и система.

  • Учитывайте client-side.
    Можно иметь быстрый API, но если фронтенд рисует страницу по 5 секунд — юзер всё равно недоволен.

  • Договоритесь о терминах.
    Load и stress для разных людей означают разное.
    Если не выработать единые определения, отчёты будут интерпретироваться по-разному и это только запутает ситуацию.

  • Фиксируйте нефункциональные ожидания в требованиях.
    Если заранее написано, что нужна проверка scalability или longevity-тест на сутки,
    команда не сможет это проигнорировать.
    И заказчик будет уверен, что результат покрывает именно то, что он ожидал.

  • Настройте мониторинг.
    Без него можно увидеть только поверхность.
    Отчёт лучше писать как историю: что произошло, где bottleneck и что с этим делать.

  • Повторяйте тесты.
    Один прогон — это случайность.
    Серия прогонов — это уже данные.


Примечание: статья написана на основе обсуждений темы перф-тестирования с экспертами — Андрей Апарович, Иван Зарубин, Надежда Тамела и Сергей Пашкевич — в рамках подкаста «Поднимая перформанс».