SGLang 与 Ollama 实现差异总结
SGLang 与 Ollama 实现差异总结
1. 这份对比只看“实现”,不看“使用场景”
这里不讨论哪一个更适合本地体验、哪一个更适合线上部署,而是只回答一个问题:
同样都是“把模型包装成标准 API 服务”,SGLang 和 Ollama 在内部到底是怎么做的,它们的实现重点有什么不同。
2. 一句话结论
Ollama更像:先有模型运行器,再在外面暴露 REST API。SGLang更像:先有高性能推理运行时,再在上面挂多种协议兼容接口。
这意味着两者虽然都能提供 API,但“API 在系统里的位置”不一样。
3. API 在系统中的位置不同
3.1 Ollama
Ollama 的 API 更接近系统本体的一部分。
它的思路是:
- 接收 API 请求
- 找到或创建对应模型 runner
- 让 runner 执行推理
- 把结果流式返回
也就是说,它的重点在“模型实例管理 + API 暴露”。
如果类比 Java,它更像:
- 一个带模型生命周期管理能力的本地/服务端守护进程
- API 是它天然的主交互方式之一
3.2 SGLang
SGLang 的 API 更像是运行时外面的一层协议适配壳。
它的思路是:
- 接收 HTTP 请求
- 按协议格式解析成统一运行时请求对象
- 交给运行时组件处理
- 再把统一结果封装回 OpenAI / Ollama / Anthropic 风格响应
也就是说,它的重点在“统一运行时 + 协议适配”。
如果类比 Java,它更像:
- 一个高性能推理内核
- 外面挂了多个 controller / adapter 去兼容不同 API 风格
4. 进程模型不同
4.1 Ollama:围绕 runner 管理
Ollama 的实现核心更接近:
- 一个 server
- 一个 scheduler
- 若干已加载的 runner
请求来了之后,系统首先关心的是:
- 这个模型是不是已经加载
- 是否可以复用现有 runner
- 内存/GPU 资源够不够
- 如果不够,要不要卸载别的模型
- 这个 runner 是否应该保活一段时间
所以它更像“模型实例调度器”。
它的调度重点是:
- 模型加载与复用
- runner 生命周期
- 显存/内存占用控制
- 模型驱逐和保活
4.2 SGLang:围绕推理流水线拆分
SGLang 在运行时内部明确拆成多个核心组件:
TokenizerManagerScheduler子进程DetokenizerManager子进程
它关心的不是“有没有一个 runner 正在跑”这么简单,而是:
- 请求如何被 tokenization
- 请求如何被批处理调度
- token 如何流式返回
- 进程之间如何解耦
- 高并发下如何压榨 GPU 吞吐
所以它更像“请求级推理执行引擎”。
5. 请求链路的差别
5.1 Ollama 的大致链路
可以抽象成:
HTTP API -> Scheduler -> 获取/加载 runner -> 后端执行 -> 流式返回
这条链路的核心特点是:
- 先找到一个可执行当前模型的 runner
- 如果模型没加载,就先加载模型
- 如果资源不足,就回收或替换其他模型
- 然后由 runner 执行请求
这里“runner”是很重要的中心概念。
5.2 SGLang 的大致链路
可以抽象成:
HTTP 协议层 -> TokenizerManager -> Scheduler -> DetokenizerManager -> HTTP 协议层
这条链路的核心特点是:
- API 层不是执行中心
- 统一请求先进入运行时
- 运行时用专门的 scheduler 管批处理与执行
- 输出由 detokenizer 再转回文本
这里“scheduler + tokenizer/detokenizer pipeline”是中心概念。
6. 调度目标根本不同
6.1 Ollama 的调度目标
Ollama 更偏向解决:
- 哪些模型正在内存里
- 哪个请求绑定哪个 runner
- 是否需要加载新模型
- 是否需要淘汰旧模型
它的调度单位更接近“模型实例”。
所以你可以把它想成:
- 偏模型级资源调度
6.2 SGLang 的调度目标
SGLang 更偏向解决:
- 当前有哪些请求可以一起组成 batch
- 哪些请求可以共享 prefix cache
- 哪些 token 生成可以 overlap
- 是否可以做 speculative decoding
- 多卡/多机上如何切分执行
它的调度单位更接近“请求 / token / batch”。
所以你可以把它想成:
- 偏请求级、token 级执行调度
7. 把“一次请求”写得更细一点
上面只是抽象链路。为了避免“都差不多是 HTTP 调模型”的错觉,这里把两边的一次请求再展开成更细的步骤。
7.1 Ollama 的一次请求
以一次聊天请求为例,可以把它理解成:
- HTTP 层收到
/api/chat或类似请求 - Server 解析请求里的模型名、消息、参数
- Scheduler 判断这个模型对应的 runner 是否已经在内存/GPU 中
- 如果 runner 已存在,就直接复用
- 如果 runner 不存在,就尝试加载模型并创建 runner
- 如果资源不够,就先驱逐旧 runner 或等待资源腾出
- 请求绑定到某个 runner
- runner 调底层推理后端开始生成
- Server 把生成结果流式返回给客户端
- 请求结束后,runner 按保活策略继续驻留一段时间或被回收
这条链路最关键的判断点不是“当前 batch 怎么排”,而是:
- 当前是否已有可复用模型实例
- 当前是否还有资源加载模型
- 当前该把请求交给哪个 runner
所以 Ollama 的一大实现重心是:
- 模型实例生命周期管理
7.2 SGLang 的一次请求
以一次 OpenAI 风格 /v1/chat/completions 为例,可以把它理解成:
- HTTP 层收到请求
- 协议适配层把 OpenAI 风格参数转换成统一的运行时请求结构
- TokenizerManager 接管请求
- TokenizerManager 做 tokenizer / template / multimodal preprocess 等预处理
- 请求被转换成 token 级输入并进入运行时内部队列
- Scheduler 从多个请求里挑选可以一起执行的项组成 batch
- Scheduler 结合 cache、prefill/decode 状态、并行配置决定执行方式
- GPU 执行得到输出 token
- 输出送到 DetokenizerManager 转回文本
- 结果再回到协议层,封装成 OpenAI 风格 streaming/non-streaming 响应
这条链路最关键的判断点不是“有没有 runner”,而是:
- 当前哪些请求可以拼批
- 哪些前缀可以复用
- 哪些 token 现在该算
- 哪些请求应该继续 decode,哪些请求该先 prefill
所以 SGLang 的一大实现重心是:
- 请求级批处理和 token 级调度
8. 两边容易混淆的几个概念
很多时候会把“缓存”“模型复用”“批处理”混成一件事,但它们不是一回事。
8.1 Ollama 的“复用”主要是 runner 复用
这里的复用更接近:
- 模型已经加载过,不要重复加载
- 这个模型实例还在,后续请求继续用它
本质上这更像:
- 模型进程/实例级复用
它节省的是:
- 模型加载时间
- 再次初始化成本
- 部分显存/内存重新分配开销
8.2 SGLang 的“复用”除了模型常驻,更强调前缀复用
SGLang 当然也依赖模型已加载,但它更重要的优化点是:
- 相同或相似 prompt 前缀不重复算
- 多请求共享 KV cache
- decode 阶段持续把请求动态拼到批里
本质上这更像:
- 计算结果级复用
- token 状态级复用
它节省的是:
- 重复前缀计算
- 解码阶段的低效空转
- 高并发下批处理不充分带来的吞吐损失
8.3 Ollama 不是没有调度,SGLang 也不是没有模型管理
要避免两个误解:
Ollama不是完全没有调度
它有调度,但调度重点更偏“模型实例和资源占用”。SGLang不是完全不关心模型加载
它也有 model loader、权重加载、LoRA 管理,但这些不是它最核心的架构卖点。
更准确地说:
Ollama的主轴是“把模型实例管好”SGLang的主轴是“把请求执行流转好”
9. 用一个表把机制差异钉住
| 维度 | Ollama | SGLang |
|---|---|---|
| API 位置 | 系统本体的重要组成部分 | 运行时外侧的协议适配层 |
| 核心对象 | runner / loaded model | request / batch / token / cache |
| 主要复用对象 | 已加载模型实例 | 前缀计算结果、KV cache、批处理窗口 |
| 调度重点 | 模型加载、驱逐、保活、资源占用 | 批处理、前缀复用、decode 调度、并行执行 |
| 请求执行中心 | runner | scheduler pipeline |
| 更像什么 | 模型守护进程 + runner 管理器 | 推理运行时 + 高性能调度器 |
10. 为什么 SGLang 的结构明显更“重”
因为它试图解决的不是“把模型提供成 API”这么简单,而是:
- 怎么让同样 GPU 扛更多请求
- 怎么减少重复前缀计算
- 怎么提高并发时吞吐
- 怎么支持多种并行策略
- 怎么支持 OpenAI / Anthropic / Ollama 等多协议
- 怎么支持 LoRA、结构化输出、推测解码、分布式部署
因此它的实现自然会出现这些层:
- 协议入口层
- 参数与配置层
- tokenizer 层
- scheduler 层
- model loader / executor 层
- detokenizer 层
- observability 层
而 Ollama 在实现上相对更聚焦:
- server 层
- scheduler 层
- runner 层
- 模型加载与保活
11. 用后端工程语言重述一次
如果用传统后端工程语言描述:
8.1 Ollama 更像
- 模型管理器
- 推理守护进程
- 带 REST API 的 runner 调度器
其重点是:
- 把模型实例管起来
- 把推理请求发给合适 runner
8.2 SGLang 更像
- 推理运行时内核
- 高性能调度系统
- 带多协议兼容层的推理平台
其重点是:
- 把请求在运行时里高效流转起来
- 把 GPU 利用率、吞吐、延迟做优化
12. 最终总结
两者都能“把模型包装成标准 API 服务”,但实现本质不同:
Ollama的中心是“模型 runner 和模型生命周期管理”SGLang的中心是“请求调度流水线和高性能推理运行时”
所以:
- 在 Ollama 里,API 更接近系统本体
- 在 SGLang 里,API 更接近运行时外面的兼容适配层
这就是它们实现上的根本差别。