What Makes an Inference Engine Actually Useful? 推理引擎怎样才算真正有用?

AI Infra Track Technology

AI Infra Learning Notes · 04 / 06
Inside SGLang—from RadixAttention and scheduling to the workloads, trade-offs, and customer outcomes behind every optimization.

This is Part 04 of my notes on learning AI infrastructure from zero. Earlier parts explained how a model computes and why serving gets hard. Here I use a Qwen-based coding agent to ask a more practical question: when does an inference optimization actually help a customer? The architecture diagrams are simplified, the example metrics are hypothetical, and the goal is to connect technical mechanisms to product decisions—not rank engines by an isolated benchmark.

00 Three complaints, three different engineering questions

Imagine a small startup building an AI coding agent on Qwen. Its product is working, but the team hears three complaints in the same week.

Developer A
“I open the same repository again and still wait several seconds for the first token.”
An interactive-response problem
Developer B
“It feels fine off-peak, but becomes unpredictable when everyone logs in.”
A reliability / tail-latency problem
Founder
“Our GPU bill keeps growing. Can we support more users without doubling it?”
An economics and capacity problem

The temptation is to answer all three with one technical fix: more GPUs, larger batches, a faster engine. But those symptoms may come from different bottlenecks. This is where an inference engine becomes more than an engineering tool: its design choices become product choices.

The question is not “Which optimization is impressive?” but “Which bottleneck is limiting customer value?”

We'll use SGLang as a concrete system, compare it carefully with vLLM, and return to the coding agent to decide which knobs are actually worth turning.

01 Inside an inference engine: who does what?

Modules 01–03 explained prefill, decode, GPU bottlenecks and general serving. Here is how those pieces map to SGLang's serving runtime. The router is optional; a single-instance deployment can talk directly to the server.

FIG 01 · A SGLang request, simplified
01 / optionalRouterSelect serving instance
02API + TokenizerManagerPrepare token IDs
03SchedulerBuild batches / admit work
04ModelRunner + GPUExecute forward passes
05Detokenizer / streamReturn generated text
Scheduler ↔ RadixCache + KV allocator  ·  Locate reusable state, reserve or release GPU memory
Component relationships, not strict process boundaries. Source: SGLang runtime and Scheduler implementation. [1, 2]

The critical distinction is that the Scheduler decides what runs; the KV-cache subsystem tracks what can be reused and where it lives; and the ModelRunner / attention backend executes the remaining GPU work. An optional cluster router decides which instance receives the request, not the token-level execution order inside that instance.

For a coding agent, this separation determines whether a repeat visit can reuse repository context, whether a long prefill delays someone else's output, and whether memory pressure causes waiting or recovery.

02 RadixAttention: reuse is a memory-management problem

Imagine two requests that begin with the same 8,000-token repository context, then diverge: “fix authentication” and “add tests.” SGLang's radix tree indexes that shared prefix and references the corresponding KV slots. It is not the place where the full K/V tensors themselves live.

FIG 02 · One shared prefix, two branches
Stable system + repository prefix 8,000 identical tokens · shared KV
Fix authentication Request A · new suffix
Write tests Request B · new suffix
Radix tree = token-prefix index + KV slot references
Tree metadataToken segments → slot indices
⇄
GPU KV poolActual K/V tensors at those slots
Illustrative token counts and branches. Identical text in different positions is not enough: the token prefix, model state and cache conditions must match. [2, 3]

Under the right conditions, a second request can skip recomputing that shared portion of prefill. But 8,000 reused token positions do not imply an 8,000-token-equivalent reduction in latency or GPU cost. Queueing, decode, attention kernels, cache residency, and transfer overhead still matter.

Why reference counts and eviction matter

When active requests reference a shared prefix, those KV slots must not be reclaimed as ordinary idle cache. When requests release their references, eligible cache leaves can be evicted under memory pressure (often using LRU). SGLang separates prefix metadata, request-to-token mappings, and GPU KV storage so metadata can be reorganized without copying the full tensors. [2, 3]

For a coding product, the practical design rule is stable context first, changing context later—as long as this preserves instruction semantics, correct file versions, and tenant isolation. A changing timestamp or tool result at the front can break a long reusable prefix. Caching an outdated file is worse than a slower response.

