想象你走进一家面馆,点了一碗牛肉面。从按下“下单”键到第一根面条送进嘴里,少说也要等上几十秒。如果赶上饭点,门口还排着长队,这道菜的上桌时间就更没法保证。聪明的老板会在后厨装一块数字看板,实时滚动着:当前接到多少单、每单从下单到出餐等了多久、出餐速度是多少、队伍排到了门口还是马路对面——有了这些数字,老板才知道该多加一口锅、还是把煮面流程改一改。 LLM应用(比如你手机里的 AI 客服)和这家面馆惊人地相似。用户每发一句话,模型就要生成一段回复——而这段回复不是一口气吐出来的,它像面条一根根从锅里捞出来一样,一个字一个字地蹦。从“用户发出请求”到“第一个字返回”的等待时间,业界叫TTFT(首Token延迟);之后每个字蹦出来的快慢,叫TPS(每秒生成Token数)。问的人一多,请求就在服务端排起队,于是有了队列深度。Langfuse、Phoenix 这类工具,扮演的正是后厨那块数字看板。 这篇文章,我们就用“面馆经营”的视角,把 LLM 应用的性能监控从零讲透:延迟怎么拆、吞吐怎么算、队列怎么看、工具怎么用、瓶颈怎么找、优化怎么落地。看完你不仅能看懂监控面板上的每一个数字,还能像一位老练的后厨主管一样,用数据精准定位 AI 服务变慢的根因。

岗位关联

学会这套延迟与吞吐量监控方法,你就能用数据说话,为 LLM 服务的容量规划、瓶颈定位和模型选型提供可靠依据,这是 AI 工程化落地中不可或缺的硬技能。

目录
  1. 可视化演示
  2. 延迟拆解:一碗面从下单到上桌的旅程
  3. 吞吐量指标:餐厅同时能喂饱多少人
  4. 队列分析:等位区里藏着的秘密
  5. 监控工具:后厨的透明看板
  6. 瓶颈定位:找到后厨最慢的环节
  7. 优化策略:让厨房真正跑起来
  8. AI 应用场景
  9. Python 演示
  10. 常见误区
  11. 面试题

可视化演示

本节配有交互动效(进入视口后自动加载,约 3KB)。

Token级延迟分解 (ms) 吞吐量与并发分析 待处理请求 SLO达成率与告警 LLM推理性能监控:TTFT首Token延迟、TPOT每Token延迟、TPS生成速率与QPS吞吐量实时追踪

延迟拆解:一碗面从下单到上桌的旅程

想象你走进一家面馆,坐下扫码下单。从手指按下“提交订单”那一刻到第一根面条送进嘴里,你的等待其实被分割成了好几段:等菜单传进后厨、等厨师烧水下面、等面条被端上桌。如果每一段都慢半拍,这碗面就要等上十几分钟。LLM应用完全一样——用户问了一句“我的订单到哪儿了”,模型在回复之前,背后也有一条清晰的“上餐流水线”。

在LLM的世界里,这条流水线的“菜品”是一个个Token(可以理解为单词或子词片段)。衡量一次请求的快慢,业界把整条链路拆成两个核心阶段:等待第一个Token的“第一口汤”时间,和后续Token逐个蹦出来的“持续上菜”速度。前者叫TTFT(Time To First Token,首Token延迟),后者用TPS(Tokens Per Second,每秒Token数)表示。此外还有从请求发出到最后一个Token落地的端到端延迟,它是整碗面从下单到吃完的时间总和。

先看TTFT,它等于“用户发出请求”的时刻到“收到第一个Token”的时刻之差,记为:

再看TPS,它衡量第一个Token之后模型的生成速度:

回到面馆:TTFT就像你等第一根面条从厨房窗口递出来的时间,TPS则是面条被一根根连续送到你面前的速度。一家好面馆不仅要“第一口快”,更要“后面不卡壳”——LLM服务也是这样,TTFT和TPS两个指标必须同时看,缺一不可。

