3、性能指标:延迟、吞吐量、首Token延迟(TTFT)、Token间延迟(ITL)的定义与测量

在vLLM推理性能调优中,如果只关注一个数字,往往会误入歧途。延迟(Latency)和吞吐量(Throughput)是宏观指标,而首Token延迟(TTFT)与Token间延迟(ITL)则是微观分解指标。只有将四者组合起来,才能准确判断瓶颈究竟在预填充(Prefill)阶段还是解码(Decode)阶段,进而指导后续的调优动作。

3.1 核心定义:四个指标各代表什么

先明确每个指标的业务含义与技术含义,避免在测量时张冠李戴。

指标 全称 定义 关注阶段 典型量级(参考)
延迟 Latency 从客户端发送完整请求到收到完整响应的总耗时 端到端 数百ms ~ 数十s
吞吐量 Throughput 单位时间内系统处理的请求数或生成的Token数 系统整体 req/s 或 tokens/s
TTFT Time To First Token 从请求发出到收到第一个输出Token的时间 预填充(Prefill) 50ms ~ 2s
ITL Inter-Token Latency 相邻两个输出Token之间的时间间隔(即单Token生成耗时) 解码(Decode) 10ms ~ 100ms/token

关键关系:延迟 ≈ TTFT + ITL × (输出Token数 - 1)。这个公式是性能拆解的基石,它把端到端延迟分解为“首Token等待”和“后续Token生成”两部分。

推理延迟分解:TTFT 与 ITL 的关系 时间 → 请求发出 预填充阶段 处理输入Prompt 并行计算所有输入Token TTFT(首Token延迟) 首个Token 解码阶段 逐个生成Token 每个Token依赖前一个Token ITL(Token间延迟) 端到端延迟 = TTFT + ITL × (N-1) 完整响应 TTFT 反映模型“理解”输入的速度,ITL 反映模型“生成”输出的速度 两者分别对应 Prefill 和 Decode 两个计算阶段

3.2 测量方法:如何准确获取四个指标

测量方式决定了数据的可信度。vLLM 提供了内置的统计接口,同时也支持通过客户端埋点进行端到端测量。

3.2.1 服务端指标获取

vLLM 的 /metrics 端点暴露 Prometheus 格式的指标,其中直接包含 TTFT 和 ITL 的直方图统计:

# 通过 Prometheus 端点获取
curl -s http://localhost:8000/metrics | grep -E "vllm:(time_to_first_token|inter_token)"

# 关键指标示例
vllm:time_to_first_token_seconds_sum{model="llama-3-8b"} 12.345
vllm:time_to_first_token_seconds_count{model="llama-3-8b"} 150
vllm:inter_token_latency_seconds_sum{model="llama-3-8b"} 45.678
vllm:inter_token_latency_seconds_count{model="llama-3-8b"} 1200

通过 sum / count 即可得到平均 TTFT 和平均 ITL。若要观察分位数(如 P95),需要配置 Prometheus 的 histogram_quantile 函数。

3.2.2 客户端埋点测量

对于端到端延迟和业务视角的 TTFT,推荐在客户端进行埋点:

import time
import requests

start = time.perf_counter()
resp = requests.post(
    "http://localhost:8000/v1/completions",
    json={"model": "llama-3-8b", "prompt": "..."},
    stream=True
)

# 记录首Token时间
first_token_time = None
tokens = []
for chunk in resp.iter_lines():
    if chunk:
        if first_token_time is None:
            first_token_time = time.perf_counter()
        tokens.append(chunk)

end = time.perf_counter()

ttft = first_token_time - start
itl = (end - first_token_time) / max(len(tokens) - 1, 1)
total_latency = end - start

测量建议:至少测量 100 个请求以上,并记录 P50、P95、P99 三个分位数。仅看平均值会掩盖长尾延迟问题。

3.3 案例:一次典型的性能诊断过程

假设我们有一个 Llama-3-8B 模型部署在单张 A100 上,输入 Prompt 为 500 Token,输出 200 Token。通过监控面板得到以下数据:

  • 平均 TTFT = 850ms
  • 平均 ITL = 35ms/token
  • 端到端延迟 = 850 + 35 × 199 = 7815ms ≈ 7.8s
  • 吞吐量 = 200 tokens / 7.8s ≈ 25.6 tokens/s(单请求视角)

从数据中我们可以解读出:

  1. TTFT 占比约 11%(850/7815),说明预填充阶段不是主要瓶颈。
  2. ITL 是主要耗时来源,199 个 Token 消耗了约 7 秒,说明解码阶段效率需要优化。
  3. 如果 TTFT 超过 2 秒,则应该关注 Prefill 的计算优化或输入长度裁剪。
  4. 如果 ITL 超过 50ms,则应该关注 KV Cache 命中率、显存带宽或批处理大小。

常见误区:不要只优化 TTFT 而忽略 ITL。在长输出场景(如代码生成、长文总结)中,ITL 对总延迟的影响远大于 TTFT。反之,在交互式对话场景中,TTFT 直接影响用户的第一感知。

3.4 吞吐量与延迟的权衡

吞吐量和延迟往往存在矛盾:提高吞吐量(如增大 Batch Size)通常会牺牲单请求延迟。vLLM 的 Continuous Batching 机制正是为了在两者之间取得更好的平衡。

场景 优先指标 调优方向
在线对话/搜索 TTFT(低延迟) 减小 Batch Size、启用 Prefix Caching、使用更小模型
离线批量处理 吞吐量 增大 Batch Size、使用更长序列、启用 Chunked Prefill
流式输出应用 ITL(稳定节奏) 优化 Decode 阶段、增加显存带宽、使用量化

3.5 复盘:指标测量中的常见问题

在实际测量中,以下问题会导致数据失真,需要特别注意:

  • 冷启动污染:模型首次推理包含权重加载和 CUDA 初始化,应预热 5-10 个请求后再开始统计。
  • 并发干扰:在并发请求下,单个请求的 TTFT 和 ITL 会相互影响。应分别测量单请求独占和稳定并发两种场景。
  • 网络开销:客户端测量的 TTFT 包含网络往返时间。若需精确测量服务端处理时间,应使用 vLLM 内置指标。
  • 输出长度影响:ITL 会随输出长度增加而略微上升(KV Cache 增大导致访存压力),应记录输出长度并分段统计。
  • 忽略排队时间:在高负载下,请求可能在队列中等待。此时 TTFT 会显著增大,但这并非模型计算变慢,而是调度瓶颈。

最佳实践:建立性能基线时,固定输入长度(如 512 Token)、输出长度(如 128 Token)、并发数(如 1/8/32 三档),分别记录 TTFT、ITL、端到端延迟和吞吐量。每次调优后对比同一基线,才能准确评估优化效果。