SGLang 响应为何变慢?逐段定位时间消耗

作者:袖梨 2026-09-11

用户口中的“回答慢”可能对应完全不同的延迟阶段:有时页面迟迟没有首段内容,有时开头很快,随后输出却断断续续。仅观察 GPU 利用率很难区分这些情况,需要沿着请求经过调度、prefill、decode 和转发链路的过程逐段记录,才能判断时间真正消耗在哪里。

SGLang 回答慢,时间究竟花在了哪里

场景:SGLang 推理服务上线后用户反馈"答得慢"。结论:两种"慢"是不同阶段的问题,需要分别看 prefill 前 / decode 后 / 链路后端三类观察点。产出:一份可复查的排障记录模板和一张症状-核对项对照表。 适用版本:SGLang v0.5.x(2026 年 9 月前后的稳定版;最新发布 v0.5.19,2026-09-05)。

TL;DR

  • 场景:用户报告"首段迟迟不来"和"开头快、后面断断续续"两类慢请求;GPU 利用率看不出问题。
  • 结论:两种症状分别指向不同阶段——首段慢优先看调度队列与实际输入长度(含 prefill 缓存命中),后续断流优先看 decode 阶段并发与转发链。
  • 产出:5 行核对表(症状 → 接下来核对什么)、6 张可复用配图、1 张可填写记录模板。

版本矩阵

