Прототип отвечает за секунду, все довольны. Открывают доступ отделу — и система начинает отвечать по десять секунд или падать.
Причина в том, что скорость на одном запросе не говорит о поведении под нагрузкой почти ничего. У систем с моделями это выражено сильнее, чем у обычных веб-сервисов: обработка запроса требует много памяти и вычислений, и параллельные запросы конкурируют за них напрямую.
Нагрузочная проверка занимает день и отвечает на вопросы, которые иначе выяснятся на пользователях.
Что измерять
Время до первого токена. Сколько человек ждёт, прежде чем что-то начнёт появляться. Для интерфейсов с постепенным выводом — главная метрика восприятия.
Скорость выдачи. Токенов в секунду на один запрос. Определяет, за сколько появится ответ целиком.
Общее время ответа. Среднее и — обязательно — худшие значения. Средним можно обмануться: при среднем в две секунды каждый десятый пользователь может ждать пятнадцать.
Пропускная способность. Сколько запросов система обрабатывает в единицу времени. Именно она отличает среды запуска — «vLLM, Ollama, llama.cpp».
Потребление памяти под нагрузкой. Не при загрузке модели, а в пике — «Расчёт видеопамяти».
Доля отказов. Сколько запросов не обработано: нехватка памяти, таймаут, превышение квоты.
Точка деградации. При какой одновременности время ответа перестаёт быть приемлемым. Практически самое ценное число из всех.
Как считать нагрузку
Не путайте поток и одновременность. Тысяча обращений в час — это в среднем меньше одного в секунду. Но если они приходят неравномерно, в пике одновременных запросов может быть двадцать.
Оценка одновременности:
Одновременных запросов ≈ (запросов в секунду) × (среднее время обработки)
При 3 запросах в секунду и 4 секундах обработки одновременно обрабатывается около 12.
Пик считайте отдельно. Утренний час, понедельник, конец месяца — распределение обычно неравномерное. Планировать надо по пику, а не по среднему.
Учитывайте длину контекста. Запросы с длинным контекстом дороже и по времени, и по памяти. Тестировать надо на реальных длинах, а не на коротких примерах — «Длина контекста и стоимость».
Методика
Шаг 1. Соберите реальные запросы. Из журнала, с настоящими длинами контекста. Синтетические короткие запросы дадут красивые и бесполезные числа.
Шаг 2. Замерьте базу — один запрос без нагрузки. Опорная точка.
Шаг 3. Наращивайте одновременность ступенями. 1, 2, 5, 10, 20, 50. На каждой ступени — достаточно запросов, чтобы усреднить.
Шаг 4. Стройте зависимость времени ответа от одновременности. Обычно она плоская до какой-то точки, потом резко растёт. Эта точка и есть предел.
Шаг 5. Найдите узкое место. Память, вычисления, квота поставщика, что-то в вашем коде.
Шаг 6. Проверьте длительную нагрузку. Полчаса-час ровной нагрузки: утечки памяти и постепенная деградация видны только так.
Разбор: где на самом деле было узкое место
Задача. Ассистент по документам, планировалось 40 пользователей, пик — около 15 одновременных запросов.
Первый замер. Один запрос — 2,5 секунды. Расчёт: если один за 2,5 секунды, пятнадцать за... и вот здесь начинается ошибка, потому что так это не работает.
Что показала ступенчатая проверка.
| Одновременных | Время ответа | Отказы |
|---|---|---|
| 1 | 2,5 с | нет |
| 5 | 3,1 с | нет |
| 10 | 4,8 с | нет |
| 15 | 12 с | нет |
| 20 | — | нехватка памяти |
Резкий излом между 10 и 15, падение на 20.
Первая гипотеза — не хватает вычислительной мощности, нужна карта помощнее.
Что нашли на самом деле. Посмотрели потребление памяти: при 15 одновременных запросах память под контекст занимала больше, чем сама модель. Среда запуска, дойдя до предела, начала обрабатывать запросы фактически по очереди — отсюда излом.
Узким местом была память под контекст, а не вычисления. Более мощная карта с тем же объёмом памяти не помогла бы.
Что сделали, по возрастанию отдачи.
Сократили передаваемый контекст: четыре найденных фрагмента вместо десяти. Память под запрос уменьшилась соответственно — и качество ответов при этом выросло.
Перешли на среду запуска с эффективным управлением памятью под контекст.
Ограничили число одновременно обрабатываемых запросов, поставив остальные в короткую очередь. Лучше подождать секунду, чем получить отказ.
Итог. При 20 одновременных запросах время ответа около 4 секунд, отказов нет. Оборудование не менялось.
Что стоит забрать. Вывод «нужно железо помощнее» напрашивается первым и часто неверен. Прежде чем закупать, стоит выяснить, чего именно не хватает: памяти, вычислений или дело в среде запуска.
Что проверять для облачных моделей
Нагрузочная проверка нужна и там, просто узкие места другие.
Квоты поставщика. Сколько запросов в минуту допускается и что происходит при превышении: отказ, очередь, замедление.
Поведение вашего кода при отказах. Есть ли повторы, не порождают ли они лавину — «Обработка ошибок».
Разброс времени ответа. У облачных сервисов он больше, чем у своей установки, и худшие значения могут быть в разы выше средних.
Стоимость под нагрузкой. Пиковый час — это пиковый счёт.
Что делать с результатом
Если предел выше вашего пика с запасом — всё, можно запускать.
Если предел близок к пику — есть три пути, и оборудование среди них последний:
- Сократить контекст — обычно даёт больше всего;
- Сменить среду запуска или настроить её;
- Перевести часть шагов на модель поменьше — «Малые модели»;
- Ограничить одновременность очередью;
- И только потом — докупить оборудование.
Частые вопросы
Почему система, быстрая на одном запросе, тормозит на десяти?
Потому что параллельные запросы конкурируют за память и вычисления, а обработка запроса моделью требует и того, и другого много. Дополнительно среда запуска может не уметь эффективно объединять параллельные запросы, и тогда они фактически выполняются по очереди.
Как посчитать, сколько одновременных запросов у нас будет?
Умножить число запросов в секунду на среднее время обработки. При трёх запросах в секунду и четырёх секундах обработки одновременно обрабатывается около двенадцати. Считать нужно по пиковому часу, а не по среднему за сутки.
Какая метрика важнее всего?
Точка, при которой время ответа перестаёт быть приемлемым, — та одновременность, после которой начинается резкий рост. Она сравнивается с вашим пиком и отвечает на главный вопрос: выдержит система или нет.
Что делать, если нагрузки не хватает?
Сначала сократить передаваемый контекст — обычно это даёт больше всего и попутно улучшает качество ответов. Затем проверить среду запуска и её настройки. Затем перевести простые шаги на модель поменьше и ограничить одновременность очередью. Докупка оборудования — последний шаг, а не первый.
Нужно ли нагрузочное тестирование для облачных моделей?
Нужно, просто узкие места другие: квоты поставщика, поведение вашего кода при отказах, разброс времени ответа и стоимость в пиковый час. Особенно важно проверить, не порождают ли повторы при отказах лавину запросов.
На каких запросах тестировать?
На реальных, взятых из журнала, с настоящими длинами контекста. Короткие синтетические запросы дадут красивые числа, не имеющие отношения к работе: время и память сильно зависят от объёма передаваемого текста.
Что дальше
Сколько памяти нужно и почему — «Расчёт видеопамяти». Чем запускать под нагрузкой — «vLLM, Ollama, llama.cpp». Как сократить контекст — «Длина контекста и стоимость». Проверка качества, а не скорости — «Тестирование модели на своей задаче».
Расчёт конфигурации и проверка под нагрузкой до запуска — часть работы по разработке и внедрению ИИ.