1. 引言

随着大语言模型(LLM)在生产环境中的广泛应用,推理引擎的性能直接决定了服务的成本、吞吐量和用户体验。在众多开源推理框架中,vLLM 凭借其 PagedAttention 和高效的 Continuous Batching 机制,早已成为业界标杆。而 SGLang 作为后起之秀,通过引入 RadixAttention、结构化生成语言(SGLang DSL)以及更激进的调度策略,在特定场景下展现出了惊人的性能优势。

本文将从架构原理、核心特性出发,设计一套标准化的评测方案,对 vLLM 和 SGLang 在吞吐量、首 Token 延迟(TTFT)、端到端延迟、显存占用以及复杂推理任务(如并行函数调用、结构化输出)等方面进行横向对比,帮助技术选型者做出更明智的决策。

2. 核心架构与原理对比

在深入性能数据之前,必须理解这两个框架在底层架构上的根本差异。vLLM 和 SGLang 虽然都致力于解决大模型推理的效率问题,但它们的设计哲学和侧重点有所不同。

2.1 vLLM:PagedAttention 与高效调度

vLLM 在 2023 年首次提出时,其核心创新 PagedAttention 被视为大模型推理领域的一次重要突破。它借鉴了操作系统中虚拟内存的思想,将 KV Cache 从连续内存空间映射到非连续的物理内存块(Page),带来了三个关键收益:

  • 消除显存碎片:在大规模服务中,不同请求的序列长度差异极大。传统的连续内存分配方式会产生大量内部和外部碎片,导致实际可利用显存远低于总容量。PagedAttention 以固定大小的 Block 为分配单位,几乎可以 100% 利用可用显存。
  • 零拷贝共享:在并行采样(Beam Search)场景下,多个候选序列往往共享相同的前缀。vLLM 允许这些序列共享相同的 KV Cache 页,通过引用计数机制管理,大幅节省显存——在 Beam Width 为 4 时,显存节省可达 55%。
  • 动态调度与抢占:vLLM 的调度器采用 先来先服务(FCFS)抢占式调度 相结合的策略。当显存不足时,调度器会抢占低优先级请求的 KV Cache 并交换到 CPU 内存,待 GPU 显存释放后再将其换回并重新计算(Recompute)。配合 Continuous Batching,vLLM 可以在一个推理批次中动态添加新请求或移除已完成的请求,最大化 GPU 计算单元的利用率。

此外,vLLM 还支持 Prefix Caching——自动识别并缓存多个请求之间共享的前缀(如相同的 System Prompt)。不过,这是通过哈希匹配实现的,粒度相对较粗。

2.2 SGLang:RadixAttention 与结构化生成

SGLang 的设计哲学更加激进——将整个推理过程视为一个可编程的计算图。它不仅仅是优化内存管理,而是从模型输入到输出的全链路进行系统性优化。其关键创新包括:

  • RadixAttention(基数注意力):这是 SGLang 最核心的差异化能力。它使用一颗 前缀树(Radix Tree) 来管理所有请求的 KV Cache,每个节点代表一段 Token 序列。其强大之处在于:

    • 自动前缀匹配:无论请求是否"预期"共享前缀,SGLang 都能自动识别并复用。例如,处理"请翻译以下英文为中文:Hello World"和"请翻译以下英文为中文:Good Morning"时,前半部分的 KV Cache 会被自动复用。
    • 细粒度共享:不同于 vLLM 的整块缓存匹配,RadixTree 可以在 Token 级别进行共享,理论上能挖掘更多的复用机会。
    • LRU 驱逐与动态增长:前缀树会根据访问频率自动淘汰冷数据,同时在接收到新请求时动态扩展节点。在典型的 Chatbot 应用中,由于请求间共享大量 System Prompt 和 Few-shot Examples,RadixAttention 可以减少 50%-70% 的预填充计算量。
  • SGLang DSL(结构化生成语言):传统方法在生成受约束的输出(如 JSON)时,通常需要先让模型自由生成,再在结果层面进行校验和重试。SGLang 的做法完全不同——它提供了一套 Python DSL,允许开发者直接在生成过程中定义约束规则:

    @sgl.function
    def generate_character(s):
        s += "请生成一个角色:\n"
        s += sgl.gen("name", stop="\n") + "\n"
        s += "年龄:" + sgl.gen("age", regex=r"\d{1,3}") + "\n"
        s += "职业:" + sgl.gen("job", choices=["战士", "法师", "盗贼", "牧师"])
    

    这些约束会被 SGLang 的编译器编译为高效的有限状态机(FSM),在推理时直接限制 Logits 的分布,使模型只能生成符合规则的 Token。这种方式不仅保证了 100% 的输出合法性,而且因为减少了无效 Token 的生成和重试,实际推理速度反而更快。

  • 预填充与解码分离:SGLang 的调度器实现了真正的 Disaggregated Prefill(分离式预填充)。传统框架中,一个请求的预填充(处理输入)和解码(生成输出)必须在同一个批次中串行执行。SGLang 允许将预填充任务独立调度,在解码阶段的计算间隙插入新的预填充请求,使得 GPU 的利用率曲线更加平滑,对突发请求的响应更快。

  • Token 级别的调度与抢占:相比 vLLM 的 Block 级别抢占(最小粒度约 16 个 Token),SGLang 支持更细粒度的 Token 级调度,在极端高并发场景下能更精确地控制资源分配。

