前缀缓存

推理优化 KV Cache

前缀缓存(Prefix Caching / RadixAttention)

KV Cache 只在单个请求内复用历史 token 的计算结果。前缀缓存把这个思路扩展到跨请求:如果多个请求共享相同的前缀(比如同一个 system prompt),就只计算一次,KV Cache 共享给所有请求。

SGLang 实现前缀缓存的机制叫 RadixAttention——把 KV Cache 的 page 组织成 radix tree,按 token 序列的前缀自动归并和复用,不需要手动标记共享前缀。

收益和前缀长度正相关

这是实验里最重要的发现:前缀缓存的价值取决于"省掉的 prefill 有多贵"。

前缀长度 SGLang 缓存加速比(vs vLLM 无缓存) 说明
~500 tokens ~1x prefill 太快(~20ms),固定开销淹没收益
8K tokens 13.4x 0.475s → 0.036s
32K tokens 35.3x 1.841s → 0.052s

反直觉的地方:缓存命中后的 TTFT(0.03-0.05s)和前缀长度几乎无关——因为命中后只需要处理新增的几十个 token,不管前缀有多长。

在 Agent 场景下的复合收益

Agent 场景里前缀缓存有双重收益:

  1. 共享 system prompt 的 KV Cache:多个 Agent 会话共用一份,内存效率大幅提升
  2. 会话内增量 prefill:每轮只处理新增的 user message,不重新算整个历史

实验七数据(16个并发 Agent 会话,6轮工具调用):SGLang 总耗时 19.9s,vLLM 44.7s,差 2.2 倍。而且 SGLang 从 4 个会话扩到 16 个,总耗时几乎不变(20.3s → 19.9s)——共享缓存让 GPU 有充裕余量。

500 token 看不出效果的原因

TTFT 的下限不是 prefill 时间,而是整条链路的固定延迟(HTTP 往返、调度、流式 SSE 首包)。4090 处理 500 token prefill 只需要 ~20ms,这点时间完全淹没在几十毫秒的固定开销里。缓存确实在工作(SGLang 服务端日志 #cached-token: 992),只是在 TTFT 指标上量不出来。

相关来源

  • llm-inference-tutorial:第3章(KV Cache 与 PagedAttention)
  • inference-experiments-2026-04:实验二、五、七、九详细测量了不同前缀长度的缓存收益