中文翻译暂不可用,显示俄语原文。

Как вы делаете load testing для LLM endpoint? Какие метрики ключевые?

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

Нагрузочное тестирование (load testing) LLM endpoint — это процесс симуляции реальной пользовательской нагрузки для оценки производительности, стабильности и масштабируемости сервиса. Ключевые метрики делятся на метрики задержки (latency: p50/p95/p99, TTFT, TPOT), пропускной способности (throughput: req/s, tokens/s), ошибок (error rate) и утилизации ресурсов (GPU utilization, memory). Инструменты вроде Locust, k6 и Gatling позволяют автоматизировать тесты и выявить узкие места до выхода в продакшн.


1. Термин: LLM endpoint

LLM endpoint — это HTTP(S) API, через которое клиенты отправляют запросы (prompt) и получают ответы от большой языковой модели. Endpoint может быть синхронным (ответ целиком) или стриминговым (токены по мере генерации). Нагрузочное тестирование имитирует множество одновременных запросов к этому endpoint, чтобы проверить его поведение под нагрузкой.

Зачем нужно нагрузочное тестирование

  • Убедиться, что endpoint выдерживает ожидаемый RPS (requests per second).
  • Найти узкие места: модель, инференс-сервер, сеть, база данных (если есть RAG).
  • Определить оптимальное количество реплик и конфигурацию GPU.
  • Проверить SLA (Service Level Agreement) по задержкам и проценту ошибок.

2. Инструменты для load testing

ИнструментЯзыкОсобенностиКогда использовать
LocustPythonСобытийно-ориентированный, легко писать сценарии на Python, встроенный веб-интерфейсЕсли команда владеет Python, нужна гибкость в сценариях
k6JavaScript (Go под капотом)Высокая производительность, встроенные метрики, поддержка HTTP/2, стримингКогда нужны точные метрики и CI/CD интеграция
GatlingScala (Java)Мощный, асинхронный, хорош для сложных сценариевВ Java/Scala-экосистеме, enterprise-проекты
Custom (wrk, hey, ab)C/GoПростые утилиты для быстрых тестовДля быстрой проверки без сценариев

Рекомендация для LLM endpoint с поддержкой стриминга лучше всего подходит k6 (есть модуль k6/net/grpc для gRPC, если endpoint на gRPC) или Locust с кастомным клиентом.


3. Ключевые метрики

3.1 Latency (задержка)

Latency — время от отправки запроса до получения ответа (или первого токена). Измеряется в миллисекундах.

  • p50 (медиана): половина запросов выполняется быстрее этого значения. Характеризует типичную задержку.
  • p95 95% запросов быстрее этого значения. Показывает «хвостовую» задержку.
  • p99 99% запросов. Критично для SLA.

Пример: если p95 latency = 2 с, значит 5% пользователей ждут дольше 2 секунд.

3.2 TTFT (Time to First Token)

TTFT — время от отправки запроса до получения первого токена ответа (только для стриминговых endpoint). Включает:

  • Сетевую задержку
  • Предобработку (tokenization)
  • Первый forward pass модели

Норма < 500 мс для интерактивных приложений, < 2 с для фоновых.

3.3 TPOT (Time Per Output Token)

TPOT — среднее время генерации одного токена после первого. Измеряется в мс/токен. Влияет на общую задержку при длинных ответах.

Формула TPOT = (total_latency - TTFT) / (number_of_output_tokens)

3.4 Throughput (пропускная способность)

  • Requests per second (req/s): количество завершённых запросов в секунду.
  • Tokens per second (tokens/s): количество сгенерированных токенов в секунду (суммарно по всем запросам).

Важно throughput зависит от batch size, размера модели, количества GPU. Для LLM часто bottleneck — это генерация токенов, а не количество запросов.

3.5 Error rate (процент ошибок)

Доля запросов, завершившихся с HTTP-кодом ошибки (4xx, 5xx) или таймаутом. Норма: < 1% для продакшна.

3.6 GPU utilization (утилизация GPU)

Загрузка GPU (compute, memory). Показывает, насколько эффективно используется оборудование. Низкая утилизация (< 50%) может указывать на узкое место в CPU/сети или неоптимальный batch size.

3.7 Дополнительные метрики


4. Процесс load testing

Шаг 1: Определение целей (SLA)

  • Максимальная latency (p95 < 2 с)
  • Минимальный throughput (100 req/s)
  • Максимальный error rate (< 0.5%)

Шаг 2: Выбор инструмента и написание сценария

Пример на k6 (JavaScript):

import http from 'k6/http';
import { check, sleep } from 'k6';