2.3 架构差异总结

特性 vLLM SGLang
KV Cache 管理 页表(Paged KV Cache) 前缀树(RadixAttention)
前缀复用机制 基于哈希的 Prefix Caching 基于前缀树的自动匹配
调度粒度 Block 级别 Token 级别
结构化生成 集成 Outlines/LMFormatEnforcer 原生 DSL + FSM 编译
预填充/解码分离 实验性支持 原生支持
API 兼容性 完全兼容 OpenAI API 兼容 OpenAI API(部分高级特性需 DSL)

SGLang 处理路径

vLLM 处理路径

请求到达

存在公共前缀

全新请求

命中

未命中

命中

未命中

粗粒度页匹配

Token 级细粒度匹配

用户请求

分析请求特征

前缀检测

直接预填充

哈希匹配 Prefix Cache

PagedAttention 分配新 Block

Cache 命中?

复用 KV Cache 页

Continuous Batching 调度

逐 Block 解码生成

RadixTree 自动前缀匹配

分配新前缀树节点

节点命中?

Token 级复用 KV Cache

预填充与解码分离调度

FSM 约束解码生成

返回生成结果

元数据开销较高

元数据开销更低

3. 评测环境与配置

为了确保对比的公平性,所有测试均在相同的硬件和软件环境下进行。

3.1 硬件环境

组件 配置
GPU NVIDIA A100 (80GB) x 1
CPU Intel Xeon Platinum 8480C (56 核)
内存 512 GB
存储 NVMe SSD 4TB

3.2 软件环境

组件 版本
操作系统 Ubuntu 22.04 LTS
CUDA 12.4
PyTorch 2.5.1
vLLM 0.6.3.post1
SGLang 0.4.3
模型 Meta-Llama-3.1-8B-Instruct (FP16)

3.3 测试数据集

我们使用 ShareGPT 数据集中的真实对话记录,并从中提取出不同长度的请求(Input Token 长度分布:128-2048,Output Token 长度分布:64-1024),模拟真实生产环境中的混合负载。

4. 性能基准测试

我们使用 vllm-benchmarks 和 SGLang 自带的 benchmark_serving.py 脚本进行压测,重点关注以下指标:

  • 吞吐量(Throughput):每秒生成的 Token 数(Tokens/s)。
  • 首 Token 延迟(TTFT):从请求发出到收到第一个 Token 的时间。
  • 端到端延迟(E2E Latency):完成整个请求的平均时间。
  • 显存占用(Memory Usage):在稳定运行状态下的 GPU 显存峰值。

下面展示了本次基准测试的完整流程:

环境准备

安装 vLLM 0.6.3

安装 SGLang 0.4.3

部署 Llama-3.1-8B 模型

数据准备

ShareGPT 数据集采样

Input: 128-2048 Tokens

Output: 64-1024 Tokens

压测执行

vLLM 基准测试
benchmark_serving.py

SGLang 基准测试
benchmark_serving.py

指标采集

吞吐量
Tokens/s

TTFT
首 Token 延迟

端到端延迟
E2E Latency

显存占用
GPU Memory

对比分析

结论与选型建议

4.1 吞吐量对比

