voyy.

BLOG ARTICLE

理解 LLM 推理性能:Latency、Throughput 与 Goodput

作者 voyy

1. 从一次 LLM 请求开始:PrefillDecode

在介绍指标之前,我们首先需要知道:LLM 是如何生成一段回答的? 对于典型的自回归大语言模型,一次生成请求可以粗略分成两个阶段:PrefillDecode

  • Prefill:模型对输入序列进行前向计算,处理 Prompt 中的所有 token,并为各层生成和缓存对应的 Key / Value(KV Cache),为后续自回归生成提供上下文。Prefill 的计算开销是 TTFT(Time To First Token) 的主要组成部分之一。
  • Decode:在已有 KV Cache 的基础上,模型以自回归方式逐步生成输出;每个 decoding step 生成一个新 token,并将该 token 对应的 Key / Value 追加到 KV Cache 中。Decode 阶段的性能主要体现在 TPOT(Time Per Output Token)ITL(Inter-Token Latency) 等持续生成延迟指标上。

2. LatencyThroughput

理解 Prefill 和 Decode 之后,我们就可以开始讨论最核心的问题:一个 LLM 推理系统到底快不快? 这里其实存在两个完全不同的观察视角:

  1. 站在用户的角度,我们关心的是:我需要等多久?这对应 Latency
  2. 站在服务器的角度,我们关心的是:单位时间内能够完成多少工作?这对应 Throughput

2.1 Latency 延迟

Latency 衡量模型处理单个请求的响应速度,直接影响用户体验,尤其是在聊天、代码补全等交互式场景中。常见指标包括:

  • TTFT(Time To First Token):从请求到达到第一个输出 token 返回的时间。TTFT 主要受到 Prefill 计算、请求排队和调度开销 影响。TTFT 越低,用户越快看到模型开始回复。
  • ITL(Inter-Token Latency):相邻两个输出 token 之间的时间间隔。ITL 描述 Decode 阶段流式生成的连续性。ITL 越低、波动越小,输出通常越流畅。
  • TPOT(Time Per Output Token):第一个 token 生成之后,平均生成一个后续 token 所需的时间。在用户看到文本逐字出现的流式场景中(例如 ChatGPT 的界面),TPOT 决定了体验的流畅程度。系统理想情况下应跟上或超过人类的阅读速度,以确保体验流畅。
  • E2E Latency(End-to-End Latency):从请求到达到完整响应生成结束的总时间。

一次 LLM 请求的时间线,以及各项延迟指标之间的关系如下图所示:

LLM 请求延迟指标时间线

简单来说:TTFT 决定“多久开始回答”,TPOT / ITL 决定“回答过程中有多快”,E2E Latency 则描述整个请求最终花了多久。

TPOT 和 ITL 的区别

  • 对于单个请求:Average ITL = TPOT
  • 但统计多个请求时,两者可能不同:
    • Average TPOT 通常是 request-weighted(按请求加权):先分别计算每个请求的 TPOT,再对所有请求取平均。它适合比较不同系统或配置下的单请求延迟,因为无论每个请求生成多少 token,所有请求都会被赋予相同的权重。
    • Average ITL 通常是 token-weighted(按 token 加权):将所有请求中的相邻 token 时间间隔汇总到一起,再除以总的 token 间隔数。因此,输出更长的请求由于贡献了更多 token,会占据更大的权重。它更适合衡量系统整体的稳定生成性能,例如聚合的流式生成速度。
  • 因此看 benchmark 时,一定要先确认论文或框架到底怎样定义 TPOT / ITL。不同的推理框架和论文可能会采用不同的计算方式,这会直接影响我们对性能数据的理解。

理解 Mean、Median 和 P99 Latency