export const options = {
  stages: [
    { duration: '2m', target: 50 },  // ramp up
    { duration: '5m', target: 50 },  // steady
    { duration: '2m', target: 0 },   // ramp down
  ],
  thresholds: {
    http_req_duration: ['p(95)<2000'], // p95 < 2s
    http_req_failed: ['rate<0.01'],    // error rate < 1%
  },
};

export default function () {
  const payload = JSON.stringify({
    model: 'gpt-3.5-turbo',
    messages: [{ role: 'user', content: 'Hello, how are you?' }],
    stream: false,
  });
  const params = {
    headers: { 'Content-Type': 'application/json' },
  };
  const res = http.post('https://your-endpoint.com/v1/chat/completions', payload, params);
  check(res, {
    'status is 200': (r) => r.status === 200,
    'response time < 2s': (r) => r.timings.duration < 2000,
  });
  sleep(1);
}

Шаг 3: Запуск теста

  • Начинать с малой нагрузки (1-10 VUs), постепенно увеличивать.
  • Мониторить метрики в реальном времени (k6 dashboard, Grafana).

Шаг 4: Анализ результатов

  • Построить графики latency vs throughput.
  • Найти точку насыщения (saturation point), после которой latency резко растёт.
  • Проверить, не превышены ли пороги ошибок.

Шаг 5: Оптимизация

  • Увеличить batch size.
  • Добавить реплики (horizontal scaling).
  • Оптимизировать модель (quantization, pruning).
  • Настроить кэширование (KV cache).

5. Типичные проблемы и их диагностика

ПроблемаСимптомыВозможные причины
Высокая latency при малой нагрузкеp50 > 1 сМедленная модель, неоптимальный инференс-сервер (vLLM, TGI)
Резкий рост latency при увеличении VUsp95 растёт быстрее p50Узкое место в batch processing, очередь запросов
Высокий error rate5xx, таймаутыНехватка GPU памяти, перегрузка CPU, лимиты API
Низкая GPU utilization< 30%Маленький batch size, узкое место в CPU/сети
TTFT > 2 сПервый токен долгоПроблемы с сетью, предобработкой, кэшем

6. Best practices

  • Тестируйте стриминг отдельно метрики TTFT и TPOT важны для чат-приложений.
  • Используйте realistic payload длина промпта и количество токенов ответа должны соответствовать продакшну.
  • Проводите тесты на разных конфигурациях GPU: A100 vs H100 vs T4.
  • Автоматизируйте в CI/CD запускайте нагрузочные тесты перед каждым релизом модели.
  • Мониторьте не только endpoint, но и инфраструктуру: CPU, память, сеть, диск.
  • Учитывайте cold start первый запрос после развёртывания может быть медленнее из-за загрузки модели.

Пет-проект для закрепления

Задача Создать нагрузочный тест для LLM endpoint (например, локально поднятого через Ollama или API OpenAI) с помощью k6, измерить ключевые метрики и визуализировать их.

Инструменты

  • k6 (установить через brew install k6 или скачать с сайта)
  • LLM endpoint: локальный Ollama с моделью llama3.2:3b (или любой публичный API с ключом)
  • InfluxDB + Grafana (опционально, для визуализации)

Шаги:

  1. Установите Ollama и запустите модель: ollama run llama3.2:3b.
  2. Напишите скрипт k6, который отправляет POST-запросы к http://localhost:11434/api/generate с параметром stream: false.
  3. Настройте stages: ramp up до 20 VUs за 1 минуту, steady 3 минуты, ramp down 1 минута.
  4. Добавьте thresholds: p95 latency < 5s, error rate < 2%.
  5. Запустите тест: k6 run script.js.
  6. Проанализируйте вывод: summary с метриками, графики latency.
  7. (Опционально) Настройте экспорт в InfluxDB и постройте дашборд в Grafana.

Ожидаемый результат

  • Вы получите отчёт с p50/p95/p99 latency, throughput (req/s), error rate.
  • Увидите, как latency растёт с увеличением числа виртуальных пользователей.
  • Сможете определить максимальную нагрузку, при которой SLA ещё выполняется.

Связь с другими вопросами

ВопросТема
7Как вы уменьшаете latency RAG-системы (время ответа)?
8Как вы обрабатываете запросы, на которые нет ответа в документах?
9Как вы обновляете документы в существующей RAG-системе?
10Что такое Self-RAG и когда его использовать?
11Как вы оцениваете качество генерации (faithfulness, answer relevance)?
12Как вы деплоите LLM в production (инференс-серверы, масштабирование)?

Навигация