Что такое перформанс тестирование
Попытка простыми словами рассказать о перформанс-тестировании: зачем оно нужно, как помогает находить узкие места, определять capacity и проверять, готов ли прод.
🐏
Введение
Если спросить у разработчика или тестировщика: «Что такое перформанс-тестирование?», часто можно услышать: «Запускаем кучу юзеров и смотрим, что будет».
Да, в этом есть доля правды, но это только верхушка айсберга. Настоящее перф-тестирование — это не просто про «сломать систему».
Это исследование, которое показывает:
- где у системы узкие места (bottlenecks),
- как она ведёт себя под нагрузкой,
- на каком числе пользователей система подходит к пределу.
Графики без анализа не дают понимания, почему растёт время ответа, что это значит для бизнеса и как это исправить.
Перформанс тестирование — это уверенность в том, что прод выдержит реальную нагрузку.
Содержание
- Зачем это нужно
- Время ответа и капасити системы
- История про овец
- Типы тестов
- Мнения коллег
- Bottleneck
- Кейсы из практики
- Теория важнее инструментов
- Рекомендации
Зачем это нужно
Чтобы понять, зачем нам перф-тесты, нужно посмотреть на три фактора, с которыми сталкивается любая система на проде:
-
Юзеры.
Они приходят хаотично: утром может быть всего 10, вечером нагрузка вырастает до 500, а в «чёрную пятницу» — это уже цунами. Поведение разное: кто-то кликнул один раз и ушёл, а кто-то за несколько минут отправил десятки запросов. -
Лимиты.
У серверов, баз данных, внешних API — у всего есть предел. Capacity не бесконечен даже в облаке. Всегда найдётся общий ресурс, в который система упрётся. -
Время.
Чем дольше работает система, тем больше в ней накапливается технический мусор: утечки памяти, переполненные кеши, висящие сессии и т.д. Сначала это незаметно, но через часы или дни начинает сильно влиять на производительность.
📌 Перф-тестирование отвечает на вопрос: выдержит ли система все эти факторы одновременно. Например, в кафе всё идёт гладко, когда сидит пара человек. Но только полный зал во время обеда показывает, справится ли кухня и официанты.
Время ответа и капасити системы
Когда мы получили первые результаты тестов, возникает вопрос – как их правильно анализировать. Обычно многие смотрят только на response time. Если он вырос с 1 до 2 секунд, кажется, что система стала в два раза хуже. Но это лишь симптом, а не диагноз.
- Response time отражает опыт одного пользователя или группы в конкретный момент.
- Capacity описывает способность системы выдерживать общее число запросов/юзеров в секунду.
Эти вещи связаны, но не одинаковы.
Например:
-
Очередь запросов растёт, пул соединений приближается к лимиту.
→ Ответы замедляются, но throughput ещё может расти или держаться на плато. -
Лимит пула уже достигнут.
→ Throughput выходит на потолок, а response time продолжает расти из-за очереди.
Это bottleneck. Его природа может быть конфигурационной (размер пула), а не исчерпанием всей системы.
⚡ Поэтому вместе с response time нужно смотреть на другие показатели:
- throughput
- CPU
- память
- GC
- состояние очередей
История про овец
Эту метафору однажды рассказал Андрей Апарович, и она очень точно описывает суть bottleneck.
Представьте дорогу и мост:
- Одна овца пробежала туда и обратно за час. Фермер доволен, всё отлично.
- Но когда по той же дороге пустили тысячу овец, всё изменилось. На пути оказался узкий мост, по которому могла пройти только одна овца одновременно. В итоге всё стадо застряло, а время прохождения выросло в разы. Bottleneck оказался не в овцах, а в ограниченной пропускной способности моста.
Теперь добавим сложности:
- Пошёл дождь, мост стал скользким, и каждая овца тратит в три раза больше времени на переход. Для одной овцы это мелочь, но для тысячи — катастрофа. Очередь растёт, задержки увеличиваются, и система из овец и моста перестаёт справляться.
- А если вдруг дорогу перегородил трактор или кто-то погнал овец обратно, даже маленькая помеха создаёт пробку, которая растягивается на километры.
🐑 В итоге фермер понимает: узкие места и внешние факторы многократно усиливают эффект нагрузки. В системах всё происходит так же. Незначительная задержка при малом трафике может быть незаметна, но под нагрузкой она превращается в серьёзный сбой.
Типы тестов
Прежде чем переходить к серьёзным видам нагрузочного тестирования, всегда начинают с самого простого шага:
1. Smoke test 🚬
Он нужен, чтобы убедиться:
- скрипты действительно запускаются,
- сервис откликается,
- инфраструктура настроена правильно.
Такой тест даёт базовую уверенность, что система жива и можно двигаться дальше.
2. Baseline 📊
Бэйзлайн полезен в двух случаях:
- В CI. Небольшой тест на десяток пользователей помогает проверить, не изменился ли response time после коммита.
- Для сравнения. Снимаем текущее состояние, делаем замеры после исправлений и видим, стало лучше или хуже.
Таким образом, бэйзлайн позволяет отслеживать тренды.
Но если задача — определить пределы системы, 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 и что с этим делать. -
Повторяйте тесты.
Один прогон — это случайность.
Серия прогонов — это уже данные.
Примечание: статья написана на основе обсуждений темы перф-тестирования с экспертами — Андрей Апарович, Иван Зарубин, Надежда Тамела и Сергей Пашкевич — в рамках подкаста «Поднимая перформанс».