在分析 LLM 性能,尤其是延迟时,只看一个数值通常是不够的。Mean、Median 和 P99 分别反映了性能的不同方面。

  • Mean(平均值):所有观测值之和除以样本数量。Mean 可以反映整体的平均性能,但容易受到极端值(outlier)的影响。例如,如果某一个请求的 TTFT 异常高,就会把整体平均值拉高。
  • Median(中位数):将所有观测值排序后位于中间的数值。Median 更能反映典型用户的体验,并且相比 Mean 对异常值更加稳定。如果 Median TTFT 达到 30 秒,就意味着大量用户都需要等待很长时间才能看到模型开始响应,这对于实时交互场景通常是不可接受的。
  • P99(99th Percentile,99 分位数):表示 99% 的请求延迟都低于或等于这个值。P99 用于观察延迟分布的尾部,可以反映最慢的一小部分请求的表现。当用户要求服务具有较高稳定性,或者 SLA (Service Level Agreement,服务级别协议) 要求 99% 的请求都必须满足某个延迟目标时,P99 尤其重要。例如,如果 P99 TTFT 接近 100 秒,就意味着虽然只有少量请求受到影响,但这些用户可能会经历非常严重的等待。

类似地,你还可能看到 P90 或 P95,分别表示 90 分位和 95 分位延迟。它们同样用于观察接近最坏情况的性能,在一些 P99 过于严格或容易受到噪声影响的场景中更加实用。

综合来看:

  • Mean:反映整体平均性能,也适合观察长期性能趋势。
  • Median:反映大多数用户的典型体验。
  • P99:反映尾部延迟(Tail Latency),而尾部延迟往往会直接影响生产环境中的用户体验和服务稳定性。

因此,在 LLM 性能 Benchmark 中,经常可以看到诸如 Mean TTFT、Median TPOT、P99 E2E Latency 这样的统计方式,用来从不同角度描述系统的延迟表现和用户体验。

2.2 Throughput 吞吐量

如果说 Latency 关注的是一个请求有多快,那么 Throughput 衡量的是推理系统在单位时间内能够处理多少工作量,反映系统整体的服务能力。常见的吞吐量指标包括:

Request Throughput

衡量系统单位时间内完成的请求数量,通常以 requests/sRPS,Requests Per Second)表示。

RPS 可以粗略反映系统处理并发请求的能力,但它并不能体现每个请求实际包含的工作量。例如,生成一句 “Hi there!” 和生成一篇长文,对模型造成的计算负载显然不同。因此,当不同 workload 的输入长度、输出长度或流量模式不同时,直接比较 RPS 可能会产生误导。

影响 RPS 的因素包括:

  • Prompt 的复杂度和长度
  • 模型规模和硬件配置
  • Batching、Caching、Inference Engine 等优化方式
  • 单个请求的延迟

Token Throughput

衡量系统单位时间内处理或生成的 Token 数量,通常以 token/sTPS,Token Per Second)表示。根据统计对象不同,可以进一步分为:

  • Input Token Throughput:整个推理系统单位时间输入 token 数量。
  • Output Token Throughput:整个推理系统单位时间生成的输出 token 数量。
  • Total Token Throughput:同时统计输入和输出 token 的总吞吐量。

同时关注 Input TPS 和 Output TPS,有助于根据不同推理 workload 判断性能瓶颈。例如:

  • 对于包含长文档的摘要任务,例如输入长度达到 2000 tokens,Input TPS 往往更加重要。
  • 对于短 Prompt、长输出的 Chatbot 场景,例如 20-token Prompt → 500-token ResponseOutput TPS 往往更加关键。

因此,在阅读 Benchmark 或评估 LLM 推理性能时,一定要确认 TPS 指的是 Input TPS、Output TPS,还是输入和输出合并后的统计结果。不同定义反映的是系统不同方面的性能。

影响 TPS 的因素主要包括:

  • Batch Size:增大 Batch Size 通常可以提升 TPS,直到系统达到饱和状态。
  • KV Cache 的效率与显存占用。
  • Prompt Length 和 Generation Length。
  • GPU Memory Bandwidth 和 Compute Utilization。

也正因为 TPS 会受到这些因素影响,它有时很容易被误读,甚至可以通过改变 Benchmark 配置让数字“看起来更高”。例如:

  • 更短的 Prompt 意味着每个请求需要完成的工作更少,因此某些测试条件下得到的 TPS 可能更高。
  • 更大的 Batch Size 和更高的并发度,可以让 GPU 保持更高利用率,从而提高系统聚合 TPS(Aggregate TPS);但与此同时,也可能增加请求排队时间,使 TTFT 或单用户 TPOT 变差