功能状态说明
SGLang 官方 Production Metrics 页✅ 已验证https://docs.sglang.io/docs/references/production_metrics 返回 200,文档可访问
--enable-metrics 启动参数✅ 已验证官方文档明确通过该参数暴露 Prometheus 指标
SGLang scheduler 源码(python/sglang/srt/managers/scheduler.py✅ 已验证GitHub 链接 commit febb3605 有效;批次调度与执行逻辑可追踪
SGLang 流式 Quickstart 示例✅ 已验证docs.sglang.io/docs/get-started/quickstart#streamingstream=True + for chunk in response 写法可访问
SGLang 最新稳定版本✅ 已验证v0.5.19,发布日期 2026-09-05
官方流式示例能证明"浏览器已显示"❌ 已驳斥for chunk in response 只证明客户端能逐段读取,不证明后端及时转发、不证明浏览器已显示
用浏览器总耗时减服务平均值当网络耗时❌ 已驳斥跨机时钟未同步会制造假延迟;正确做法是同进程内时间间隔 + request_id 串联
"看到指标上涨就加并发"❌ 已驳斥等待请求数高可能是入口流量增加,也可能是每条请求生成更长答案

文章正文

用户发来一句话,页面过了好一会儿才开始显示;换一个问题,文字马上出现,却一小段一小段地往外挤。这两种"慢",需要查的地方并不相同。

第一种先看首段内容出现之前发生了什么,第二种要看开始生成之后为什么跟不上。沿着一条请求走一遍,比只盯着 GPU 利用率更容易找到方向。

请求到了,并不代表 GPU 已经开始算

起步慢,还是开始后断断续续?

应用把消息发送给 SGLang 后,消息还需要按模板组织、转换成 token,并进入执行调度。遇到已有任务占用资源,新请求会等待。

SGLang 的调度器源码可以用来追踪选取批次、执行批次和处理结果的过程。这里的批次,是一次安排在一起计算的一组请求;它不是"某位用户的一整段回答"。具体实现会随版本和运行模式改变,不能把一张串行流程图当作所有部署的进程拓扑。

这一步对排障的意义很直接:请求已经被服务接收,仍可能长时间待在队列里。应用只记录"请求发送"和"最终返回",会把这段等待全算进"模型推理慢"。

首 token 之前,长输入要先被处理

只问了一句,模型可能又读了一整份文档

模型要理解输入中的规则、文档和历史。处理输入的阶段通常称为 prefill。如果可复用前缀仍在缓存中,一部分重复计算可以省去;剩余输入仍需处理。

一位用户只问了一句"那第三条呢",不等于这次输入很短。应用可能把整份文档和十轮历史又发了过来。排查时应该保存模型实际接收的输入长度,而不仅是聊天框里新增的那句话。

如果前缀命中增加,但首 token 时间没改善,还要看排队和其他开销。缓存只影响部分计算,不会让已经拥堵的队列自动缩短。

第一段文字出来以后,任务还没有结束

接下来是生成新内容的 decode。常见自回归生成要依据已有上下文逐步继续;输出越长,后续计算也越多。

多个请求的生成过程可以一起被调度,因此某条请求的表现会受同一服务中其他负载影响。"我单独测试很快,上线就慢"需要检查并发请求的输入长度、输出长度和到达节奏。

如果使用结构化输出,还要考虑约束解码;如果启用了特殊推理模式或其他优化,输出处理也可能不同。先保留实际启动参数,才知道你在排查哪条路径。

服务有 token,页面未必立即有文字

先把三个观察点记在同一条请求上

官方流式示例,证明的是逐段读取

生成出的 token 需要转成文字并发送出去。客户端、业务后端和反向代理可能继续缓冲。一个流式响应里的首个事件,也可能只是角色或元信息,而不是用户看得见的内容。

因此,要区分"收到第一个事件"和"收到第一段非空内容"。当服务指标很好、页面仍然停顿时,可以在同一请求上分别记录:服务发出内容、业务后端收到内容、浏览器显示内容的时刻。

跨机器时钟没有同步,直接相减会制造假延迟。优先记录同一进程内的时间间隔,再用请求 ID 串起不同观察点。不要把浏览器总耗时减去某个服务平均值,就当成网络耗时。

用一组症状决定下一步看哪条记录

先打开指标,再追具体请求

官方指标页列出了首 token 时间、等待请求数、运行中请求数、缓存命中等指标。启动服务时可以启用 --enable-metrics。这些指标适合观察负载变化,但聚合指标不能单独还原一次请求。

下面这张表是排查顺序,不是已确认的故障结论:

你看到的现象接下来核对什么
首段迟迟不来,等待请求数持续上升请求到达速度、并发上限、正在运行的长任务
只有长文问题起步慢实际输入长度、可复用前缀和 prefill 情况
起步正常,后续文字变慢输出长度、同时运行的任务、生成阶段资源压力
服务已发出文字,页面仍没显示后端转发、代理缓冲、浏览器处理
请求偶发消失或提前结束错误、超时、取消、结束原因与客户端重试

不要看到一个指标上涨就马上改配置。比如等待请求数高,可能是入口流量增加,也可能是每条请求开始生成更长的答案。两种情况下都加并发,未必能解决问题。

留下能够重现的请求,再改一个变量

把"模型慢"写成一条能复查的记录

从慢请求中选一个已脱敏样本,固定模型、模板、输入和生成设置,记录它在低负载下的表现,再逐步恢复当时的并发条件。本文没有执行模型压测,这里给的是定位办法。

你需要的结果不是"模型慢"四个字,而是更具体的描述,例如:"长输入在首 token 之前耗时增加""队列增长后短请求也被拖慢",或者"服务已经流式返回,代理还在攒数据"。

描述能落到具体阶段,改动就能落到相应位置。下一次复测时,也知道该检查哪段等待有没有真的缩短。


错误速查卡

症状根因定位修复
首段迟迟不来,等待请求数持续上升请求被调度器积压,批次还没轮到当前请求核对到达速率、并发上限、当前在跑长任务;同一进程内测"请求入队 → 选中执行"间隔在不改变业务峰值的前提下,调并发上限或拆长任务;先固定一个变量复测
只有长文问题起步慢实际输入比用户感知的长得多,prefill 阶段耗时长记录模型实际收到的输入 token 数、命中前缀比例缩短上下文、复用前缀缓存、减少每轮重发整份文档
缓存命中增加,首 token 没改善缓存只省部分计算,没解决调度排队与其他开销同时看排队长度和 prefill 时长单独看排队、再单独看 prefill,逐项验证
起步正常,后续文字变慢decode 阶段资源被其他请求挤占,或输出特别长看运行中请求数、输出 token 数、生成阶段 GPU/带宽指标限流或拆短输出,先复测同输入短输出
服务指标很好,页面仍停顿业务后端/代理/浏览器在缓冲,token 没及时落到 UI同一请求上分别记录:服务发出首段非空内容、业务后端收到、浏览器显示检查后端是否收齐整段才转发、代理是否有 proxy_buffering、浏览器是否被节流
stream=True 示例跑通就觉得"流式没问题"官方 for chunk in response 只证明客户端能逐段读把"收到第一个事件"和"收到第一段非空内容"分开记同时校验后端转发与浏览器显示两侧
把浏览器总耗时减服务平均值当网络耗时跨机时钟未同步在同进程内比对时间戳;用 request_id 串联不同观察点改为同进程内时间间隔 + request_id 关联
看到等待请求数高就加并发原因可能是入口流量增大,也可能是每条请求输出变长看输入/输出分布、达到节奏、生成阶段指标先判断是入口侧还是生成长度侧,再决定调入口或限流
请求偶发消失或提前结束错误、超时、取消、客户端重试在同一进程内记录"结束原因"标签区分是服务侧主动结束,还是客户端侧主动断开
排查时只盯 GPU 利用率排队、后端缓冲、浏览器渲染都看不见拉同请求多观察点 + 聚合指标把"GPU 利用率"换成"首 token 之前 / decode 之后 / 链路后端"三段观察

作者:武子康的个人博客 发布日期:2026-09-11(基于 SGLang v0.5.x,2026 年 9 月) 核查依据:官方 Production Metrics 页(HTTP 200)、SGLang GitHub 源码(commit febb3605)、官方 Quickstart Streaming 文档;最新发布版本 v0.5.19(2026-09-05)。

相关文章

精彩推荐