Как по-настоящему нагрузить LLM и не обмануть себя метриками
Когда вы тестируете обычный REST API, вам обычно хватает wrk, autocannon или старого доброго jmeter. Вы пускаете сотню виртуальных пользователей, смотрите на latency в миллисекундах, собираете p95/p99 и идёте пить кофе. С генеративными моделями этот трюк моментально ломается.
Обычный профилировщик видит стриминг токенов как один бесконечный HTTP-ответ. Он не понимает, когда сервер отдал первый байт, сколько миллисекунд ушло на генерацию между соседними токенами и как просел KV-кэш при длинном системном промпте. В итоге разработчики пишут свои самодельные скрипты на Python с asyncio и time.perf_counter(), которые упираются в GIL, перегружают клиентский процессор и искажают замеры.
Команда из NVIDIA выложила в открытый доступ AIPerf (репозиторий ai-dynamo/aiperf). Это инструмент для бенчмаркинга инференса генеративных моделей, заточенный под специфику LLM, эмбеддингов, аудио и картинок.
Что умеет AIPerf и зачем его сделали
AIPerf берет на себя всю грязную работу по измерению специфичных для AI метрик:
- TTFT (Time to First Token) — время до появления первого токена в ответе;
- ITL (Inter Token Latency) — задержка между генерацией соседних токенов;
- Throughput — реальная пропускная способность в токенах за секунду на пользователя и на весь сервер;
- Goodput — пропускная способность с фильтрацией ответов, уложившихся в заданный SLA.
Утилита работает с любым сервером, умеющим в протокол OpenAI: vLLM, SGLang, TensorRT-LLM, Hugging Face TGI или локальный Ollama.
Быстрый старт на локальной машине
Попробовать инструмент можно за пару минут на локальном инстансе Ollama. Поднимем легковесную модель granite4:350m в Docker:
docker run -d \
--name ollama \
-p 11434:11434 \
-v ollama-data:/root/.ollama \
ollama/ollama:latest
docker exec -it ollama ollama pull granite4:350m
Ставим сам AIPerf через pip:
python3 -m venv venv
source venv/bin/activate
pip install aiperf
Если вы запускаете это на Linux с архитектурой ARM64, заранее поставьте системные инструменты сборки вроде build-essential. Одна из зависимостей пакета (библиотека crick) собирается из исходников. На x86_64, macOS и Windows всё ставится из готовых wheel-пакетов без лишних телодвижений.
Теперь запускаем первый замер:
aiperf profile \
--model "granite4:350m" \
--streaming \
--endpoint-type chat \
--tokenizer ibm-granite/granite-4.0-micro \
--url http://localhost:11434 \
--concurrency 5 \
--request-count 10
В консоли появится аккуратная таблица со статистикой: средние значения, перцентили p50, p90, p99, минимальные и максимальные задержки, а также экспорт в JSON и CSV.
Что интересного под капотом
В отличие от простых оберток над httpx, разработчики упаковали внутрь полноценную многопроцессную архитектуру.
- Десять изолированных сервисов на ZeroMQ. Генерация нагрузки, сбор телеметрии, подсчет метрик и отрисовка терминального UI разнесены по отдельным процессам ОС. Они общаются через очереди ZMQ. Благодаря этому клиентский планировщик не захлебывается при параллельных запросах и точно фиксирует тайминги.
- Три режима интерфейса. Есть полноценный интерактивный дашборд в терминале (TUI) с живыми графиками, упрощенный режим с прогресс-барами и тихий headless-режим для запуска в CI/CD пайплайнах.
- Воспроизведение реальных трейсов. Вместо синтетических запросов фиксированной длины можно скармливать дампы реального трафика. Из коробки поддерживаются форматы ShareGPT, BurstGPT (с реалистичными всплесками нагрузки), датасеты Bailian, Baseten и дампы логов сессий кодовых агентов вроде TraceLab.
- Умный контроль потока. Можно задавать распределения Пуассона для симуляции реальных пользователей, плавно наращивать нагрузку (ramping), сбрасывать KV-кэш между фазами теста через серверные хуки или запускать байесовскую оптимизацию для автоматического поиска максимальной нагрузки в рамках SLA.
Инструмент умеет цепляться к сторонним системам мониторинга. Если вам нужны дашборды в бою, доставляем модули:
pip install "aiperf[mlflow,otel,wandb]"
Это включает отправку метрик в OpenTelemetry, логирование прогонов в Weights & Biases или MLflow, а также сбор показателей утилизации GPU через NVIDIA DCGM.
Реальные сценарии использования
Где AIPerf спасает время:
- Выбор движка инференса. Хотите сравнить vLLM и SGLang на вашем железе под конкретную задачу? Прогоняете одинаковый трейс через AIPerf и смотрите не только на средний TPS, но и на деградацию ITL при росте параллельных сессий.
- Оценка спекулятивного декодирования. В репозитории есть поддержка метрик для speculative decoding: можно отслеживать процент принятых черновых токенов (draft acceptance rate) прямо во время теста.
- Тестирование агентных сценариев. При работе агентов контекст постоянно разрастается, забивая память видеокарты. AIPerf умеет эмулировать многошаговые диалоги с поддержкой общего префикса, проверяя эффективность префиксного кэширования сервера.
Ограничения и шероховатости
У проекта есть нюансы, с которыми можно столкнуться на практике. Если вы зададите неверный флаг в конфигурации, процесс иногда зависает на старте без понятной ошибки, приходится отменять его через Ctrl+C.
При экстремальных нагрузках свыше 15 000 одновременных соединений система рискует исчерпать доступные сетевые порты, так что лимиты ОС придется подкручивать руками.
Для строгого контроля длины генерируемого ответа нужно явно передавать параметры вроде ignore_eos на сторону инференс-сервера через аргумент --extra-inputs, иначе модель остановится раньше на первом встречном токене окончания текста.
Итоги
AIPerf закрывает пробел между наивными нагрузочными скриптами и громоздкими закрытыми бенчмарками. Если вы деплоите модели в прод, подбираете квантование или настраиваете параметры пакетной обработки (continuous batching), этот инструмент стоит положить в свой рабочий арсенал.
Начать проще всего с локальной модели в Ollama или vLLM, запустив базовый профиль с флагом --streaming, а дальше собрать YAML-конфиг под свой реальный профиль нагрузки.