03 Scheduling: maximizing occupancy can hurt the user

SGLang's Scheduler coordinates waiting requests, prefill batches, running decode batches and KV-memory allocation. Its policies can consider prefix reuse; its memory-aware paths may delay or retract requests when the next execution step cannot obtain enough slots. CPU–GPU overlap can hide some scheduling work behind GPU execution, but adds synchronization complexity. [2]

FIG 03 · The decisions that sit between a request and the GPU
Waiting requests
→
Prefix match + ordering
→
KV capacity check
→
Prefill / decode batch
Not enough memory?   Keep waiting, reclaim evictable cache, or retract / recover eligible work according to the execution path.
Request retraction is a recovery mechanism, not free preemption: it can add delay and recomputation.

A batch policy that improves aggregate tokens per second can still worsen p95 time-to-first-token (TTFT) or time-between-output-tokens (ITL). That is not just a technical trade-off. For an interactive coding assistant, it can make the tool feel unreliable precisely during peak usage.

04 Disaggregated prefill and decode: where the handoff costs live

Instead of sharing one worker pool, SGLang can place prefill and decode on separate workers. This lets operators tune their capacity independently—but they now have to transfer the computed KV state before decoding can continue.

FIG 04 · The handoff has a control path and a data path

Prefill worker

Processes prompt, produces K/V tensors
Potentially optimized for long input processing

Decode worker

Reserves destinations, receives KV and generates tokens
Potentially optimized for stable output-token cadence
Bootstrap coordination · worker pairing, request metadata, destination information
KV transfer engine · move the tensors (e.g., Mooncake / NIXL)
The diagram separates responsibilities; actual readiness checks and transfer preparation may overlap with computation. [4]

One current architectural choice makes the trade-off concrete. With the early policy, decode can reserve destination KV slots before prefill finishes. With prefill_complete, allocation waits until prefill is ready. The latter can reduce time spent reserving decode memory, but may leave the prefill worker holding state longer and reduce transfer overlap; the documented option also has configuration restrictions. [4]

So the win is not “two worker types are always faster.” It is less interference and more controllable prefill/decode capacity when those benefits outweigh network and coordination cost. Short prompts, light traffic or slow inter-worker links may favor simpler unified serving.

05 SGLang vs. vLLM: compare the architecture, not a headline benchmark

Both projects support modern serving techniques, including continuous batching, prefix caching and multi-GPU execution. The more useful comparison is how they implement those ideas and how those choices behave under a specific workload.

Design questionSGLangvLLM (V1, documented design)
How is cached prefix found?Radix tree: compressed token-prefix segments referencing KV slots.Hash-based block lookup: a block hash incorporates its content and preceding prefix.
How is memory protected?Cache-node references / locks, KV allocator, eviction rules.Reference-counted KV blocks, free-block queue, block allocation / eviction.
What controls execution?Scheduler, batch construction, prefix-aware policies and memory checks.Token-budget scheduling and KV-cache manager working together.
Can prefill and decode separate?Yes; disaggregation transfer backends include Mooncake and NIXL.Yes; disaggregated prefilling is documented as experimental.
Which models / GPUs?Version- and backend-dependent; check exact model and hardware matrix.Also version- and backend-dependent; verify specific support.
Which is faster?Depends on workload, configuration, model and hardware.Depends on the same factors; no universal winner.

Radix tree versus hash blocks is a data-structure distinction, not evidence that one always has a better cache-hit rate or TTFT. Both can reuse identical prefixes. Benchmarks also depend on software versions, request distributions, cache warmup, concurrency, output length and equal hardware budgets. [5, 6, 7]

06 The workload atlas: six users, six optimization hypotheses

This is the part I find most useful from a product perspective. “Inference is slow” is not a diagnosis. It is a place to begin asking better questions.

Below are six common coding-agent workload shapes. Each suggests different measurements and mechanisms. They are hypotheses, not automatic prescriptions.

01

Repeated repository context

USER EXPERIENCE
An agent asks follow-up questions over the same codebase.
POSSIBLE BOTTLENECK
Repeated prefill or low prefix reuse
CHECK FIRST
Cache-hit prefix length, TTFT, cache eviction
CANDIDATE LEVER
RadixAttention, stable prompt ordering
TRADE-OFF · Caching consumes scarce KV capacity; edits may invalidate the prefix.
02

