预计阅读 9 分钟

SGLang vs vLLM:横向对比与选型决策

谁该读这一篇? 已经熟悉一边、想搞清另一边、或者站在选型决策点上的工程师 / 架构师。 前置阅读: 01-what-is-sglang.md。最好也对 vLLM 有印象(vllm-learning/01-overview/01-what-is-vllm.md)。 耗时: 30 分钟 学完能: 1. 一张表说出两者在前缀缓存、调度、结构化输出、前端、部署成熟度上的差异; 2. 看到一个业务场景能立刻判断"这个用 SGLang 还是 vLLM 更合适"; 3. 解释为什么"vLLM 通用、SGLang 复杂程序更强"是相对成立而非教条; 4. 知道两者在哪些维度其实是收敛的(很多优化技术互相借鉴); 5. 给团队写选型 RFC 时有一份可以直接抄的决策表。


1. 一句话定位

定位
vLLM 通用、稳健、生态最全、OpenAI 兼容 API 的高吞吐推理后端。
SGLang 把"前缀复用 + 结构化程序"做到极致的引擎,复杂 LLM 程序场景碾压。

两者都开源、都用 Python + C++ + CUDA,目标都是把 GPU 喂饱。它们越来越像,但核心叙事不同。


2. 全维度对比表

维度 vLLM v1 SGLang 简短判断
前缀缓存 Block 级 hash(默认 16 token) Token 级 radix tree SGLang 粒度更细,多分支天然支持
调度策略 FCFS + 优先级(v1 默认) Cache-aware policy 高复用场景 SGLang 更优
Chunked Prefill 默认开(v1) 默认开 打平
Continuous Batching 招牌 也用 打平
结构化输出 xgrammar / outlines / llguidance 多后端可选 压缩 FSM 复杂 schema SGLang 更快
前端 DSL @functiongenselectfork SGLang 独占
OpenAI 兼容 API 完整 完整(也是默认入口) 打平
多模态 Llava / Qwen-VL / 视频 / 音频 Llava / Qwen-VL / 视频 都还在快速演进
量化 FP8 / INT4 / AWQ / GPTQ / Marlin 同 + DeepSeek FP8 优化 打平,SGLang 在 DeepSeek 系更专
投机解码 n-gram / EAGLE / Medusa / MTP EAGLE / EAGLE-3 / 多种 draft 打平
TP / PP / EP 全支持 全支持 打平
P/D 分离 成熟(disaggregated v1) 在推进中 vLLM 当前更成熟
多副本路由 多种第三方方案 sgl-router(Rust 自带) SGLang 自带 router 是优势
CUDA Graph 默认开(v1) 默认开 打平
生态 / 文档 极其完整(贡献者最多) 快速追赶中 vLLM 当前明显领先
K8s 部署 Production Stack / llm-d / AIBrix 自己 + LWS / KServe vLLM 当前更成熟
典型论文/Blog 数量 中(学术热度高) vLLM 更易找参考
核心团队 / 治理 UC Berkeley + Anyscale 等基金会 LMSYS Org 都健康

3. 架构差异:进程模型

vLLM v1:
HTTP server ─▶ AsyncLLM ─▶ EngineCore (调度 + ModelRunner) ─▶ GPU
            │             │
            └── Tokenizer 在 HTTP 进程内
                          ├── ZMQ ─▶ MMInputCacheServer(如有)
                          └── ZMQ ─▶ EngineCore 进程

SGLang:
HTTP server ─▶ TokenizerManager (asyncio) ─▶ ZMQ ─▶ Scheduler (+ Worker) ─▶ GPU
                        ▲                                   │
                        │                                   ▼
                        └─── ZMQ ◀──────────── DetokenizerManager

差异:

  • vLLM 把 tokenize 放 HTTP 进程,SGLang 把它独立成 TM 进程。两者都有理由(vLLM 减少进程数、SGLang 强调隔离)。
  • vLLM 没有独立 Detokenizer 进程,detokenize 在 EngineCore 出口做、流式回给客户端。SGLang 独立 Detokenizer 让长 batch detokenize 不阻塞 forward。

工业上影响:

  • 高 QPS / 短请求场景,vLLM 进程少更省 RPC 开销。
  • 长 batch / 高吞吐场景,SGLang 分进程的"流水化"更稳。
  • 都不是问题决定项。

4. 算法层:RadixAttention vs PagedAttention

详细已在 02-core-concepts/01-radix-attention.md §5 展开,这里只给一个直观对照:

PagedAttention(vLLM):
  - 把 KV 切成 16 token 一块的物理 block
  - 每个请求一张 block table(逻辑→物理)
  - 前缀缓存:每 block 算 hash,存 dict
  - 命中粒度:整块(16 token)

RadixAttention(SGLang):
  - 把 KV 切成 1 token 一槽(page_size=1 默认)
  - 全局共享一棵 radix tree
  - 前缀缓存:tree 边上保存 token 序列,下钻匹配
  - 命中粒度:任意 token