TTFT=tfirst_token−trequest_sent\displaystyle \text{TTFT} = t_{\text{first\_token}} - t_{\text{request\_sent}}
通俗含义:把请求发出的时刻和第一个字返回的时刻分别打上时间戳,两者相减,就是用户屏息等待的秒数。它包含了网络传输、排队、显存分配和模型Prefill(提示词预填充)的全部时间。
TPS=Ntokentlast_token−tfirst_token\displaystyle \text{TPS} = \frac{N_{\text{token}}}{t_{\text{last\_token}} - t_{\text{first\_token}}}
通俗含义:从第一个字到最后一个字,总共生成了多少个字、花了多少秒,两者相除就是每秒吐出多少个Token。这个值越大,后半程的“上菜”越流畅。
  1. t_request_sent(请求发出时刻)客户端把请求数据包发出网络的那一刻,这是整个延迟计时的起点,通常由SDK自动打点记录。
    trequest_sentt_{\text{request\_sent}}
  2. t_first_token(首Token到达时刻)服务端返回的响应流中第一个Token落地的时刻,这是TTFT计时的终点,标志着用户终于“看见”了第一个字。
    tfirst_tokent_{\text{first\_token}}
  3. 相减得到TTFT(首Token延迟)终点减起点,得到用户等待第一个字的时长,单位常用毫秒或秒,是LLM应用最核心的体验指标之一。
    TTFT=tfirst_token−trequest_sent\text{TTFT} = t_{\text{first\_token}} - t_{\text{request\_sent}}
  4. N_token(生成Token总数)一次请求中模型完整生成的所有Token数量,是TPS公式的分子,代表这碗面总共捞出了多少根面条。
    NtokenN_{\text{token}}
  5. t_last - t_first(生成耗时)从第一个Token到最后一个Token的累计时间,即“上菜过程”的持续时间,分母越大说明后半程越拖沓。
    tlast_token−tfirst_tokent_{\text{last\_token}} - t_{\text{first\_token}}
  6. 相除得到TPS(生成速度)总Token数除以生成耗时,得到每秒生成Token的速度,数值越高,用户在等待后半段回复时的体验越好。
    TPS=Ntokentlast_token−tfirst_token\text{TPS} = \frac{N_{\text{token}}}{t_{\text{last\_token}} - t_{\text{first\_token}}}

吞吐量指标:餐厅同时能喂饱多少人

假设面馆只有一位厨师,每位顾客要等10分钟才能吃上一碗面。如果店里同时坐着五位顾客,最后一位顾客可能足足等了50分钟。但如果厨房有五个灶台,情况就完全不同了。这就引出了“吞吐量”:餐厅在单位时间内到底能接待多少位顾客完成用餐。对应到LLM服务,吞吐量通常指单位时间内系统完成的生成请求数或生成的Token总数,它回答的是“这个服务能扛住多少用户”。

吞吐量受两个关键因素支配:同时处理的请求数(并发数)和每个请求的生成速度(TPS)。厨房里同时开火几口锅,每口锅每分钟出几碗面,两者乘起来就是整家店的总出餐能力。对于一个运行稳定的服务,有效吞吐量可以近似表示为:

需要提醒的是,一味增加灶台并不总是好办法——并发开得太多,每口锅的火力反而会被分摊(GPU显存被瓜分),单个请求变慢,甚至触发显存溢出。吞吐量与单请求延迟之间是一场精细的权衡:并发拉到最大时系统吞吐可能最高,但用户侧的TTFT和TPS已经恶化到不可接受了。监控时要用“有效吞吐”而非“理论吞吐”来做容量基线。

回到面馆的比喻:老板不会为了多接待客人就把灶台加到一百个,因为厨房就那么大。他会算出“最佳并发——既能喂饱最多的客人,又不会让每碗面的质量塌方”,这套思路与LLM服务的容量规划完全同构。

Throughput=Concurrency×AvgTPS\displaystyle \text{Throughput} = \text{Concurrency} \times \text{AvgTPS}
通俗含义:同时开几桌、每桌吃多快,两者相乘就是整个餐厅的出餐总量。注意这里的AvgTPS是所有并发请求的平均生成速度,而不是单个请求的TPS。
  1. Concurrency(并发请求数)同一时刻正在被服务端处理的请求数量,相当于同时开火的灶台数。并发越高,理论上能同时服务的顾客越多。
    Concurrency\text{Concurrency}
  2. AvgTPS(平均生成速度)所有并发请求的单个TPS的平均值,代表每口锅的平均出餐速度。它受模型大小、硬件和推理引擎共同影响。
    AvgTPS\text{AvgTPS}
  3. 相乘得到有效吞吐量并发数与平均速度相乘,就是单位时间内系统产出的Token总量。这个指标决定了你能否支撑起千万级用户的AI产品。
    Throughput=Concurrency×AvgTPS\text{Throughput} = \text{Concurrency} \times \text{AvgTPS}