Different users, different prompts

USER EXPERIENCE
Many unrelated requests arrive with little shared context.
POSSIBLE BOTTLENECK
Low reuse; scheduling and model execution dominate
CHECK FIRST
Cache-hit distribution, queueing, TTFT/ITL
CANDIDATE LEVER
Load-aware scheduling, batching, better capacity allocation
TRADE-OFF · Forcing cache locality may not help.
03

Very long inputs

USER EXPERIENCE
A user supplies a 40k-token repository snapshot.
POSSIBLE BOTTLENECK
Heavy prefill and KV memory footprint
CHECK FIRST
Prefill time, peak KV usage, TTFT
CANDIDATE LEVER
Chunked prefill, prefix reuse, appropriate parallelism
TRADE-OFF · Chunk sizing and shared memory contend with decode.
04

Long generated outputs

USER EXPERIENCE
An agent produces a long refactor and explanation.
POSSIBLE BOTTLENECK
Decode steps, memory bandwidth, ongoing KV growth
CHECK FIRST
TPOT/ITL, output tokens/s, energy or cost
CANDIDATE LEVER
Decode batching, efficient attention kernels
TRADE-OFF · More throughput can raise per-user latency.
05

Peak-hour concurrency

USER EXPERIENCE
It is fast at 9 a.m. and unpredictable at 3 p.m.
POSSIBLE BOTTLENECK
Queueing, admission limits, preemption, contention
CHECK FIRST
p95/p99 latency, queue time, retractions, goodput
CANDIDATE LEVER
Scheduler policies, admission control, capacity scaling
TRADE-OFF · Aggressive admission may hurt SLO attainment.
06

Dense, evolving agent context

USER EXPERIENCE
The agent keeps tool outputs, diffs and file history across turns.
POSSIBLE BOTTLENECK
Context growth, cache churn, stale context risk
CHECK FIRST
KV occupancy, prefix validity, task success, E2E time
CANDIDATE LEVER
Context design, selective retrieval, session-aware caching
TRADE-OFF · Correctness and tenant isolation outrank a high cache-hit rate.

Notice how the same knob can move from helpful to irrelevant across scenarios: prefix caching matters a lot when context repeats, but may offer little for unrelated prompts or long decode-heavy generations. Disaggregation may help noisy high-concurrency deployments while adding unnecessary transfer latency to small ones.

07 A product experiment: throughput up, useful work down

Let's say our startup tests three configurations on the same Qwen model, hardware budget, workload mix and SLO definition. A request counts as meeting the SLO only if it completes successfully within the agreed latency limits.

All numbers in this section are invented for teaching. They are not measured SGLang or vLLM performance.

ConfigurationCompleted requests/sSLO attainmentGoodput (req/s)
Current baseline2065%13.0
Aggressive batching2450%12.0
SLO-oriented scheduling1990%17.1
FIG 05 · Useful completed requests per second
Current
13.0
More batching
12.0
SLO-oriented
17.1
Schematic bar lengths scaled to the highest goodput. Source: hypothetical example, not an external benchmark.
Goodput ≈ completed requests per second × fraction satisfying the defined SLO.

The “aggressive batching” configuration finishes more requests in total, yet fewer requests meet the user-relevant requirement. Under this defined goal, the third configuration delivers more useful completions. It is a product win even without the highest raw throughput.

How I'd test it before shipping

01 / ControlKeep model, precision, GPU count, workload mix and request arrival rates comparable.
02 / InstrumentSplit TTFT into queue, prefill, KV transfer and first-decode components; inspect p50/p95/p99.
03 / DecideTrack goodput, task success, retractions and cost per successful task, not utilization alone.

08 Translate infrastructure into a customer promise

For a product-oriented reader, the strongest explanation of an infrastructure feature is a causal chain—not a list of kernel names.

MechanismReuse KV / schedule better
System metricLess work / lower tail latency
User outcomeFaster, more reliable agent
Business valueMore useful work per dollar

Before proposing an optimization, I'd ask three questions:

01

Our workload

Do contexts repeat? Are prompts long, outputs long, or arrivals bursty?

02

Our bottleneck

Queueing, prefill, decode, memory pressure, transfer—or product correctness?

03

Our customers

Which SLO, reliability threshold, and cost per successful task actually matter?

The best inference engine is not the one with the most impressive single benchmark. It's the one that turns the customer's actual workload into reliable, affordable progress.

References & boundaries

  1. SGLang official documentation — serving, features and ecosystem.
  2. SGLang Scheduler source — scheduling and execution coordination.
  3. SGLang RadixCache source — prefix tree and cache lifecycle.
  4. SGLang PD Disaggregation documentation — transfer backends and allocation policies.
  5. vLLM Automatic Prefix Caching design — block hashing and reference counting.
  6. vLLM Disaggregated Prefilling — design goals and feature maturity.
  7. Zheng et al., SGLang: Efficient Execution of Structured Language Model Programs — original RadixAttention paper.
Scope of these notes: diagrams are explanatory, not complete process diagrams. All example token counts, workload observations and performance numbers are teaching assumptions. Exact support and behavior can change by software release, model architecture, GPU backend, configuration and cache-isolation policy. Performance claims require measured, controlled comparisons.
AI Infra 学习笔记 · 04 / 06
走进 SGLang:从 RadixAttention、Scheduling、PD Disaggregation,到不同 Workload 背后的产品价值。

这是「AI Infra Learning Notes」的 Part 04。前几篇已经讨论过 LLM 如何计算、GPU 为什么成为瓶颈,以及 Serving System 如何处理大量请求。这次,我想把问题变得更贴近真实产品:为什么同样是“响应慢”,不同的 Coding Agent Workload 却需要完全不同的基础设施优化? 文中的架构图经过简化,性能数字均为教学假设。重点不在于宣布哪个引擎更快,而是把机制与产品决策真正联系起来。

00 三种用户抱怨,可能是三种完全不同的瓶颈

假设我们正在做一家使用 Qwen 的 AI Coding Agent startup。产品已经能用,但最近团队同时收到了三种反馈。

Developer A
“我每次打开同一个代码库,再问一个问题,还是要等好几秒才开始回答。”
交互响应的问题
Developer B
“平时挺快的,一到高峰期就忽快忽慢,特别不稳定。”
可靠性与尾部延迟的问题
Founder
“GPU 账单越来越高,难道用户翻一倍,成本也必须翻一倍?”
成本与容量的问题

很容易想要用同一个办法回答这三个问题:买更大的 GPU、增加 batching,或者换一个“更快”的推理引擎。但这三种体验背后,可能是三种不同的 bottleneck。

真正的问题不是“哪项技术很厉害”,而是“什么瓶颈正在限制用户获得价值”。

这篇笔记以 SGLang 为一套真实的推理系统,比较它和 vLLM 的设计,再回到 Coding Agent 的产品场景,判断:什么值得优化,什么暂时不值得?

01 进入 Inference Engine:每个组件究竟负责什么?

我们在前几个 Module 已经理解了 prefill、decode、GPU bottleneck 和 serving 的通用原理。现在把这些知识映射到 SGLang 的实际运行结构。首先注意:Router 是可选组件,不是每一个单实例请求都必须经过它。

图 01 · 一次请求在 SGLang 中的路径(简化)
01 / 可选Router选择 Serving Instance
02API + TokenizerManager准备 Token IDs
03Scheduler组 Batch / 决定准入
04ModelRunner + GPU执行 Forward Pass
05Detokenizer / Stream返回生成结果
Scheduler ↔ RadixCache + KV Allocator  ·  查找可复用状态,分配或回收 GPU 内存
这是职责关系,不是精确进程图。参考 SGLang Runtime 与 Scheduler 源码。[1, 2]

最关键的区分是:Scheduler 决定什么时候执行;KV Cache 子系统管理哪些计算结果可以复用、存在哪里;ModelRunner / Attention Backend 才执行剩余 GPU 计算。而可选的 Router 管的是把请求交给哪个实例,不是实例内部每一步 token 的调度。