直觉

  • 命中率高、且命中长度不齐 16 倍数时,SGLang 收益更明显。
  • 命中率低时打平。
  • vLLM 的实现复杂度低、可调参数少(block_size 几乎不用动),上手快。
  • SGLang 的实现复杂度高、tree 结构对长尾分布更友好。

5. 调度层:Cache-aware vs FCFS+Priority

vLLM v1 默认 FCFS,但加了 priority 字段(每个请求可以带优先级)。 SGLang 默认 cache-aware(按 prefix 命中长度排序,加权调度),见 02-core-concepts/03-cache-aware-scheduling.md

效果差别:

场景 vLLM FCFS SGLang cache-aware
同 system prompt 100 用户复用 命中靠运气(block hash 表查到才行) 调度时显式优先命中长的,TTFT 显著低
突发新用户 + 老用户混 老用户因 FCFS 排在后面 老用户因为命中长被插队优先
完全独立请求 公平 退化为近似 FCFS

业务上的副作用:cache-aware 会让"新用户 / 低命中用户"等更久。需要在 SLO 上做平衡(SGLang 提供权重参数)。


6. 结构化输出:压缩 FSM vs xgrammar

vLLM v1 支持 xgrammar / outlines / llguidance 三种后端,按 schema 复杂度选最快的。 SGLang 用自家的压缩 FSM,外加可选 xgrammar fallback。

性能差距并不大(两者都很快),但取舍不同:

  • vLLM 用社区生态,xgrammar 在简单 JSON 上接近原生速度。
  • SGLang 的压缩 FSM 在复杂深嵌 schema 上略快(jump-ahead 在长字符串更值钱)。

如果你的业务严格输出场景占比高(> 30%),两者都可,选择更多看团队熟悉度。


7. 前端:vLLM 没有 SGLang 有

这是唯一硬性差异。vLLM 只接 OpenAI 兼容 API,所有"agent / 多分支 / 程序化生成"都靠客户端循环。

# vLLM 的"两轮请求":
ans = client.chat.completions.create(model="...", messages=[
    {"role": "system", "content": SYS},
    {"role": "user", "content": "问题1"}
])
ans2 = client.chat.completions.create(model="...", messages=[
    {"role": "system", "content": SYS},        # ← 重复发送,靠后端 hash 命中
    {"role": "user", "content": "问题2"}
])
# SGLang DSL 的"两轮请求":
@sgl.function
def two_questions(s):
    s += SYS                              # ← 显式:常量
    s += "问题1: "
    s += sgl.gen("ans1", max_tokens=128)
    s += "问题2: "
    s += sgl.gen("ans2", max_tokens=128)

差别:

  • vLLM 两次请求之间,后端只能盲猜复用,命中率受请求间隔、调度顺序影响。
  • SGLang DSL 让运行时显式知道两个 gen 共享同一棵 prefix tree 节点,命中 100% 确定性。

agent 多分支场景下,SGLang 的 s.fork(N) 是 vLLM 做不到的:vLLM 必须发 N 个请求、每个请求重复发完整 prompt。


8. 选型决策表

回答下面几个问题,加分项越多越倾向 SGLang:

问题 YES 倾向
业务里有大量"同 system prompt 多请求"? SGLang
Agent / 多分支推理 / ReAct 框架是核心? SGLang
严格 JSON / 结构化输出占比 > 30%? 都行,看团队
团队愿意接受 DSL 的学习曲线? SGLang
用 DeepSeek / Llama 系大模型且要榨干性能? SGLang(DeepSeek 优化更深)
全是单轮独立请求、无前缀复用? vLLM 打平甚至略优
已经用 vLLM 跑得稳,迁移成本高? vLLM
团队需要文档最全、Stack Overflow 答案最多? vLLM
部署 K8s、要现成的 Production Stack? vLLM(当前更成熟)
需要 P/D 分离 / NIXL / RDMA 等前沿分布式特性? vLLM(当前更成熟)

经验法则

  • POC / 选型阶段 → 两个都跑一遍 benchmark(用 07-hands-on/02-benchmark-throughput.md 的方法),别信 PPT 数字。
  • 生产上线 → 优先选团队熟悉的;性能差距 < 30% 时运维成熟度比性能重要
  • 复杂 agent 业务 → 直接 SGLang,性能差距能到 3-5×。

9. 现实工程师常踩的"教条陷阱"

教条 现实
"SGLang 比 vLLM 快 5×" 只在特定 benchmark 配置下,单轮请求一般打平
"vLLM 是 batching 之王" SGLang 也支持 continuous batching,差异在调度策略
"SGLang DSL 太复杂没人用" OpenAI API 接口完全可用,DSL 是可选项
"PagedAttention 已经过时" vLLM 也在演进,block_size、prefix caching v2 都在优化
"选 vLLM 就稳,选 SGLang 就是赌新" SGLang 已经被 xAI、字节、月之暗面等大规模生产使用