队列分析:等位区里藏着的秘密

任何一家热门餐厅门口都有一个等位区。顾客到得多了,座位满了,新到的人只能排队。队伍的长度直接反映了餐厅的“供不应求”程度:队排得越长,说明顾客来的速度远比厨师出餐的速度快。LLM服务前也有一道“等位区”——请求队列。当并发请求超过服务处理能力时,新请求就会进入队列等待。

队列深度(当前排队的请求数)是判断服务负载状态的关键信号。如果队列持续很深,说明系统已经超负荷运转:即使每个请求本身处理得很快,用户真正感受到的响应时间也会因为排队而变得很长。这就像面条做得再快,前面排着二十个人,你也得干等。相反,队列长期为空,则说明服务资源有富余,可以考虑提高并发或缩容省钱。

排队理论中有一条著名的Little定律,它像交通守恒定律一样,把队列中的三个核心量统一了起来:

监控队列深度,就像看餐厅门口的等位人数。等位人数突然暴涨,要么是顾客(请求)来得太猛,要么是厨师(模型推理)出餐速度掉了。顺着这两个方向分别去查到达速率和服务耗时,就能快速锁定问题来自流量的洪峰还是服务能力的塌陷。队列并不是洪水猛兽——适度的排队是系统吸收突发流量的缓冲垫,真正危险的是队列无限增长导致的服务雪崩。

L=λ×W\displaystyle L = \lambda \times W
通俗含义:队列中的平均请求数(L)等于请求到达速率(λ)乘以每个请求在系统中的平均逗留时间(W)。这两个因素任何一个变大,队伍都会变长。
  1. L(队列中的平均请求数)任意时刻系统中正在排队和正在处理的请求数量之和,它是队列深度的统计期望值。
    LL
  2. λ(请求到达速率)单位时间内到达服务端的新请求数量,相当于顾客进店的速率,通常用每秒多少个请求来衡量。
    λ\lambda
  3. W(平均逗留时间)一个请求从进入队列到处理完成所花的总时间,等于排队时间加服务时间之和。
    WW
  4. 三者由Little定律统一排队中请求数等于到达速率乘以平均逗留时间。只要知道任意两个量,就能算出第三个,这是容量规划的基础工具。
    L=λ×WL = \lambda \times W

监控工具:后厨的透明看板

一家连锁餐厅的总部想了解每个分店后厨的真实状况,靠打电话问“你那边慢了没”是不靠谱的。正规做法是装一套数字化看板:每个灶台、每个传菜口都装上传感器,总部随时能看到每道菜从下单到出锅的完整时间线。LLM服务的监控工具扮演的正是这个角色——它让每一次请求的内部环节全部透明化。

在LLM可观测性领域,主流开源工具包括Langfuse和Phoenix(Arize Phoenix)。它们的核心能力一致:把一次完整的LLM请求拆成一个Trace(调用链)和若干Span(环节),每个环节记录耗时、Token数、模型名等元数据。工程师在UI上就能看清“输入处理→模型调用→工具调用→输出返回”每一段的耗时占比,就像看后厨每个工位的实时录像。

接入Langfuse一般分两步:配置Endpoint和API Key,然后安装SDK。在Python侧的初始化通常长这样:

接着用SDK提供的装饰器或上下文管理器包装LLM流式调用,就能自动记录TTFT、TPS、Token用量和延迟分布。Phoenix则更偏底层链路追踪,适合与OpenTelemetry生态配合,把Prompt、响应、嵌入向量一并落库,供后续离线分析。两者都支持把监控数据汇总成可视化面板,用时间序列曲线展示P50/P99延迟、队列深度和吞吐量。

有了这块“透明看板”,后厨的一切效率问题都不再是猜谜。哪个环节慢、哪个模型贵、哪个Prompt经常触发超时,一眼就能定位。Langfuse和Phoenix这类工具让LLM运维从“玄学”变成了“科学”——它们采集的数据,正是当前面所有延迟、吞吐、队列指标的源头。

