Rust in Everything

怎么读这一卷

主线位置:三条主线的总览。本页不走进代码路径,只交代版本、源码链接、「默认 / 可选」的判断方法和数字的四种来源,再把「一个请求的一生」的每一段对到讲它的页。
版本:vLLM v0.32.0、SGLang v0.5.22

先说结论:

  • 每个源码链接都指向 tag,行号从 tag 取。本地克隆和 tag 一致,工作区干净。
  • 页面说某个功能「默认」,意思是不加任何参数和环境变量、在所写的平台上就生效;「可选」要显式打开;「条件默认」会写出全部条件。依据是源码里的默认值,不是上游文档的描述。
  • 数字分四种:源码事实、估算、实测、待实测(C3-n)。估算和实测分开写,待实测的格子不填估计值。
flowchart TB
  claim["页面上的一句话"] --> kind{"说的是什么"}
  kind -->|"行为、默认值"| src["源码事实<br/>附 tag 行号"]
  kind -->|"数字"| num{"数字从哪来"}
  num -->|"公式 + 公开配置"| est["估算<br/>明确标出"]
  num -->|"跑过"| meas["实测<br/>写机器、版本、命令"]
  num -->|"要 GPU"| pend["待实测(C3-n)"]
  src --> dflt{"默认还是可选"}
  dflt -->|"不加参数就生效"| d1["默认"]
  dflt -->|"要开关"| d2["可选"]
  dflt -->|"默认开,但有回退"| d3["条件默认<br/>列出条件"]

锁定版本

项目tagcommitcommit 日期
vLLMv0.32.05df63a7203cdb9328d824a27b682e77c7b9928be2026-10-17
SGLangv0.5.22baa9befa381511cd4d56f83980951e5a45fffc6d2026-10-13
vllm-project/routerv0.1.16db02f358da401b60d4ae14eb286163763a0705cc2026-10-09
mistral.rsv0.9.5465191d0b0a7e2432d327b0de06204ab3f94d3a22026-10-19

vLLM 和 SGLang 是主角,各页都对着它们写。router 只在路由一节出现;mistral.rs 只作对照,看「Rust 跑前向」是什么样子。TGI 已于 2026-03 归档,不读源码。

读者手上的版本不同时,先对比本页的 tag,再看链接指向的代码。

源码链接怎么读

链接的形式是:

https://github.com/vllm-project/vllm/blob/v0.32.0/vllm/envs.py#L1475
https://github.com/sgl-project/sglang/blob/v0.5.22/python/sglang/srt/environ.py#L1902
  • 路径和行号都以 tag 为准,不以 main 分支为准。main 上同一行号多半已经是别的代码。
  • 代码片段只摘关键几行,删掉的部分用 # ...(Python)或 // ...(Rust)标出,片段上方给文件路径和链接。
  • 每个链接都用脚本对过 tag 上的文件:路径存在、行号不越界,并抽看了指向的行。

每页的结构

  1. > 主线位置:这一页在「一个请求的一生」上的哪一段,这一段在两个引擎里是 Python 还是 Rust。
  2. > 版本:本页对照的 tag。
  3. 先给结论,再走源码。
  4. 至少一张图:进程结构图、时序图或流程图。
  5. ## 小结。

「默认 / 可选」怎么判断

这一卷说「默认」「可选」,只看源码里的默认值。分四层看。

环境变量

vLLM 把环境变量集中在 vllm/envs.py:文件前部有一段带默认值的类型声明,后部的 environment_variables 字典里是真正读取环境变量的 lambda。以后者为准。

vllm/envs.py#L1475

    "VLLM_USE_RUST_FRONTEND": lambda: bool(
        int(os.getenv("VLLM_USE_RUST_FRONTEND", "0"))
    ),

默认是 "0",所以 Rust 前端默认关。注意它先过 int():按这行代码,VLLM_USE_RUST_FRONTEND=true 会在 int("true") 处抛 ValueError,要写 1。前部的声明 envs.py#L170 写的也是 False,两处一致。

SGLang 把环境变量集中在 python/sglang/srt/environ.py 的一个类里,每个字段是一个带类型的描述符:

python/sglang/srt/environ.py#L1902

    SGLANG_RUST_SERVER = EnvBool(False)