随着并发请求数不断增加,系统的总 TPS 通常会先持续上升,直到达到硬件计算或内存资源的饱和点(Saturation Point)。超过这个点之后,继续增加请求可能不再提高吞吐量,甚至会因为系统过载而导致整体性能下降。

3. 从 ThroughputGoodput:高并发下怎样才算“好”?

实际的 LLM Serving 系统通常需要在 Throughput 和 Latency 之间进行权衡:提高 Batch Size 和并发度可以提升系统吞吐量,但也可能增加请求排队时间,使 TTFT 或 TPOT 变差。如何在这种权衡下衡量一个系统真正“可用”的服务能力,就是这一节要讨论的 SLO 与 Goodput

3.1 为什么提高 Throughput 可能让用户变慢?

一个请求单独执行 Decode 时,每一步只有少量工作,并不一定能够充分利用 GPU。于是 Serving 系统通常希望:把多个 request 放进同一个 batch。比如:

Batch Size = 1

GPU
┌─────┐
│ Req │
└─────┘

变成:

Batch Size = 8

GPU
┌─────────────────────────────────┐
│ R1 R2 R3 R4 R5 R6 R7 R8        │
└─────────────────────────────────┘

更多请求一起处理,可以提高 GPU 利用效率,也往往可以提高整个系统的 throughput。但问题也随之出现。随着系统负载不断增大,请求可能需要排队;新的 Prefill 还可能与正在进行的 Decode 竞争执行机会。因此,追求更大的 batching 和更高的系统 throughput,可能同时带来 TTFT、TPOT 或 tail latency 的增加。

Sarathi-Serve 研究的核心问题正是这个 throughput–latency trade-off:Decode batching 有利于系统吞吐,但 Prefill 与 Decode 在同一 serving engine 中交错执行时,又可能造成延迟干扰。(arXiv)

可以把一个 LLM 服务粗略想象成:

Latency

   │                              ●
   │                         ●
   │                    ●
   │               ●
   │          ●
   │     ●
   │ ●
   └──────────────────────────────────→ Throughput

                           接近饱和

一开始增加负载时,系统 throughput 可以快速提高,而 latency 变化不大。

但达到某个区域以后,再继续压入请求,就会带来明显的排队和延迟增长。

因此: 一个系统把 GPU 跑得很满,并不等于用户体验就很好。

3.2 平均 Latency 也可能骗人

假设系统处理了 100 个请求:

99 个请求:100 ms
 1 个请求:10 s

如果只报告:

Average Latency

那个极慢的请求很容易被平均值掩盖。

因此在线服务通常还会看 latency distribution,也就是:

  • P50
  • P90
  • P95
  • P99

例如:P99 TTFT = 2 s

可以理解为:99% 的请求,其 TTFT 不超过大约 2 秒

为什么要关注 P99?因为对于服务系统来说:“大部分用户很快”还不够,我们还要知道最慢的那部分用户有多慢。 这就是所谓的 Tail Latency

Latency Distribution

可以用一个简单的分布图表示:

Requests

   │              █████
   │            █████████
   │         ██████████████
   │      █████████████████
   │   ████████████████████            ██
   │████████████████████████___________██
   └────────────────────────────────────────→ Latency

                ↑                       ↑
               P50                     P99

这比用一大段文字解释 P99 更直观。

3.3 SLO:多快才算“合格”?

知道 TTFT、TPOT、P99 之后,还有一个问题:

TTFT 到底多少才算快?

TPOT 到底多少才算好?

这个答案并不是固定的。一个离线文档总结任务,可能并不在乎首 token 是否晚几秒出现。一个 IDE 里的代码助手,却可能对响应延迟非常敏感。

所以生产系统往往不会简单地把目标定义为“Latency 越低越好”,而是先定义一个服务目标:SLO

SLO 是:Service Level Objective,服务水平目标。 可以简单理解成:系统希望达到的服务质量要求。

例如,我们可以规定 TTFT < 2 sTPOT < 50 ms。只有满足这些条件的请求,才算达到了我们定义的服务目标。

现实 benchmark 中确实存在这样的设计。比如 MLPerf Inference v6.0 的 GPT-OSS 120B Interactive 场景设置了 99th-percentile TTFT ≤ 2.0 s、TPOT ≤ 15 ms 的 latency constraints;DeepSeek-R1 Interactive 的约束则是 99th-percentile TTFT ≤ 1.5 s、TPOT ≤ 15 ms。这些具体阈值针对特定 benchmark workload,并不是所有 LLM 应用都应该照搬,但很好地展示了 SLO 的思想。(MLCommons)

