[mem_cache][5/N] refactor: extract host KV cache base layer into pool_host package - #27273
Conversation
There was a problem hiding this comment.
Code Review
This pull request refactors the host-side memory pool implementation by splitting memory_pool_host.py into a modular package under pool_host/ and updating all dependent imports. Feedback on these changes includes correcting the page alignment calculation in HostKVCache to prevent allocating an unnecessary extra page, and relaxing the type hint for the allocator parameter in alloc_with_pin_memory to avoid static type-checking issues.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
| self.page_num = self.size // self.page_size + 1 | ||
| self.size = self.page_num * self.page_size |
There was a problem hiding this comment.
Using self.size // self.page_size + 1 to align the host memory pool size always allocates an extra page even when self.size is already a multiple of self.page_size. It is more efficient and standard to use the round-up formula (self.size + self.page_size - 1) // self.page_size.
self.page_num = (self.size + self.page_size - 1) // self.page_size\n self.size = self.page_num * self.page_size| dtype: torch.dtype, | ||
| device: str, | ||
| pin_memory: bool, | ||
| allocator: None, |
There was a problem hiding this comment.
The type hint allocator: None is overly restrictive and will cause static type checkers to complain when a HostTensorAllocator instance is passed (which happens in memory_pool_host.py). Changing it to allocator: HostTensorAllocator | None = None makes it compatible with the signature of alloc_with_host_register and type-safe.
| allocator: None, | |
| allocator: HostTensorAllocator | None = None, |
a0a9628 to
fb7fcd7
Compare
fb7fcd7 to
d3b6125
Compare
|
/tag-and-rerun-ci |
There was a problem hiding this comment.
is this file necessary? should we combine it with the base.py?
There was a problem hiding this comment.
I think base.py is for abstract base classes, and utilities shared across modules should go in a separate file.
|
please resolve the conflicts and rerun ci |
1ded307 to
9f863fa
Compare
|
/rerun-group radix_cache/unified_radix_tree/hicache |
|
⛔ Known groups: |
|
/rerun-group radix_cache hicache |
|
Results for 🚀 🚀 🚀 🚀 🚀 |
|
/rerun-test registered/radix_cache/unified_radix_tree/test_unified_radix_cache_kl_mamba.py |
|
Results for 🚀 |

Motivation
First PR of the
pool_hostphase of the mem_cache refactor (issue #25371). Sibling of the completed allocator series (#26675, #26676).memory_pool_host.pyis a ~2960-line module holding the host-side KV cache base class, shared allocation helpers, and every concrete host pool (MHA / MLA / Mamba / DeepSeekV4 / DSA). This PR extracts only the shared base layer into a newpool_host/subpackage. All concrete pool classes stay inmemory_pool_host.pyand will be relocated one family at a time in follow-up PRs (mha,mla,mamba,deepseek_v4,nsa,group), all tracked under #25371.Modifications
Mechanical relocation. The moved implementation bodies are unchanged; only import preambles and caller import routes are rewritten.
HostKVCache(abc),synchronized,HICACHE_HOST_MEMORY_RESERVE_BYTESmemory_pool_host.pypool_host/base.pyHostTensorAllocator,get_allocator_from_storage,alloc_with_host_register,alloc_with_pin_memory,ALLOC_MEMORY_FUNCSmemory_pool_host.pypool_host/common.pyHiSparseHostPoolMixinmemory_pool_host.pypool_host/hisparse.pyHiSparseHostPoolMixingets its ownpool_host/hisparse.py(rather thanbase.pyormla.py) because it is a concrete mixin shared by multiple host pools (MLATokenToKVPoolHostandDeepSeekV4PagedHostPool, both still inmemory_pool_host.py). Keeping it separate frommla.pyavoids making the DeepSeekV4/paged host path depend on an MLA-family module in follow-up moves.pool_host/__init__.pyintentionally re-exports only the package-level public API used by callers today:HostKVCacheandHostTensorAllocator. Lower-level helpers stay importable from their owning submodules (pool_host.base,pool_host.common,pool_host.hisparse). The Mooncake allocator import insideget_allocator_from_storagestays lazy (function-local), matching the original.memory_pool_host.pykeeps every concrete pool class. It imports the package-levelHostKVCachefrompool_host; imports base-only helpers (HICACHE_HOST_MEMORY_RESERVE_BYTES,synchronized) frompool_host.base; imports host allocation helpers (ALLOC_MEMORY_FUNCS,get_allocator_from_storage) frompool_host.common; and importsHiSparseHostPoolMixinfrompool_host.hisparsefor its still-local implementations.ruffremoved the now-orphanedabc,defaultdict,wraps,alloc_mmap, andKVCacheimports from it.Caller-site impact
12 import sites across 11 files are redirected away from
memory_pool_hostfor moved symbols:HostKVCacheimports now usesglang.srt.mem_cache.pool_host; 2 of these are insideTYPE_CHECKINGblocks.mooncake_store.pysplits the not-yet-movedMLATokenToKVPoolHostimport frommemory_pool_hostwhile movingHostKVCache/HostTensorAllocatortopool_host.ALLOC_MEMORY_FUNCS/alloc_with_pin_memorynow import frompool_host.common(jit_kernel/tests/test_hicache.py,test_dsa_pool_host_unit.py, plus 2 method-local lazy imports intest_hisparse_unit.py).A repo-wide symbol scan confirms no external caller imports the moved symbols from
memory_pool_hostafter this PR;memory_pool_host.pyitself still imports the helpers because its concrete host pools remain there for now.Git blame preservation
git blame -C -C -Con the three relocated-code files recovers their pre-refactor ancestry frommemory_pool_host.pyand earlier history:base.pycommon.pyhisparse.py= 326 / 340 (95.9%) of relocated lines traced; the rest are rewritten import preambles.
pool_host/__init__.pyis a new 7-line re-export module.memory_pool_host.pyis modified (not deleted), so the concrete pools' blame is preserved natively for the follow-up PRs.Mechanical Move
Transform script (self-contained, reproduces this PR's current diff byte-for-byte from the current PR base): https://gist.github.com/alphabetc1/34850017427438e4b26fad6fb3874d2a
Current verified target:
7e7e3820c26ba0609f017b99358172a9776197defrom basee1955bf57ab39a4de7f7daf9a619e4f68f952ed9.One-click verification — run from the repo root with Python >= 3.10:
python3.10 <(curl -sL https://gist.githubusercontent.com/alphabetc1/34850017427438e4b26fad6fb3874d2a/raw/5cd0e3a845800883de7ca210eec603835a031f59/transform_pool_host_base.py)Expected output:
PASS: transform reproduces the commit exactly.Accuracy Tests
The unit tests that exercise the moved symbols (host pools + allocation funcs) all pass on an NVIDIA H20:
python -m pytest -q \ test/registered/unit/mem_cache/test_dsa_pool_host_unit.py \ test/registered/unit/managers/test_hisparse_unit.py \ python/sglang/jit_kernel/tests/test_hicache.pySpeed Tests and Profiling
N/A — mechanical relocation only, no hot-path change.
Checklist
Review and Merge Process
/tag-and-rerun-ci,/tag-run-ci-label,/rerun-failed-ciCI States
Latest PR Test (Base): ✅ Run #27803114008
Latest PR Test (Extra): ❌ Run #27803113902