性能度量:TTFT、TPOT、吞吐与延迟分位数
一句话定义
推理性能度量用 TTFT(首 token 时间)、TPOT(每 token 时间)、吞吐(tokens/s)与延迟分位数(P50/P99)四组指标,把"快"拆成可优化、可验收的数字。
为什么重要
没有正确的度量就没有正确的优化:把"平均延迟"当 KPI 会掩盖长尾,把"GPU 利用率"当容量指标会导致误扩容,把裸压测吞吐当承诺会让线上事故。度量是本库所有知识点的验收语言——每项优化"值不值"最终都要换算回这几个数字。
前置知识
- kp-001(优化四象限与本领域问题设定)。
核心概念
- TTFT(Time To First Token):请求发出到第一个 token 返回的时间,由排队时间 + prefill 时间构成,决定"响应快不快"的体感。
- TPOT(Time Per Output Token):首 token 之后平均每个输出 token 的间隔,决定"打字机流不流畅";其倒数即单流 decode 速度。
- 吞吐(Throughput):系统单位时间产出的总 token 数,分请求吞吐与系统吞吐,必须写明并发数。
- 端到端延迟(E2E Latency):TTFT + 输出 token 数 × TPOT。
- 分位数 P50/P99:把延迟排序,P99 表示 99% 的请求快于该值;SLO 应写在 P99 上。
公式与模型
数值例子:一个请求 prefill 120ms、输出 200 个 token 共耗时 8.12s,则 TPOT = (8120 − 120)/199 ≈ 40ms/token,对应单流 decode 约 25 tokens/s。
原理与机制
指标之间天然互相牵制:提高并发 batch size 会拉高吞吐、同时拉高 TPOT 与排队 TTFT;投机解码降低 TPOT 但验证占用算力,大并发下反而压吞吐。因此工程上先定 SLO(如 TTFT P99 < 800ms、TPOT P99 < 50ms),再在满足 SLO 的前提下最大化 goodput,而不是最大化裸吞吐。
图示
时间轴上一个流式请求:
|--排队--|--prefill--|--decode×N(每 TPOT 一个 token)--|
^请求发出 ^第一个token(TTFT) ^结束
实例或案例
一次规范压测(可复现流程):①固定输入/输出长度(如 in 512 / out 128)与采样参数、固定随机种子;②预热 20 个请求再开始计时;③并发从 1、4、16、64 逐级加压,每级记录 TTFT/TPOT/E2E 的 P50/P99 与系统吞吐;④绘制"吞吐–P99 TPOT"曲线,SLO 约束线与曲线的交点就是该配置的最大可用并发。vLLM 自带的 benchmark_serving 脚本就是按这套口径输出的。
常见误区
- 只看平均值:decode 长尾被短请求稀释,P99 可能是均值 5 倍以上。
- 混淆单流速度与系统吞吐:"25 tokens/s" 可以是单请求速度,也可以是 64 并发下的人均速度,汇报必须带并发数。
- 用理论峰值做容量承诺:应以实测 P99 与 goodput 为准。
- 忽略 prefill:长输入场景 TTFT 主要由 prefill 决定,优化 decode 无济于事。
自测题
- 一个请求 TTFT=300ms,之后 99 个 token 用了 4.7s,求 TPOT 与 E2E。
要点:TPOT = 4700/99 ≈ 47.5ms;E2E = 5s。
- 为什么 SLO 要写在 P99 而不是平均值上?
要点:平均值掩盖长尾,而用户体验与故障往往由长尾决定。
- 加大 batch 会让哪些指标变好、哪些变差?
要点:吞吐变好;TPOT 变大、排队 TTFT 变长。
与其他知识点的关系
kp-003 解释 TTFT/TPOT 背后的两阶段计算;kp-021 说明批处理如何在吞吐与 TPOT 间取舍;kp-028 把这些指标折算成成本。
延伸阅读
《Orca: A Distributed Serving System for Transformer-Based Generative Models》(Yu 等,2022)第一节对"请求级 vs 迭代级"调度与延迟指标的讨论值得一读。