也就是说,我们不再问:谁的 latency 最低?而开始问:在满足业务 latency 要求的前提下,这个系统到底能服务多少请求? 这一步,就自然引出了 Goodput。

3.4 Goodput:真正“有用”的 Throughput

假设有两个服务器:

  • Server A 最大可以处理 100 requests/s,但在高负载下,很多请求的 TTFT 都超过了我们的 SLO,最后只有 60 requests/s 满足要求。
  • Server B 的最大 Throughput 只有 85 requests/s,但其中 80 requests/s 都满足我们的 TTFT 和 TPOT 要求。

放在一起:

服务器 Throughput 满足 SLO 的吞吐量
Server A 100 req/s 60 req/s
Server B 85 req/s 80 req/s

如果只看 Throughput,A > B;但如果看真正符合服务质量要求的请求,B > A。于是就有了 Goodput。AIPerf 当前给出的定义非常直接:

Goodput = 满足所有 SLO 的请求数 ÷ Benchmark 持续时间

也就是:单位时间内,真正满足 SLO 的请求数量。 因此 Goodput 一定小于或等于 Request Throughput。(NVIDIA Docs)

DistServe 进一步把这一思想直接作为 LLM Serving 的系统优化目标:给定应用的 TTFT 和 TPOT 要求以后,优化系统能够在这些 latency constraints 下持续服务的最大 request rate,而不是单纯追求没有延迟约束的峰值 throughput。(arXiv)

vLLM 当前的 benchmark CLI 也已经直接提供:

--goodput

参数,可以针对 ttfttpote2el 设置 SLO,再计算相应的 goodput。(vLLM)

这让我们得到了一个很重要的结论:高 Throughput ≠ 好的 Serving 系统。

更完整的评价应该是:在满足 latency SLO 的前提下,系统能够保持多大的有效吞吐? 这才是 Goodput 真正想回答的问题。

Throughput 与 Goodput 对比

可以用一个简单的柱状图表示:

            Throughput       Goodput

Server A    ██████████       ██████
              100              60


Server B    ████████▌        ████████
               85              80

这也直观地说明了:最高 Throughput 并不一定意味着最高 Goodput。

4. 小结

如果关心单个用户感受到的响应速度,需要看 TTFT、TPOT 和 ITL;如果关心整个系统的处理能力,需要看 Throughput

但一旦进入真实的多用户 LLM Serving 场景,问题就会进一步变成 Throughput 与 Latency 的权衡,此时还需要关注 P99、SLO 与 Goodput。 最终可以用三句话概括:

  • Latency 回答:一个用户需要等多久。
  • Throughput 回答:整个系统能够处理多少工作。
  • Goodput 回答:在保证用户体验的前提下,系统真正能够处理多少工作。

Latency、Throughput 与 Goodput 的关系总结

参考资料

  • vLLM — Metrics:适合了解 vLLM 在真实 Serving 系统中如何记录 TTFT、ITL、E2E Latency、Queue Time、Prefill Time、Decode Time 等指标。(vLLM)
  • vLLM — vllm bench serve:可以进一步了解 TTFT、TPOT、ITL percentile,以及基于 SLO 的 Goodput benchmark 是如何实际落地的。(vLLM)
  • NVIDIA AIPerf Metrics Reference:我最推荐作为“指标字典”使用,对 TTFT、ITL、Per-user Throughput、System Throughput、Goodput 等指标都给出了明确公式。(NVIDIA Docs)
  • MLPerf Inference:适合了解工业标准 benchmark 为什么会同时设置 throughput 和 latency constraints,以及不同 workload 为什么需要不同 SLO。(MLCommons)
  • DistServe: Disaggregating Prefill and Decoding for Goodput-optimized Large Language Model Serving:如果想真正理解 Goodput 为什么重要,这篇最值得读。(arXiv)
  • Taming Throughput-Latency Tradeoff in LLM Inference with Sarathi-Serve:非常适合理解 Prefill / Decode 的执行特征以及 throughput–latency trade-off。(arXiv)