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 | 无 | @function、gen、select、fork |
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. 自检
- 用一句话告诉新人 vLLM 和 SGLang 的本质差别。
答案
vLLM:通用单请求高吞吐引擎,靠 PagedAttention(block hash 表)+ FCFS 调度 + OpenAI API。 SGLang:复杂程序场景的高吞吐引擎,靠 RadixAttention(token-level radix tree)+ cache-aware 调度 + 前端 DSL 暴露复用结构。 独立单轮请求两者打平;多分支 / 长共享 prefix / agent 场景 SGLang 强 2-5×。- 我要做一个 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)。- 我要做一个简单的翻译 API(独立单轮),后端怎么选?为什么差距不大?
答案
两者都行,倾向选团队熟悉的。差距不大的原因:(a) 独立单轮无前缀共享 → cache_hit_rate 接近 0,RadixAttention 优势消失;(b) 无多分支 → cascade 优势消失;(c) 短输出 → 投机解码、cache-aware 调度收益都小。 差距体现在 CUDA Graph、attention kernel 这些底层优化上,两边都很卷,剩 ±5%。- 团队上一周才学会 vLLM,业务是 chat agent 但 deadline 紧,你怎么建议?
答案
先上 vLLM 抢时间,agent 业务用客户端循环 + OpenAI API 兼容写法。 原因:(a) 团队学习曲线大于性能差距;(b) vLLM 文档生态更全,遇坑能快速搜到答案;(c) DSL 不是性能的唯一来源,agent 后续也能在 SGLang 上跑 OpenAI 协议(损失 fork 收益但 cache 仍部分命中)。 规划 1-2 个迭代后评估:如果 SGLang 收益 > 30%(看真实业务 benchmark),再做迁移。- 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. 下一步
04-project-structure.md— SGLang 源码地图。05-quickstart.md— 5 分钟跑通 SGLang。02-core-concepts/01-radix-attention.md— 算法层深入。07-hands-on/02-benchmark-throughput.md— 自己跑数字。- 对照阅读 →
vllm-learning/同名章节。
上游对比:
sglang/python/sglang/srt/vsvllm/v1/。