10. 选型 RFC 模板(直接抄)

## 推理引擎选型:SGLang vs vLLM

### 业务画像
- 模型:[Qwen2.5-72B / DeepSeek-V3 / Llama-3.1-70B / ...]
- 主要 workload:[chat / agent / RAG / 结构化输出 / embedding]
- 流量特征:[峰值 QPS / 平均 prompt 长度 / 输出长度]
- SLO:[TTFT < X ms, TPOT < Y ms, p99 < Z ms]

### 关键决策因子
- 前缀复用率(重要):__%(来自 prod 数据 / 估算)
- 多分支推理占比:__%
- 严格结构化输出占比:__%
- 团队熟悉度:vLLM=__, SGLang=__

### 候选评估
- vLLM benchmark 数字:__ token/s, TTFT=__, TPOT=__
- SGLang benchmark 数字:__ token/s, TTFT=__, TPOT=__
- 资源 / 部署成本对照:相同 GPU 配置下

### 决策
选型:__(SGLang / vLLM)
理由:
1. ...
2. ...
3. ...

### 风险与对冲
- 风险 1:__;对冲:__
- 风险 2:__;对冲:__

11. 小结

  • vLLM:通用引擎之王,生态完整,部署成熟,纯独立请求场景最稳。
  • SGLang:在前缀复用 + 结构化程序场景做到极致,复杂 agent 业务首选。
  • 两者算法层互相借鉴,差异主要在前端 DSL默认调度策略两件事上。
  • 选型不是 ideology,是 benchmark + 团队熟悉度 + 运维成熟度的综合权衡。

12. 自检

  1. 用一句话告诉新人 vLLM 和 SGLang 的本质差别。
答案 vLLM:通用单请求高吞吐引擎,靠 PagedAttention(block hash 表)+ FCFS 调度 + OpenAI API。 SGLang:复杂程序场景的高吞吐引擎,靠 RadixAttention(token-level radix tree)+ cache-aware 调度 + 前端 DSL 暴露复用结构。 独立单轮请求两者打平;多分支 / 长共享 prefix / agent 场景 SGLang 强 2-5×。
  1. 我要做一个 RAG 服务,每个 query 都带相同的检索 context(约 4k token),后端怎么选?
答案 选 SGLang。原因:(a) 检索结果稳定时 cache 命中率高(同 doc 多 query 共享前缀);(b) cache-aware 调度让命中长的请求优先;(c) RadixAttention 的 token-level 命中比 vLLM block-level 更精确。 实测 RAG 场景下 SGLang TTFT 比 vLLM 低 30-50%。 注意要保证检索 context 稳定(同问题返回同 doc 顺序,否则 cache miss)。
  1. 我要做一个简单的翻译 API(独立单轮),后端怎么选?为什么差距不大?
答案 两者都行,倾向选团队熟悉的。差距不大的原因:(a) 独立单轮无前缀共享 → cache_hit_rate 接近 0,RadixAttention 优势消失;(b) 无多分支 → cascade 优势消失;(c) 短输出 → 投机解码、cache-aware 调度收益都小。 差距体现在 CUDA Graph、attention kernel 这些底层优化上,两边都很卷,剩 ±5%。
  1. 团队上一周才学会 vLLM,业务是 chat agent 但 deadline 紧,你怎么建议?
答案 先上 vLLM 抢时间,agent 业务用客户端循环 + OpenAI API 兼容写法。 原因:(a) 团队学习曲线大于性能差距;(b) vLLM 文档生态更全,遇坑能快速搜到答案;(c) DSL 不是性能的唯一来源,agent 后续也能在 SGLang 上跑 OpenAI 协议(损失 fork 收益但 cache 仍部分命中)。 规划 1-2 个迭代后评估:如果 SGLang 收益 > 30%(看真实业务 benchmark),再做迁移。
  1. SGLang 的 s.fork(N) 和 vLLM 客户端循环发 N 次请求,性能差距来源是什么?
答案 两个独立的差距: (a) **Prefill 算力**:客户端 N 次独立请求 = N 次完整 prefill;fork 共享父节点 KV,所有分支只算 1 次共享 prefix 的 prefill + N 次 tail prefill。算力节约接近 (N-1)/N。 (b) **Attention kernel 效率**:fork 出来的 N 个分支用 FlashInfer **Cascade Attention**——shared K/V 在 GPU 内存只存一份,N 个 Q 一次性吃同一段 K/V,L2 cache 命中率拉满。客户端独立请求即便后端 hash 命中(vLLM 也可能命中),K/V 内存里仍是 N 份。 两个加起来通常 3-5×。

13. 下一步

上游对比:sglang/python/sglang/srt/ vs vllm/v1/