python6 行
from langfuse import Langfuselangfuse = Langfuse(    public_key="pk-...",    secret_key="sk-...",    host="http://localhost:3000")

瓶颈定位:找到后厨最慢的环节

假设面馆出餐变慢,是面下锅太慢、汤底没熬好、还是服务员传菜太磨蹭?经理拿着一块秒表蹲在后厨,逐个环节计时,很快就会发现真相。LLM服务的性能调优,做的就是同一件事:用监控数据把“变慢”这个笼统的抱怨,拆解成具体环节的具体数字。

LLM推理的两个阶段速度差异巨大。Prefill阶段(处理用户的提示词Prompt)是一次性并行计算,通常很快;Decode阶段(逐个生成Token)是逐Token串行完成的,往往占据大头。如果监控显示TTFT暴涨,问题大概率在Prefill或排队环节;如果TPS偏低,则往往指向Decode阶段的显存带宽或模型结构瓶颈。就像面馆里,如果“第一口”等很久,可能是下单流程堵了;如果“后面上菜慢”,可能是煮面锅的产能不行。

常见的瓶颈点有三个。第一是显存:模型权重加上KV Cache是否挤爆了GPU,显存不足会触发换页,速度断崖式下跌。第二是推理引擎:vLLM、TGI等引擎的优化程度差异巨大,是否开启PagedAttention、是否启用连续批处理,直接影响吞吐上限。第三是模型参数:模型参数量与量化精度(FP16还是INT8)共同决定单卡吞吐,更大的模型不一定更聪明,但一定更慢。

定位瓶颈时重点看两块监控数据:GPU显存利用率和KV Cache的命中情况。显存长期逼近100%说明硬件是短板;显存还有富余但TPS仍然上不去,说明引擎配置或模型结构才是瓶颈。这两个信号能帮你快速区分是“硬件不够”还是“引擎没调好”。用秒表逐环节计时是件看似枯燥的事,却是调优中最值得的投资——至少你不会在“汤底不够鲜”的问题上白白加十口锅。

优化策略:让厨房真正跑起来

找到了瓶颈,下一步就是改造厨房。聪明的面馆老板不会只买一口更大的锅,他会统筹安排:错峰备料、批量下面、把常点的浇头提前煮好。LLM服务也一样,优化不是单一技巧,而是一套组合拳——针对前面定位到的瓶颈,选择性地施药。

最有效的三招是动态批处理、并发控制和缓存复用。动态批处理(Continuous Batching)把多个请求拼成一个batch喂给模型,摊薄计算开销——就像厨师把四碗面同时下进一口大锅,虽然单碗面没变快,但整体的“出餐总量”大幅提升。vLLM等推理框架默认支持该特性,生产环境应优先开启。

并发控制通常在网关层实现,用信号量限制同时进行的模型调用数量。这听起来和“提高吞吐”矛盾,但实际防止了过载雪崩:当并发超过服务能力时,每个请求都被拖慢,吞吐反而下降。就像餐厅不会让所有客人同时挤进后厨,而是在门口限流,保证每位已入座的客人都能按时吃上饭。缓存复用则分两种:对重复的Prompt前缀做KV Cache复用,能省去重复的Prefill计算;对常见问题做结果缓存,命中后延迟能降到十几毫秒,几乎等于免费上菜。

优化生效后,监控数据会告诉你一切:TTFT下降了吗?TPS上升了吗?队列深度回到安全水位了吗?记住,性能调优不是一锤子买卖,而是“监测→定位→优化→再监测”的循环。每一次微小的优化,都会让下一碗面的上桌时间更短一点;而持续的循环迭代,才能让系统的每一项指标都稳步逼近目标值。厨房的改造永无止境,但方向和依据永远来自那块看板上的数字。

AI 应用场景

场景1:LLM在线服务TTFT劣化排查

阶段:模型部署与推理优化

解决的问题:线上AI客服的TTFT从800ms暴涨到2.5秒,用户纷纷投诉“回复变慢了”。传统排查只能靠重启服务或拍脑袋,无法定位慢在哪一环。

具体案例:运维团队在Langfuse上按Trace拆解后发现,2.5秒中有1.5秒花在请求队列等待上,Prefill只占0.3秒。进一步查看队列深度曲线,发现是上游网关把并发限制从20调到了50,超过了推理服务的实际处理能力。将并发限制回调到30并启用vLLM动态批处理后,TTFT回到1秒以内。