对于 Coding Agent,这个分工决定了:重复打开同一代码库能否复用上下文、长 prefill 会不会干扰别人的生成、GPU memory 不够时请求是等待还是进入恢复流程。

02 RadixAttention:复用前缀,本质也是管理 GPU 内存

想象两个请求拥有完全相同的 8,000-token repository context,随后分别要求“修复登录问题”和“补充测试”。SGLang 使用 radix tree 索引公共前缀,并保存对应的 KV slot 引用。注意:树本身不是存储完整 K/V tensors 的地方。

图 02 · 同一个 Prefix,分成两个 Branch
Stable System + Repository Prefix8,000 个相同 tokens · 共享 KV
修复 Authentication Request A · 新 suffix
编写 Tests Request B · 新 suffix
Radix Tree = Token Prefix 索引 + KV Slot 引用
Tree MetadataToken Segments → Slot Indices
⇄
GPU KV Pool保存实际的 K/V Tensors
假设性的 token 数量。即使文本相似,也需要前缀 token、模型配置与缓存条件兼容才能真正复用。[2, 3]

满足条件时,第二个请求可以跳过已复用部分的 prefill。但复用 8,000 个 token positions,不代表 TTFT 或 GPU 成本按比例下降。排队、decode、attention kernels、缓存是否仍在、网络传输等都会影响最终结果。

Reference Count 与 Eviction 为什么重要?

活跃请求正在引用的 KV slots 不能被当作空闲缓存随便释放。请求结束、引用解除后,符合条件的 cache leaf nodes 才可能在内存紧张时被 eviction(常见策略是 LRU)。SGLang 分离 prefix metadata、request-to-token mappings 与 GPU KV storage,让系统能够调整索引,而无需为拆分树节点复制完整 tensors。[2, 3]

对应到 Coding Agent,一个有用的原则是:稳定上下文尽量放在前面,动态内容放在后面。但前提是不能改变指令语义、不能使用过时的文件版本,更不能破坏用户之间的数据隔离。为了更高 cache hit rate 而让 Agent 读错代码,是得不偿失的。

03 Scheduling:GPU 更忙,不代表用户体验更好

SGLang Scheduler 协调 waiting requests、prefill batches、正在运行的 decode requests 和 KV memory allocation。它可以考虑 prefix reuse;当下一轮执行缺少 KV slots 时,也可能推迟请求或进行 retraction / recovery。CPU–GPU overlap 能把部分 CPU 调度工作藏在 GPU 执行的时间里,但也增加同步复杂度。[2]

图 03 · 请求进入 GPU 之前的几个关键决策
Waiting Requests
→
Prefix Match + 排序
→
KV 容量检查
→
Prefill / Decode Batch
内存不够怎么办?   继续等待、回收可淘汰缓存,或根据当前执行路径 retract / recover 部分请求。
Request Retraction 是恢复机制,不是免费的抢占:它可能增加等待或重复计算。

更激进的 batching 可能提高每秒生成的 tokens,却同时让 p95 TTFT 或 ITL 变差。这不是“技术指标之间的矛盾”这么简单:对交互式 Coding Agent 来说,用户会在高峰期直接感到这个工具不可靠。

04 Prefill–Decode Disaggregation:真正复杂的是交接

SGLang 可以将 Prefill 和 Decode 放在不同的 Worker 上,让两者的资源能够分别配置。但这也带来了一个新问题:Prefill 算出来的 KV state,必须安全、及时地传给 Decode Worker。

图 04 · Worker 之间有两条不同的路径

Prefill Worker

处理长输入,计算 K/V Tensors
可以针对输入计算配置资源

Decode Worker

准备接收 KV,然后逐步生成 Tokens
可以针对持续生成配置资源
Bootstrap Coordination · 对接 Worker、Request Metadata、目标 Memory 位置
KV Transfer Engine · 真正传输 Tensors,例如 Mooncake / NIXL
这里是职责图。实际 readiness checks 与传输准备有可能和模型计算重叠。[4]

一个很具体的架构选择是:使用 early allocation 时,Decode 可以在 Prefill 完成前预留 KV slots;改为 prefill_complete,就等 Prefill 准备好后再分配。后者可能减少 Decode Worker 提前占着内存等待的时间,但也可能让 Prefill Worker 更久地持有缓存,减少传输 overlap;该模式的官方文档还列出了具体的配置限制。[4]

