Documentation of the locally modified KV cache offload/restore flow driven by tool-calling semantics (TOOL_START/TOOL_END), covering both shadow-copy (V1) and HiRadixCache-native (V2) implementations.
- HTTP endpoints:
/session/tool_start,/session/tool_end,/session/kv_meta(handled inpython/sglang/srt/entrypoints/http_server.py). - Scheduler integration: lazy manager selection in
python/sglang/srt/managers/scheduler.py:2682-2707.- Uses V2 (HiRadixCache) when
tree_cacheexposesoffload_for_tool&preload_for_tool. - Falls back to V1 (shadow copy) otherwise.
- Uses V2 (HiRadixCache) when
- Managers:
- V1:
ToolKVManager(python/sglang/srt/managers/tool_kv_manager.py:155-994). - V2:
ToolKVManagerV2(python/sglang/srt/managers/tool_kv_manager.py:995-1422).
- V1:
- HiRadixCache primitives:
offload_for_tool,preload_for_tool,load_back, lock helpers (python/sglang/srt/mem_cache/hiradix_cache.py:373-482, 521-578). - Radix cache locking/leaf collection:
inc_lock_ref/dec_lock_ref,_collect_leaves(python/sglang/srt/mem_cache/radix_cache.py:571-602, 751-763).
- Added tool-aware KV control plane (tool_start/tool_end) with semantic pause/resume.
- V1 (shadow copy) hardened: bigram key handling, null CPU copy checks, length validation, write-ack verification, try/finally cleanup, branch deletability checks.
- V2 added: native HiRadixCache integration (commit
b55a9ccdf), using host protection and TTL cleanup to avoid leaks. - Scheduler auto-selects V2 when hierarchical cache enabled; V1 is fallback.
- Offload (
ToolKVManagerV2.tool_start):- Find session’s last radix node (
_find_session_node). HiRadixCache.offload_for_tool(node, protect=True):- GPU→CPU write (
write_backup+writing_check). - Evict GPU value (
_evict_backuped→node.value=None). - Protect CPU buffer (
node.protect_host()).
- GPU→CPU write (
- Track session→node, timestamp, meta (state=OFFLOADED_TO_CPU, tier=CPU, epoch++).
- Find session’s last radix node (
- Restore (
ToolKVManagerV2.tool_end):- Validate epoch/meta.
HiRadixCache.preload_for_tool(node, release=True):- CPU→GPU (
load_back), wait vialoading_check. - Release host protection.
- CPU→GPU (
- Clear tracking; meta→RUNNABLE, tier=GPU.
- TTL cleanup:
cleanup_stale_sessions()releases host locks and invalidates meta after 1h (tool_kv_manager.py:1322-1359).
- Offload cached/finished sessions: build radix key, copy leaf-branch KV to CPU (
kv_cache.get_cpu_copy), prune branch from radix tree; store_kv_cache_cpu, radix tokens, lengths, epoch (tool_kv_manager.py:308-399). - Restore: reinsert CPU snapshot when tokens+metadata exist; otherwise just mark runnable and drop CPU buffers (
tool_kv_manager.py:850-929).
- V2: The radix node’s KV payload (
node.value) is written to CPU (node.host_value); GPU value set toNone; node stays in-tree, host buffer protected. - V1: CPU snapshot of the leaf branch (
_kv_cache_cpuor_k_host/_v_host/_kv_host), plus radix path tokens and extra key metadata for reinsertion.
- Host lock leak on preload failure:
preload_for_toolreturns early ifload_backreturns None, without releasinghost_ref_counteracquired during offload (hiradix_cache.py:440-482). ongoing_load_backconcurrency: set/pop without explicit locking betweenload_backandloading_check(hiradix_cache.py:303-316, 521-578).- Stale host buffers on GPU eviction:
_evict_backupedfrees GPU but leaveshost_value; if the node is later removed without host eviction, CPU memory can leak (hiradix_cache.py:365-371). - Leaf collection ignores host locks:
_collect_leavesfilters onlylock_ref==0, nothost_ref_counter, soevict_hostheaps include nodes that will be skipped later (radix_cache.py:751-763). - Session→node cache validity:
_find_session_nodeonly checkshasattr(node, "id"); stale nodes (removed/GC’d) may remain (tool_kv_manager.py:1056-1096). - TTL cleanup requires caller:
cleanup_stale_sessions()is defined but not auto-invoked; needs periodic scheduler call to release host locks if tool_end never arrives (tool_kv_manager.py:1322-1359). - Offload/evict race window: during
offload_for_tool, GPU value goes to None after backup; concurrent eviction could see transient states despitelock_refprotection (hiradix_cache.py:373-438).
- Enable hierarchical cache (
--enable-hierarchical-cache) to use V2; otherwise V1 shadow copy runs. - Orchestrator must call
tool_endwith the returned epoch; otherwise rely on TTL cleanup (V2) to release host protections. - On V2 preload failure (OOM/threshold), the session stays offloaded and host-locked; manual cleanup or TTL required.
- Epoch increments on each offload; callers must echo epoch on restore.
- V2 keeps radix sharing intact: nodes stay in-tree; only payload tiers change.
- Offload path (V2):
scheduler.py:2682-2722→tool_kv_manager.py:1120-1216→hiradix_cache.py:373-438. - Restore path (V2):
scheduler.py:2731-2766→tool_kv_manager.py:1227-1311→hiradix_cache.py:440-482. - TTL cleanup (V2):
tool_kv_manager.py:1322-1359. - Shadow copy paths (V1): offload
tool_kv_manager.py:308-399; restoretool_kv_manager.py:850-929.