场景2:ChatBot并发能力规划

阶段:容量规划与负载测试

解决的问题:企业AI助手上线前不知道服务能扛多少并发用户,上线后被流量挤爆的案例屡见不鲜。

具体案例:某企业内部AI助手计划支持200人同时在线。团队用监控工具在压测环境模拟并发请求,发现单实例在20并发时TPS降至不足5、P95延迟超5秒。通过增加实例并开启连续批处理后,40并发下TPS稳定在12、P95延迟降到2秒,以此数据规划出3副本的部署方案。

场景3:生产环境持续性能监控

阶段:可观测性与告警

解决的问题:模型版本升级后出现性能回退,用户不投诉就很难察觉,等发现时损失已造成。

具体案例:某团队将LLM从v1升级到v2后的第二天,Phoenix监控面板显示TTFT从800ms涨到2.5秒、吞吐量下降40%。通过对照Trace数据定位到新模型Decoder结构导致Decode阶段变慢,随即回滚到v1版本。监控数据让团队在用户大规模受影响之前就完成了处置。

Python 演示

python66 行
import randomimport time  def simulate_token_stream(start_time, ttft, tps, total_tokens=50):    """Simulate a token arrival timeline for one LLM request."""    events = []    first_token_time = start_time + ttft    for i in range(total_tokens):        if i == 0:            t = first_token_time        else:            interval = random.expovariate(tps)            t = events[-1][0] + interval        events.append((t, i + 1))    return events  def compute_metrics(events, request_start):    """Compute TTFT, TPS and total latency from token timeline."""    first_token = events[0][0]    last_token = events[-1][0]    total_tokens = len(events)    ttft = first_token - request_start    generation_time = last_token - first_token    tps = total_tokens / generation_time if generation_time > 0 else 0.0    total_latency = last_token - request_start    return {        "ttft_s": round(ttft, 3),        "tps": round(tps, 3),        "total_tokens": total_tokens,        "total_latency_s": round(total_latency, 3),    }  def simulate_concurrent_load(concurrency, ttft, tps, tokens=50):    """Estimate effective throughput under concurrent requests."""    req_list = []    for _ in range(concurrency):        start = time.time() + random.uniform(0, 0.5)        events = simulate_token_stream(start, ttft, tps, tokens)        req_list.append(compute_metrics(events, start))    total_tokens = sum(m["total_tokens"] for m in req_list)    total_time = max(m["ttft_s"] + m["total_tokens"] / m["tps"] for m in req_list)    throughput = total_tokens / total_time if total_time > 0 else 0.0    return throughput  def main():    random.seed(42)    start = time.time()    events = simulate_token_stream(start, ttft=0.8, tps=15.0)    m = compute_metrics(events, start)    print("=== Single Request Metrics ===")    print("TTFT (s):", m["ttft_s"])    print("TPS (tokens/s):", m["tps"])    print("Total tokens:", m["total_tokens"])    print("Total latency (s):", m["total_latency_s"])     tp = simulate_concurrent_load(10, ttft=0.8, tps=15.0)    print("\n=== Concurrent Throughput (10) ===")    print("Effective throughput (tokens/s):", round(tp, 2))  if __name__ == "__main__":    main()
目的:用蒙特卡洛模拟模拟一次LLM流式请求的Token到达时间线,计算TTFT、TPS、端到端延迟,并估算并发场景下的有效吞吐量——这正是监控系统在后台做的核心数学运算。
  1. events = simulate_token_stream(start, ttft=0.8, tps=15.0)生成一份带真实时间戳的Token到达时间表,模拟一次流式响应
  2. interval = random.expovariate(tps)用指数分布模拟Token生成间隔,均值正好等于1/TPS,符合LLM解码过程的统计特性
  3. ttft = first_token - request_start首个Token时间戳减去请求发出时间戳,就是首Token延迟TTFT
  4. tps = total_tokens / generation_time总Token数除以纯生成耗时,得到每秒生成Token数
  5. total_time = max(m["ttft_s"] + m["total_tokens"] / m["tps"] for m in req_list)一批并发请求中,最后完成的那个请求决定整批耗时,这是有效吞吐的计算基础
  6. tp = simulate_concurrent_load(10, ttft=0.8, tps=15.0)模拟10个并发请求,估算系统在给定并发下的总吞吐量
  7. random.seed(42)固定随机种子,保证每次运行结果可复现,方便调优前后对比