因此,PD Disaggregation 并不等于“两类 Worker 一定更快”。它的价值在于:如果负载值得,系统可以减少 Prefill 对 Decode 的干扰,并独立调节两种资源。但网络、协调、运维成本可能抵消收益。短 prompt、低并发或较慢的 Worker 间网络,反而可能更适合 Unified Serving。

05 SGLang vs. vLLM:比较设计,而不是比较一张跑分图

这两套系统都支持成熟的 LLM serving 技术,例如 continuous batching、prefix caching 和多 GPU 执行。更有价值的问题是:它们用什么结构实现这些能力?在怎样的 workload 下,这些差异才会变得重要?

设计问题SGLangvLLM(V1 的公开设计)
如何查找缓存前缀?Radix Tree:压缩的 token-prefix 节点,引用 KV slots。Hash-based blocks:利用 block 内容和此前 prefix 形成 hash 进行查找。
如何保护内存?节点引用 / lock、KV allocator、eviction rules。KV block reference count、free-block queue、allocation / eviction。
谁来决定执行?Scheduler、batch construction、prefix-aware policies、memory checks。统一 token-budget scheduling 与 KV Cache Manager 协作。
能否 Prefill / Decode 分离?可以;传输后端包括 Mooncake 与 NIXL。可以;官方文档将 disaggregated prefilling 标为 experimental。
哪些模型 / GPU 可用?取决于版本和 backend,需要核对具体支持矩阵。同样取决于版本和 backend,不能笼统判断。
谁一定更快?没有普遍胜者,要看具体测试条件。同样没有普遍胜者。

Radix Tree 和 Hash Blocks 首先是数据结构的差别,不能直接推导出谁的 cache hit rate 或 TTFT 一定更好。两者都能复用相同的前缀。而 benchmark 还受到版本、输入输出分布、warm cache、并发、模型、GPU 和部署配置影响。[5, 6, 7]

06 Workload Atlas:六种用户场景,六种不同的优化假设

这是我觉得从 Product 角度最值得保留的一部分。“Inference 很慢”不是诊断结论,而是一个值得继续追问的现象。

下面整理了 六种常见 Coding Agent workload。每一种,都意味着不同的测量指标和工程机制。这些是有待检验的假设,而不是看到症状就能直接开出的处方。

01

重复的 Repository Context

用户看到的现象
Coding Agent 多轮读取同一个代码库。
可能的瓶颈
重复 prefill,或 prefix reuse 不足
先测量什么
命中前缀长度、TTFT、cache eviction
可能的工程手段
RadixAttention、稳定的 prompt 顺序
潜在代价 · 缓存占用 KV 空间;代码改动可能让前缀失效。
02

不同用户、不同 Prompts

用户看到的现象
大量请求几乎不共享上下文。
可能的瓶颈
缓存重用低,调度与模型执行更重要
先测量什么
cache-hit 分布、排队时间、TTFT/ITL
可能的工程手段
Load-aware scheduling、batching、容量配置
潜在代价 · 强求 cache locality 可能适得其反。
03

超长输入

用户看到的现象
用户一次传来 40k tokens 的仓库内容。
可能的瓶颈
Prefill 计算重、KV memory 占用大
先测量什么
prefill time、KV 峰值、TTFT
可能的工程手段
Chunked prefill、prefix reuse、并行配置
潜在代价 · Chunk 大小与 Decode 共享资源时会相互影响。
04

超长输出

用户看到的现象
Agent 要生成长篇重构方案和解释。
可能的瓶颈
Decode 步骤多、带宽压力、KV 不断增长
先测量什么
TPOT/ITL、output tokens/s、单位成本
可能的工程手段
Decode batching、高效 attention kernels
潜在代价 · 吞吐提高可能同时拉高单用户延迟。
05

高峰期高并发

用户看到的现象
上午很快,下午却时快时慢。
可能的瓶颈
排队、admission limit、preemption、资源竞争
先测量什么
p95/p99 latency、queue time、retractions、goodput
可能的工程手段
Scheduling、admission control、容量扩容
潜在代价 · 过度激进的准入可能损害 SLO。
06

