Prhub

#32016 [Fix] Evict only the KV shortfall in evict_from_tree_cache

原始 PR 作者 hnyls2002 合并时间 2026-07-23 03:41 文件变更 2 提交数 1 评论 4 代码增减 +6 / -3

执行摘要

修复 Standard allocator 过度驱逐问题

Standard allocator 分支在 evict_from_tree_cache 中驱逐了完整的 num_tokens 而非仅驱逐短缺量 num_tokens - available_size,而 SWA 分支已经正确计算了短缺量。每次内存压力事件会额外破坏最多 available_size 个缓存前缀,在 MambaRadixCache 上损失更大(不可增量恢复)。见 PR 描述。

值得快速合并。建议后续补充针对 evict_from_tree_cache Standard allocator 分支的单元测试,验证驱逐量正确性。

讨论亮点

无 review 讨论。

实现拆解

  1. python/sglang/srt/mem_cache/common.py - evict_from_tree_cache 函数:在 else 分支(Standard allocator)中,将 tree_cache.evict(EvictParams(num_tokens=num_tokens)) 改为 tree_cache.evict(EvictParams(num_tokens=num_tokens - available_size))。先读取 available_size,若不足 num_tokens,则只驱逐短缺量。
  2. python/sglang/srt/managers/schedule_batch.py - check_decode_mem 方法:添加了 docstring 说明仅驱逐 shortfall,无逻辑变更。
文件 模块 状态 重要度
python/sglang/srt/mem_cache/common.py 缓存层 modified 6.09
python/sglang/srt/managers/schedule_batch.py 调度器 modified 3.92

关键符号

evict_from_tree_cache check_decode_mem

关键源码片段

python/sglang/srt/mem_cache/common.py core-logic

核心 bugfix 位置:修正 `evict_from_tree_cache` Standard allocator 分支的驱逐量计算。

# python/sglang/srt/mem_cache/common.py
def evict_from_tree_cache(tree_cache: BasePrefixCache | None, num_tokens: int):
    if tree_cache is None:
        return
    if tree_cache.is_chunk_cache():
        return
​
    allocator = tree_cache.token_to_kv_pool_allocator
​
    if isinstance(allocator, SWATokenToKVPoolAllocator):
        # Hybrid allocator: evict only the shortfall for each pool
        full_available_size = allocator.full_available_size()
        swa_available_size = allocator.swa_available_size()
        if full_available_size < num_tokens or swa_available_size < num_tokens:
            full_num_tokens = max(0, num_tokens - full_available_size)
            swa_num_tokens = max(0, num_tokens - swa_available_size)
            tree_cache.evict(
                EvictParams(num_tokens=full_num_tokens, swa_num_tokens=swa_num_tokens)
            )
    else:
        # Standard allocator: evict only the shortfall (mirrors the SWA arm)
        available_size = allocator.available_size()
        if available_size < num_tokens:
            # 修正前:驱逐完整 num_tokens 导致过度驱逐
            tree_cache.evict(EvictParams(num_tokens=num_tokens - available_size))

评论区精华

没有提炼出高价值讨论线程

当前评论区没有形成足够清晰的争议点或结论,后续有更多讨论时会体现在这里。

风险与影响

风险极低:核心变更仅 1 行逻辑修正,将驱逐量从 num_tokens 改为 num_tokens - available_size,与 SWA 分支保持一致。未引入新代码路径或配置变更。但测试覆盖不足:未包含专门针对 Standard allocator 驱逐量的回归测试。

影响范围限于 Standard allocator 路径下的内存驱逐行为。减少不必要的缓存前缀驱逐,提高 KV cache 命中率和 decode 性能,尤其对 MambaRadixCache 和长序列场景有正面影响。不影响 SWA allocator、chunk cache 或无 tree cache 场景。

缺少测试覆盖

关联 Issue

未识别关联 Issue

当前没有检测到明确关联的 Issue 链接,后续同步到相关引用后会出现在这里。

完整报告

参与讨论