常见误区

误区我把TPS从10优化到了20,性能肯定翻倍了!用户应该感觉快多了吧?

正解TPS只衡量生成阶段的速度,TTFT可能仍然是瓶颈。就像厨师下面再快,你的面单在收银台卡了十分钟,用户照样急得跺脚。优化必须同时看TTFT和TPS,还要看P50/P99分布,单独追求任一指标都可能事倍功半。

为何常见:人的直觉是“快就是好”,但延迟是分段叠加的,单段最快不等于整体最优,这是初学者最容易踩的坑。

误区监控面板显示平均延迟1.5秒,看起来还挺健康的嘛,不用管了。

正解平均值会被少数极快请求拉低,掩盖长尾风险。LLM服务的延迟分布往往是长尾的——P99可能是3秒甚至5秒。餐厅说“平均上菜5分钟”,但高峰期真的有人等了20分钟。必须用P50、P95、P99等多百分位指标监控延迟分布。

为何常见:平均数是人类最容易理解和计算的统计量,但它对异常值极不敏感,这在快慢差异巨大的LLM服务中特别危险。

误区请求排队越来越长,肯定是服务能力不够,马上加两台GPU服务器!

正解队列深度大可能是到达速率过高,也可能是处理速率骤降(显存碎片、引擎死锁、上游超时重试)。先用Little定律做定量分析:如果λ(到达速率)没变而队列涨了,说明W(服务时间)出了问题,加机器治标不治本。正确的做法是按监控数据区分“流量洪峰”与“服务劣化”。

为何常见:把症状当病因,看到队伍长就认定是地方不够大,却没有用排队论的工具去拆解到达率和服务率这两个独立变量。

误区响应成功的请求才需要监控,报错的直接重试就好,不用管它。

正解超时、报错和重试的请求恰恰是最需要监控的样本。Langfuse和Phoenix都能记录错误Trace,失败请求的TTFT和TPS往往能暴露系统真正的缺陷——比如某个Prompt触发超长生成导致KV Cache溢出。只统计成功路径就像只记录没翻车的司机,完全忽略了事故高发路段。

为何常见:人倾向于关注“成功路径”,而运维实践中真正决定用户体验的,恰恰是那1%的失败和超时样本。

误区TTFT都2秒了,肯定是模型太大太慢,赶紧换个更小的模型!

正解TTFT包含网络传输、队列等待、显存分配、Prefill计算等多个环节。用Trace工具拆开看,你可能会发现排队时间占了1.5秒,模型真正的Prefill只花了0.2秒。换小模型完全没解决排队问题。这就好比面馆出餐慢,问题在传菜通道堵塞,你却把灶台换了个更小的。

为何常见:TTFT是一个笼统的数字,初学者天然想把它归因于最显眼的因素(模型),而忽略了它其实是多个环节时间的叠加。

面试题

Q1. TTFT描述的是LLM请求的哪个阶段?

单选题 · mid

  • A.请求发出到首个Token返回的时间← 正确答案
  • B.整个请求从发起到完成的时间
  • C.模型权重加载到显存的时间
  • D.Token生成速度的倒数

答案:A。TTFT(Time To First Token)指从请求发出到收到第一个Token的时间差,它包含网络、排队、Prefill等环节。B描述的是端到端延迟,C是模型加载时间,D是生成阶段的概念。就像面馆里“第一根面条上桌”和“整碗面吃完”不是一回事。

Q2. 下列哪个指标衡量模型每秒生成Token的速度?

单选题 · easy

  • A.首Token等待时间(TTFT)
  • B.Token每秒生成数(TPS)← 正确答案
  • C.请求队列的排队长度
  • D.同时处理的请求数量

答案:B。TPS(Tokens Per Second)衡量生成阶段每秒吐出的Token数。TTFT衡量首Token等待时间,队列长度描述排队情况,并发数指同时处理的请求量。四者分别对应面馆的“第一口速度”“上菜速度”“等位人数”和“灶台数量”。

Q3. 下列哪些因素会影响TTFT?

