mirror of
https://github.com/kvcache-ai/Mooncake.git
synced 2026-11-05 01:17:55 +00:00
[GH-ISSUE #4766] [RFC]: Pipeline SSD restore sub-batches with DRAM-to-HBM transfers #1215
Labels
No labels
ascend
auto-closed
bug
bug
CI/Build
Common
documentation
enhancement
feature request
good first issue
help wanted
high priority
MetaX
nightly-failure
pull-request
PyTorch Backend
question
RFC
Roadmap
stale
Store
Tests
Transfer Engine
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
kvcache-ai/Mooncake#1215
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Originally created by @ckeyever on GitHub (Oct 19, 2026).
Original GitHub issue: https://github.com/kvcache-ai/Mooncake/issues/4766
Changes proposed
Summary
Add an opt-in, bounded sub-batch pipeline to Mooncake Store's LOCAL_DISK restore path. While the SSD owner reads sub-batch B(i+1) into its DRAM staging arena, the requesting client transfers the already loaded sub-batch B(i) into its final destination buffers, including accelerator HBM.
The first implementation operates on complete objects and reuses the existing offload-read and buffer-release RPCs. It does not introduce intra-object chunking or a streaming RPC protocol. The initial target workload is batched KV-cache restoration on Ascend; scheduling should remain transport-independent.
This is a design proposal. No performance improvement has been measured yet.
Motivation and current behavior
The current restore path contains a barrier between SSD loading and destination transfer:
Relevant source at the inspected baseline:
The batch barrier prevents transfers for ready objects from overlapping the remaining objects' disk reads within that request. This proposal targets end-to-end SSD-hit restoration latency, measured until all requested destination data is usable.
Scope
In scope:
Deferred:
A request with a single object has no intra-object overlap benefit in this version.
Proposed design
1. Plan whole-object sub-batches
After the existing replica query and selection, group LOCAL_DISK objects by owner endpoint. Partition each owner group using both a target byte size and a maximum object count.
Each sub-batch contains full objects with their original result indices, destination slices, selected-replica metadata, sizes, and expected checksums. Preserve the caller's current duplicate-key behavior and restore results to their original positions.
Use byte-based partitioning because KV object sizes vary. An object larger than the target size is handled as a standalone sub-batch; account for its actual allocation size. If it exceeds the pipeline admission budget, execute the existing path exclusively after draining pipeline work, rather than rejecting a previously valid request.
Start with two sub-batches in the lifecycle window: one being loaded and one being transferred. Increase the window only after measurement. Keep useful batching within each SSD request so that the change does not collapse NVMe queue depth or turn small objects into one-RPC-per-key requests.
2. Run independent load and transfer stages
Use shared executors/coroutines rather than creating threads for every request.
Load stage:
Transfer stage:
Conceptual steady state:
The table assumes equal stage durations for illustration; the actual scheduler is completion-driven.
A dedicated transfer worker may initially use the existing blocking transfer wrapper while the independent load worker continues. Exposing the existing submitter's TransferFuture through a nonblocking Client helper can subsequently support multiple in-flight transfers. Asynchronous execution in every low-level API is not a prerequisite for the two stages to overlap.
3. Bound memory and scheduling
Track the full lifecycle:
Admission counts all allocated or reserved bytes, including reads in progress, READY buffers, alignment overhead, and transfers/checks still holding buffers.
Use:
The bounded READY queue is essential: when destination transfers slow down, loading must stop before unbounded DRAM accumulation. Requester-local accounting alone is insufficient to bound concurrent remote clients.
4. Preserve ownership and lease safety
The current synchronous ReleaseGuard must not release buffers immediately after a new asynchronous submit helper returns. Ownership moves to the in-flight operation context and lasts through confirmed transfer termination and any verification that still accesses the staging buffer.
For the same-process path, retain the LocalBatchResult owner. For the remote path, retain the returned batch_id and issue the existing release RPC only after the source is no longer accessed.
The owner's existing TTL-based GC is a specific issue to settle before enabling this feature: prefetching introduces additional residence time before transfer. Track deadlines conservatively from before each load RPC, reserve transfer capacity before prefetching, and stop admitting work that cannot meet its budget. These checks reduce exposure but do not prove that a timed-out DMA has stopped.
The required safety contract is:
Prefer a minimal integration with existing buffer ownership and release handling. If safe lifetime handling requires an owner capability or lease extension, include that small change and gate the opt-in path accordingly; it does not require a streaming data protocol. Mixed-version deployments must retain the existing path unless the required owner behavior is known to be available.
5. Preserve API and failure semantics
Keep synchronous public batch APIs synchronous: return only when their existing completion conditions are satisfied. Internally, individual objects can finish earlier.
Map load, transfer, and checksum errors back to the affected keys. Do not report a partially written destination as a successful object. Preserve the current behavior for independent successful keys.
On cancellation or fatal request failure, stop new loads, drain/cancel outstanding operations using supported transport semantics, release buffers after quiescence, and retain the caller's destination-buffer lifetime until those accesses have ended. Retries must follow the existing replica/version rules; do not overwrite a destination while an earlier attempt can still write to it.
Implementation touch points
Existing Ascend constraints remain applicable: buffer-pool mode and the async executor cannot simply be enabled together, and the optional pinned restore arena is disabled with io_uring in the inspected code. Enabling an async environment variable alone does not remove the Store batch barrier. Reuse the existing protocol-aware registered staging allocator and validate the intended deployment's memory/transfer compatibility.
Tentative opt-in tuning controls, with final names to follow maintainer guidance:
Initial experiments should sweep 1-4 MiB target sub-batches and windows of 2 and 4. These are experimental settings, not selected production defaults.
Expected benefit and trade-offs
For N equal sub-batches with effective load time tr and transfer time tx, an ideal two-stage pipeline takes:
The corresponding serialized work takes N * (tr + tx). This model assumes independent resources and excludes additional RPC and scheduling costs. The real baseline is the current one-large-batch implementation, so benchmark against it directly; extra sub-batch RPCs and reduced disk batching can erase the overlap benefit.
Benefits should be largest when both stages contribute materially to restoration time and requests contain multiple objects. Costs include more RPCs, executor work, staging pressure, and lifetime-management complexity. Use the current path for small requests or unsupported configurations.
Validation and rollout
Correctness:
Performance:
Roll out as opt-in on deployments with validated buffer-lifetime support. Change defaults only after correctness and workload-level performance results are available. Report measurements before claiming a speedup.
Alternatives considered
Related work
The following existing discussions and open PRs were reviewed before submission:
Searches included SSD pipeline, SSD overlap, offload sub-batch/subbatch, and open offload PRs. The distinct question here is whether to add bounded, whole-object load/transfer overlap inside a LOCAL_DISK demand batch.
Questions for maintainers
Before submitting a new issue...
AI assistance disclosure: this RFC was drafted with AI assistance at the submitter's request.
@github-actions[bot] commented on GitHub (Oct 19, 2026):
Thanks for opening this issue, @ckeyever!
11692486A maintainer will triage this when possible. To help us respond faster, please include:
Useful links: Documentation · Contributing guide