密集且不断变化的 Agent Context

用户看到的现象
工具结果、代码 diff、历史文件不断累计。
可能的瓶颈
上下文膨胀、cache churn、过期信息风险
先测量什么
KV occupancy、prefix validity、任务成功率、端到端时间
可能的工程手段
Context 组织、选择性检索、session-aware cache
潜在代价 · 正确性与用户隔离,比 cache hit rate 更重要。

这里有一个很重要的认识:同一个 optimization,在不同 workload 下可能从“特别有用”变成“几乎没用”。 比如 Prefix Caching 对重复上下文很有价值,却未必能帮助几乎不共享 prompt 的用户,或者主要耗时在长 decode 的任务。PD Disaggregation 也可能缓解高并发下的干扰,但对小流量服务反而增加额外传输开销。

07 一个产品实验:Throughput 提高,真正有用的工作反而减少

现在假设我们的 Startup 在同一个 Qwen 模型、相同 GPU 预算、相同 Workload Mix、相同 SLO 定义下,对比三种配置。只有请求成功完成、并满足预先约定的延迟要求,才被计为 SLO 达标。

以下全部是教学假设数据,不是 SGLang 或 vLLM 的真实 Benchmark。

配置完成请求数 / 秒SLO 达标率Goodput(req/s)
当前基线2065%13.0
Aggressive Batching2450%12.0
SLO-oriented Scheduling1990%17.1
图 05 · 每秒真正满足要求的请求数
当前基线
13.0
更大 Batch
12.0
SLO 优先
17.1
条形长度按最大 Goodput 归一化。数据为教学假设,不是外部实测。
Goodput ≈ 每秒完成请求数 × 满足所定义 SLO 的比例。

Aggressive Batching 虽然让系统完成了更多请求,但真正达到用户要求的请求反而更少。在这个明确的目标下,第三种方案没有最高 Throughput,却完成了更多“有用的请求”。这才是产品意义上的优化。

如果由我来设计实验

01 / 控制变量模型、精度、GPU 数量、请求分布、到达率尽量保持一致。
02 / 找到延迟来源把 TTFT 拆成排队、Prefill、KV Transfer、首次 Decode 等部分;观察 p50/p95/p99。
03 / 用价值衡量看 Goodput、任务成功率、Retraction 频率、Cost per Successful Task,而不只看 GPU Utilization。

08 把 Engineering Mechanism 翻译成真正的 Customer Value

对于做产品的人,我认为最有说服力的讲法不是罗列底层技术名称,而是建立一条完整的因果链。

工程机制KV 复用 / 更好的调度
系统表现更少重复计算 / 更低尾延迟
用户体验更快、更稳定的 Agent
业务价值每美元完成更多有效工作

在建议团队动手优化之前,我想先问三个问题:

01

Our Workload

我们的 Context 重复吗?是长 Prompt、长 Output,还是请求突然集中涌入?

02

Our Bottleneck

问题发生在 Queue、Prefill、Decode、KV Memory、Transfer,还是 Agent 本身的正确性?

03

Our Customers

用户真正看重什么 SLO、可靠性、任务成功率与单位成本?

最好的 Inference Engine,不是某一张 Benchmark 上最快的那个,而是能让客户的真实 Workload 变成可靠、可负担的有效成果的那个。

References & Notes

  1. SGLang 官方文档:Serving、功能与生态。
  2. SGLang Scheduler 源码:调度和执行协调。
  3. SGLang RadixCache 源码:前缀树与 Cache Lifecycle。
  4. SGLang PD Disaggregation 文档:传输后端与内存分配策略。
  5. vLLM Automatic Prefix Caching 设计文档:Block Hash 与 Reference Counting。
  6. vLLM Disaggregated Prefilling:设计目标和功能成熟度。
  7. Zheng et al., SGLang: Efficient Execution of Structured Language Model Programs:RadixAttention 原始论文。
阅读边界:图解是为了理解机制,不是完整的进程部署图。文中的 Tokens、Workload 与性能数字均为教学假设。具体能力受软件版本、模型结构、GPU backend、部署配置及 Cache 隔离策略影响;所有性能判断都需要对照真实、可控的测试。
← Back