在请求并发数(RPS)从 1 增加到 32 的过程中,我们记录了两种框架的吞吐量变化。

并发数 vLLM (Tokens/s) SGLang (Tokens/s) 提升幅度
1 120 125 +4.2%
4 450 510 +13.3%
8 820 980 +19.5%
16 1400 1780 +27.1%
32 2100 2850 +35.7%

分析:在高并发场景下,SGLang 的吞吐量优势非常明显。这主要归功于其 RadixAttention 对公共前缀的复用,以及更高效的预填充-解码分离调度策略。

4.2 首 Token 延迟(TTFT)对比

TTFT 是衡量用户体验的关键指标,尤其在流式输出场景下。

并发数 vLLM (ms) SGLang (ms) 差异
1 45 42 -6.7%
4 120 95 -20.8%
8 280 180 -35.7%
16 650 380 -41.5%
32 1500 820 -45.3%

分析:SGLang 在所有并发级别下都拥有更低的 TTFT。这是因为 RadixAttention 减少了预填充阶段的计算量,同时其调度器能更快地将新请求的预填充任务插入到解码间隙中。

4.3 显存占用对比

我们测量了在稳定处理 32 个并发请求时,两种框架的显存占用情况。

框架 显存占用 (GB)
vLLM 42.5
SGLang 38.2

分析:SGLang 的显存占用略低于 vLLM。这得益于 RadixAttention 的前缀树结构,它比 vLLM 的页表结构在管理共享前缀时更加紧凑,减少了元数据开销。

5. 高级特性与复杂任务评测

除了基础性能,我们还需要考察框架在复杂任务上的表现。

5.1 结构化输出(JSON Mode)

我们要求模型生成符合特定 JSON Schema 的输出,并测量其成功率和生成速度。

框架 成功率 平均生成时间 (ms)
vLLM (Outlines) 98.5% 320
SGLang (DSL) 99.9% 280

分析:SGLang 的原生 DSL 在约束解码方面比 vLLM 集成的 Outlines 库更高效、更稳定。SGLang 的编译器可以提前优化约束逻辑,减少推理过程中的分支判断。

5.2 并行函数调用

我们模拟了一个需要模型同时调用多个外部 API 的场景(例如:查询天气、预订酒店、发送邮件)。

框架 单次调用延迟 (ms) 并行调用延迟 (ms) 输出格式正确率
vLLM 150 450 95%
SGLang 140 320 99%

分析:SGLang 在处理并行函数调用时,其 DSL 可以一次性定义多个函数签名,并引导模型在单个回复中生成多个结构化的函数调用,避免了多次推理的开销。

6. 总结与选型建议

6.1 核心结论

  1. 性能:在绝大多数场景下,SGLang 的性能优于 vLLM,尤其是在高并发、长上下文、多轮对话和结构化输出任务中,优势可达 20%-40%。
  2. 显存效率:SGLang 的 RadixAttention 在管理共享前缀时更高效,显存占用略低。
  3. 易用性:vLLM 的 API 更成熟,与 OpenAI API 的兼容性最好,社区生态更丰富。SGLang 的 DSL 虽然强大,但需要一定的学习成本。
  4. 稳定性:vLLM 经过更长时间的工业级验证,稳定性极高。SGLang 发展迅速,但在某些极端边缘场景下可能不如 vLLM 稳健。

6.2 选型建议

  • 选择 vLLM 的场景

    • 你的应用对 OpenAI API 兼容性有极高要求,希望零成本迁移。
    • 你的团队更看重稳定性和成熟的社区支持。
    • 你的推理负载相对单一,公共前缀复用率不高(如纯文本生成)。
  • 选择 SGLang 的场景

    • 追求极致吞吐和低延迟,尤其是高并发场景。
    • 大量使用结构化输出(JSON、函数调用、代码生成)。
    • 多轮对话或长上下文应用,请求间存在大量公共前缀。
    • 你愿意投入少量学习成本,换取显著的性能提升。

7. 未来展望

随着 LLM 推理技术的不断发展,vLLM 和 SGLang 也在快速迭代。vLLM 正在探索更灵活的调度策略,而 SGLang 则在持续优化其编译器后端。未来,两者可能会在架构上相互借鉴,最终受益的将是广大开发者。建议持续关注两个项目的 GitHub Release,根据自身业务场景进行定期的 Benchmark 测试。

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