EnvBool 的解析接受 true、1、yes、y 及对应的假值,其他值报错(environ.py#L143)。所以 SGLang 的 Rust 服务也是默认关。

命令行参数和配置类

vLLM 的参数默认值写在 vllm/config/ 下的配置类里,vllm/engine/arg_utils.py 引用它们。比如显存比例:

vllm/config/cache.py#L102

    gpu_memory_utilization: float = Field(default=0.92, gt=0, le=1)

SGLang 的参数在 python/sglang/srt/arg_groups/fields/ 下按组声明,形如 名字: A[类型, 说明] = 默认值。比如 mem_fraction_static 的默认值是 None(schedule.py#L27),实际比例在启动时按机器算出来,07 部分再讲。

默认值是 None,启动时再决定

不少参数的默认值是 None,意思是「按其他配置推出来」。这时不能只看声明,要找推导它的代码。

  • vLLM 的异步调度 async_scheduling 默认 None。vllm/config/vllm.py#L1585 起逐条排除不兼容的情况(池化模型、部分投机解码方法、执行器不支持等),都不命中时在 #L1644 设为 True。所以单卡生成模型默认开异步调度。
  • vLLM 的执行器后端 distributed_executor_backend 默认 None,单卡(world_size == 1)时设为 "uni"(vllm/config/parallel.py#L1079),模型跑在 EngineCore 进程里,不另起 worker 进程。
  • SGLang 的字段可以带 resolvable=True(arg_utils.py#L78),表示启动时的解析步骤可以改写它。比如 disable_overlap_schedule 默认 False 且可解析(schedule.py#L187),所以重叠调度默认开,但某些配置下会被关掉。

默认开,运行时回退

最容易写错的一层。SGLang 的前缀树核心默认选 Rust:

python/sglang/srt/environ.py#L688

    SGLANG_UNIFIED_RADIX_TREE_CORE_BACKEND = EnvStr("rust")

但创建时会检查一串条件,命中任何一条就回退到 Python 实现:

python/sglang/srt/mem_cache/unified_cache/tree_core_registry.py#L44

def _rust_fallback_reason(params: CacheInitParams) -> Optional[str]:
    if params.enable_session_radix_cache:
        return "session-aware caching requires the Python TreeCore"
    # ...
    if sys.platform != "linux":
        return "the Rust TreeCore supports Linux only"
    # ...

所以这一卷写它是「条件默认」:Linux 上、PyTorch 版本在支持范围内、设备是 CPU / CUDA、没有开会话缓存等条件都满足时才是 Rust;在 macOS 上永远是 Python。全部条件在 06 部分逐条列出。

判断规则

写法含义例子
默认不加参数、不设环境变量,在所写的平台上生效vLLM 单卡用 uni 执行器;SGLang 重叠调度
可选要显式打开VLLM_USE_RUST_FRONTEND=1、SGLANG_RUST_SERVER=1
条件默认默认值指向它,但运行时检查不过就回退;页面列出全部条件SGLang 的 Rust 前缀树核心

上游文档、README 和博客里的「默认」只当线索。和 tag 上的代码不一致时,以代码为准,并在页面上写出差别。

四种数字

  • 源码事实:默认值、通道类型、进程数。附 tag 上的行号。
  • 估算:按公式和模型公开配置算出来的数,比如 为什么服务大模型难 里 Llama-3.1-8B 的 KV cache 每 token 128 KiB。页面写明「估算」、写出公式和输入,算它的脚本只用 Python 标准库。估算回答「量级是多少、瓶颈在哪」,不回答「实际跑多快」。
  • 实测:写明机器、版本、命令和原始输出。本卷在 CPU 上能做的实测只涉及前端(对假引擎)、路由器和文本栈的微基准、前缀树核心的单项操作和机制模拟,不涉及模型前向。
  • 待实测(C3-n):要 NVIDIA GPU 才能得到的数。本机没有 GPU,这些实验集中登记在 GPU 待测清单里,租到机器后一次跑完再回填。页面上写「待实测(C3-n)」,不写估计值、不引用别人的跑分。
编号内容
C3-1显存预算:两个引擎上显存比例取几档时的 KV 块数、最大并发
C3-2吞吐与延迟曲线:并发 1–256,TTFT、TPOT、总吞吐
C3-3前缀复用:命中率和 TTFT
C3-4连续批处理与分块预填充:长 prompt 混进短请求时短请求的 TPOT
C3-5投机解码与量化:开关前后的吞吐与输出一致性
C3-6路由层:缓存感知路由在多副本前的效果
C3-7(多卡时)张量并行、预填充与解码分离

默认按单张 24 GB 的卡、一个 8B 模型设计这些实验。

主线落在哪一页

一个请求的一生:

段vLLM 默认SGLang 默认换成 Rust 的开关讲它的页
HTTP 进来Python(FastAPI)Python(FastAPI)VLLM_USE_RUST_FRONTEND=1 / SGLANG_RUST_SERVER=101 vLLM、01 SGLang、两种 Rust 前端
模板与分词Python 调 HF tokenizersPython 调 HF tokenizers同上同上
调度PythonPython无03 调度
KV 块 / 前缀命中PythonPython 编排 + Rust 树核心(条件默认)SGLang 的树核心默认就是 RustRadixAttention、树核心
前向、采样Python 调 CUDA kernelPython 调 CUDA kernel无04、05
反分词、流式返回PythonPython(独立进程)同第一行01 vLLM、01 SGLang

HF tokenizers 本身是 Rust 写的库,经 PyO3 被 Python 调用。这一卷说某段「是 Python」,指的是两个项目自己的代码;第三方库的内部实现另算。

一张 24 GB 的卡上放一个 8B 模型:公式在为什么服务大模型难,块怎么分在 02,参数和预算在 07,数字等 C3-1。

在本站中:08。

阅读路线

  • 只想知道请求怎么走:01 两页,再看 06 的两种前端。
  • 要调显存和并发:为什么服务大模型难 → 02 → 03 → 07。
  • 关心 Rust 能接手哪一段:本页的表 → 01 → 06。

小结

  • 四个 tag:vLLM v0.32.0、SGLang v0.5.22、router v0.1.16、mistral.rs v0.9.5;链接和行号都从 tag 取。
  • 「默认」以源码默认值为准:vLLM 看 envs.py 的 lambda 和 vllm/config/ 的字段,SGLang 看 environ.py 和 arg_groups/fields/。默认值是 None 的要找推导代码;默认开但会回退的写成「条件默认」并列出条件。
  • VLLM_USE_RUST_FRONTEND 要写 1,写 true 会在 int() 处报错;SGLANG_RUST_SERVER 接受 1 或 true。
  • 数字分源码事实、估算、实测、待实测四种;要 GPU 的写「待实测(C3-n)」,不填估计值。

💬 关联讨论

发起讨论
加载中...