多选题 · mid

  • A.网络传输时延过大← 正确答案
  • B.请求队列等待过长← 正确答案
  • C.Prefill阶段计算耗时← 正确答案
  • D.生成阶段采样速度

答案:ABC。TTFT指请求发出到第一个Token返回,网络时延、队列等待、Prefill计算都发生在这个区间内,都会推高TTFT。D影响的是第一个Token之后的生成速度,对应TPS而非TTFT。就像“第一口面等多久”包含下单、排队、下面,但不包含“后面几口吃得快慢”。

Q4. Little定律公式 L = λW 中,W代表什么?

单选题 · mid

  • A.系统最大并发数
  • B.请求平均逗留时间← 正确答案
  • C.GPU显存容量
  • D.每秒生成Token数

答案:B。Little定律中W是请求从进入队列到处理完成的平均逗留时间(排队+服务);L是系统中的平均请求数,λ是到达速率。三者的关系就像面馆等位区:等位人数等于顾客进店速度乘以每人平均等多久。

Q5. 关于Langfuse和Phoenix的描述,正确的是?

多选题 · hard

  • A.两者都是LLM可观测性工具← 正确答案
  • B.Langfuse能记录Trace和Token用量← 正确答案
  • C.Phoenix支持OpenTelemetry生态← 正确答案
  • D.两者都能直接优化模型权重

答案:ABC。Langfuse和Phoenix都是LLM可观测性平台,可记录Trace、Span、Token用量和延迟分布,Phoenix与OpenTelemetry集成良好。D错误——它们是观测工具,只负责“看”数据,不直接修改模型参数,就像后厨的摄像头不会帮你炒菜。

Q6. 队列深度持续增大通常说明什么?

单选题 · mid

  • A.服务处理能力小于请求到达速率← 正确答案
  • B.模型推理速度变得太快
  • C.网络传输带宽严重过剩
  • D.缓存命中率持续走高

答案:A。队列深度持续增大说明请求“进多出少”,即到达速率λ超过服务速率。这时即使单请求处理不慢,用户感知的响应时间也会被排队拉长。对应面馆场景,就是顾客进店速度超过了厨师出餐速度。

Q7. LLM推理中Decode阶段慢于Prefill阶段的最主要原因是?

单选题 · hard

  • A.Decode串行无法并行← 正确答案
  • B.Decode阶段不消耗显存
  • C.Prefill阶段动态批处理
  • D.Decode阶段KV Cache被复用

答案:A。Decode阶段每个Token依赖前一个Token的生成结果,本质是串行的,无法像Prefill那样一次性并行处理整个输入,因此速度更慢。B错误,Decode同样消耗显存;C是框架无关说法;D中的KV Cache复用反而有助于加速,不是变慢原因。

Q8. 下列哪些手段可以提升LLM应用的吞吐量?

多选题 · mid

  • A.启用动态批处理← 正确答案
  • B.增加请求缓存复用← 正确答案
  • C.关闭所有并发限制
  • D.前缀KV Cache复用← 正确答案

答案:ABD。动态批处理摊薄计算开销、请求缓存命中后几乎零成本返回、前缀KV Cache复用省去重复Prefill,都能提升单位时间产出。C“关闭所有并发限制”会导致过载雪崩、吞吐骤降,正确做法是设置合理的并发上限。

Q9. 一次LLM流式请求中,从第一个Token到最后一个Token的耗时属于哪个指标?

单选题 · easy

  • A.首Token等待时长
  • B.生成Token总耗时← 正确答案
  • C.请求排队的时间
  • D.网络传输的时延

答案:B。生成耗时指第一个Token到达后到最后一个Token到达之间的时间,它是计算TPS的分母。TTFT只覆盖第一个Token之前的等待;排队时间和网络时延都是TTFT的组成部分而非独立指标。

Q10. 监控发现P99延迟远超平均值,最合理的解释是?

单选题 · mid

  • A.系统存在长尾延迟且少数请求偏慢← 正确答案
  • B.所有请求延迟均匀分布
  • C.平均值的计算方式有误
  • D.队列中完全没有请求等待

答案:A。P99指99%的请求延迟都小于该值。P99远超均值说明存在长尾延迟——少数请求因未命中缓存、排队过长或触发重试而明显偏慢,拉高了尾延迟。只看平均值会严重低估这种风险,就像只报“平均上菜5分钟”却不说高峰期有人等了20分钟。