You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This RFC discusses how Mooncake Store traffic should participate in TENT QoS so that latency-sensitive transfers are protected from background offload traffic.
A representative serving workload has two priority classes:
HIGH: foreground point-to-point KV handoff, such as Prefill-to-Decode (P2D), and foreground remote-prefix fetch.
LOW: background writes to DRAM, local SSD, remote memory, or remote storage.
The main contention is on NIC TX and accelerator PCIe outbound bandwidth. A background Store write should not delay a foreground KV handoff that gates time-to-first-token. This RFC compares three integration boundaries:
Option A — route all storage data movement through TENT.
Option B — use layered QoS and unified admission while retaining existing executors.
Option C — route only the network portion of remote Store traffic through TENT.
The proposed rollout is C first, then B if PCIe-side interference remains measurable. Option A should remain a longer-term choice only if TENT is intentionally expanded into a general data-movement runtime.
This RFC is an integration proposal. It does not redefine the intent schema, QoS contract, budget scheduler, execution plan, or local admission queue proposed in #2865, #2856, #2866, #2863, and #2132. Instead, it asks how Mooncake Store should consume those mechanisms and where the ownership boundary should be.
Motivation
Consider the following traffic classes:
Traffic
Typical resources
Priority
Reason
Foreground P2D KV handoff
accelerator PCIe OUT + NIC TX
HIGH
decode cannot start until the KV state arrives
Foreground remote-prefix fetch
NIC RX + accelerator PCIe IN, depending on placement
HIGH
a hit avoids repeated prefill computation
DRAM offload
accelerator PCIe OUT + memory bandwidth
LOW
background cache management
Local SSD write
accelerator PCIe OUT + memory bandwidth + NVMe
LOW
background persistence/eviction
Remote Store write
accelerator PCIe OUT, depending on GDR/staging, + NIC TX
LOW
background persistence/write-through
Foreground prefix fetch often uses the opposite direction from background writes, so it should remain concurrent when the resources do not conflict. The scheduler must therefore reason about resources and direction; a single global HIGH/LOW gate would unnecessarily serialize independent RX/IN and TX/OUT work.
The required behavior is cooperative preemption:
foreground HIGH arrives
-> stop admitting new conflicting LOW slices
-> allow already-submitted DMA/WQE/I/O to complete
-> run HIGH
-> resume LOW using otherwise-idle capacity
Already-posted WQEs and already-submitted DMA or NVMe operations generally cannot be revoked. Therefore, the protection bound depends on both slice size and the global LOW in-flight window, not on queue ordering alone.
Store Put dispatches disk writes to PutToLocalFile, while memory and NoF replicas go through TransferSubmitter (client_service.cpp).
TransferSubmitter then selects local memcpy, Transfer Engine, SPDK NoF, or file-read execution depending on replica type and locality (transfer_task.cpp). These executors do not share one priority scheduler.
The file-put path performs synchronous accelerator-to-host copying into a pinned buffer before submitting StorageBackend::StoreObject to the write pool (client_service.cpp). Deferring this copy requires an explicit buffer-lifetime contract; queueing a raw pointer after the caller may reuse it would be unsafe.
Store priority is not propagated to TENT
Remote memory replica transfers construct the legacy Transport::TransferRequest (transfer_task.cpp). The legacy request has no intent or QoS priority field (transport.h), and the adapter does not populate those fields when creating tent::Request (transfer_engine.cpp). The effective result is the TENT default priority rather than Store-aware classification.
TENT already contains useful QoS primitives
TENT RDMA slicing preserves request priority and passes it into device selection and worker dispatch (rdma_transport.cpp). RDMA workers maintain three priority queues and select HIGH before MEDIUM before LOW (workers.cpp, workers.cpp).
However:
SharedSlotManager provides cross-process slot visibility/gating, not a cross-process priority queue or global LOW in-flight budget.
LOW priority promotion must be configured carefully; promoting old background work into HIGH can defeat strict foreground protection.
Device selection fallback is availability-oriented, not a hard priority reservation.
Rail monitoring provides health and rerouting, not business-priority arbitration.
Hardware QoS is a QP-pool decision
SL/traffic class is associated with configured QP pools and selected by policy. A practical design uses distinct HIGH and LOW named QP pools. It should not claim per-WQE hardware preemption. End-to-end network differentiation also requires matching switch DCB/PFC/ETS configuration.
Goals
Protect foreground handoff P95/P99 latency under background Store load.
Preserve concurrency for transfers that do not contend on the same directional resource.
Prevent LOW traffic in one process from blocking HIGH traffic in another process sharing a NIC or PCIe root complex.
Allow LOW traffic to consume unused bandwidth and guarantee minimum progress.
Expose unmanaged paths explicitly instead of claiming QoS coverage for black-box backends.
Keep a default-off, reversible rollout path.
Non-goals
Hard cancellation of already-submitted RDMA, CUDA, SPDK, or NVMe work.
Using transport kernel duration as the only success metric. The primary metric should be the application-visible foreground handoff latency; transport timing is diagnostic.
Requiring all storage backends to be rewritten in the first phase.
Common semantic contract
All three options need the same semantic plumbing:
The concrete names and ABI should reuse #2865 and #2856 rather than introduce a second public schema. The important integration requirement is end-to-end propagation:
Store operation
-> legacy/public request compatibility layer
-> tent::Request
-> policy and QP-pool selection
-> admission and worker queues
-> metrics/completion
Unknown legacy callers should be visible as UNKNOWN in metrics. A compatibility default may be necessary during rollout, but silently treating every Store request as HIGH should not be the steady state.
Option A: route all storage data movement through TENT
Design
Expand TENT into a general data-movement runtime. P2D, remote memory, remote SSD, local SSD, accelerator/host copies, and prefix fetches are represented as logical transfer DAGs scheduled by one resource-aware runtime.
P2D / prefix / DRAM / local SSD / remote Store
|
v
TENT resource-aware scheduler
/ | \
RDMA Copy File/NoF
executor executor executor
A logical request would contain ordered stages, stable buffer ownership, resource charges, priority/intent, completion, and cancellation metadata. The Execution Plan work in #2863 is the natural representation boundary.
Scheduling rules:
maintain runnable queues per resource and priority;
stop new conflicting LOW slice submission while HIGH is pending;
permit non-conflicting directional work to continue;
enforce global and per-process LOW bytes/slices/outstanding limits;
guarantee LOW progress with a minimum budget, not by blindly promoting it to HIGH;
reserve all resources required by the next composite stage atomically or in a fixed order.
Required implementation work
Add Copy, file/NVMe, SPDK/NoF, and backend adapters/executors with priority-equivalent scheduling.
Convert synchronous file-put D2H into a lifetime-safe asynchronous contract. Possible models are retaining the source allocation, copying to runtime-owned staging memory, or exposing an asynchronous completion contract.
Extend local and cross-process admission to all declared resources.
Ensure an executor failure cannot block unrelated foreground TENT work.
Benefits
One scheduling domain can model NIC, PCIe, memory, and NVMe contention.
Consistent fairness, observability, and cross-process accounting.
Strong foundation for deadlines, tenant budgets, and composite transfer plans.
Risks
Largest scope and failure-domain expansion.
TENT becomes responsible for very different completion, retry, and cancellation models.
Buffer allocator lifetime changes may be invasive.
A central scheduler/shared lock can become a new bottleneck.
Merely wrapping black-box backend calls in a TENT API would produce apparent, not effective, QoS.
Option B: layered QoS with unified admission and existing executors
Design
Keep TENT, memcpy workers, file workers, SPDK/NoF, and storage backends as execution owners. Extend the Admission Queue from #2132, or a shared layer above it, so every executor must acquire a resource-scoped permit before submitting its next slice.
The uncontended path should remain an atomic fast path. Heartbeats/generations reclaim leaked permits after process failure.
Buffer-lifetime boundary
This option still cannot defer the synchronous file-put D2H safely without source retention or owned staging memory. The path should remain explicitly unmanaged until that contract exists. Network and stable-buffer paths can be integrated first.
Benefits
Unified scheduling authority while retaining mature executors.
Can cover both NIC and PCIe contention incrementally.
All executors must honor the permit contract; bypasses need auditing.
Priority configuration can diverge across layers and cause inversion.
Resource declarations may not match a backend's real pipeline.
Cross-process leases and multi-resource acquisition remain non-trivial.
Option C: route only remote Store network traffic through TENT
Design
Address the clearest conflict first: foreground handoff and background remote Store writes sharing NIC TX.
foreground handoff HIGH ----\
> TENT priority/admission -> RDMA/NIC
remote Store write LOW ------/
DRAM / local SSD / opaque backend -> existing path, reported as unmanaged
“Remote Store” must first be classified:
Remote memory replica already using Transfer Engine/TENT. Propagate priority/intent through the legacy adapter and limit LOW in-flight work.
Remote SSD backend exposing a network-transfer stage. Add a TENT transport adapter for the data plane while leaving metadata/control RPCs in the backend.
Remote SSD network hidden inside StorageBackend. TENT cannot directly schedule it. The backend must expose bounded slices, completion, stable buffers, and endpoint/resource metadata; otherwise only coarse external rate limiting is possible.
Minimum changes for case 1:
add backward-compatible intent/priority/trace propagation to the legacy request adapter;
mark background remote writes LOW and foreground fetch/handoff HIGH;
Should TENT remain a network transport runtime, or eventually own all storage data movement?
Do maintainers agree with Option C as the first integration phase and Option B as the target architecture?
Should the legacy Store transfer request gain explicit intent/priority fields, or should Store move directly to the newer request/options API?
Should cross-process Store QoS extend the existing shared-slot state, or use the distributed admission mechanism proposed elsewhere?
Which LOW intents may age within LOW, and which, if any, may be promoted to another priority class?
Is HIGH/LOW named-QP-pool selection the preferred hardware boundary?
For deferred file-put D2H, should Mooncake retain the source allocation, use runtime-owned staging memory, or expose asynchronous completion to callers?
Should the primary acceptance metric be the application-visible handoff P99, with CQ/API/kernel timings treated as diagnostic breakdowns?
Before submitting a new issue...
Searched existing issues for TENT QoS, transfer intent, admission, resource budgets, traffic classes, and execution plans.
Read the TENT roadmap and the related RFCs listed above.
Changes proposed
Summary
This RFC discusses how Mooncake Store traffic should participate in TENT QoS so that latency-sensitive transfers are protected from background offload traffic.
A representative serving workload has two priority classes:
The main contention is on NIC TX and accelerator PCIe outbound bandwidth. A background Store write should not delay a foreground KV handoff that gates time-to-first-token. This RFC compares three integration boundaries:
The proposed rollout is C first, then B if PCIe-side interference remains measurable. Option A should remain a longer-term choice only if TENT is intentionally expanded into a general data-movement runtime.
This RFC is an integration proposal. It does not redefine the intent schema, QoS contract, budget scheduler, execution plan, or local admission queue proposed in #2865, #2856, #2866, #2863, and #2132. Instead, it asks how Mooncake Store should consume those mechanisms and where the ownership boundary should be.
Motivation
Consider the following traffic classes:
Foreground prefix fetch often uses the opposite direction from background writes, so it should remain concurrent when the resources do not conflict. The scheduler must therefore reason about resources and direction; a single global HIGH/LOW gate would unnecessarily serialize independent RX/IN and TX/OUT work.
The required behavior is cooperative preemption:
Already-posted WQEs and already-submitted DMA or NVMe operations generally cannot be revoked. Therefore, the protection bound depends on both slice size and the global LOW in-flight window, not on queue ordering alone.
Current code shape
The observations below use commit
9c6125f.Store traffic does not have one execution path
Store
Putdispatches disk writes toPutToLocalFile, while memory and NoF replicas go throughTransferSubmitter(client_service.cpp).TransferSubmitterthen selects local memcpy, Transfer Engine, SPDK NoF, or file-read execution depending on replica type and locality (transfer_task.cpp). These executors do not share one priority scheduler.The file-put path performs synchronous accelerator-to-host copying into a pinned buffer before submitting
StorageBackend::StoreObjectto the write pool (client_service.cpp). Deferring this copy requires an explicit buffer-lifetime contract; queueing a raw pointer after the caller may reuse it would be unsafe.Store priority is not propagated to TENT
Remote memory replica transfers construct the legacy
Transport::TransferRequest(transfer_task.cpp). The legacy request has no intent or QoS priority field (transport.h), and the adapter does not populate those fields when creatingtent::Request(transfer_engine.cpp). The effective result is the TENT default priority rather than Store-aware classification.TENT already contains useful QoS primitives
TENT RDMA slicing preserves request priority and passes it into device selection and worker dispatch (
rdma_transport.cpp). RDMA workers maintain three priority queues and select HIGH before MEDIUM before LOW (workers.cpp,workers.cpp).However:
SharedSlotManagerprovides cross-process slot visibility/gating, not a cross-process priority queue or global LOW in-flight budget.Hardware QoS is a QP-pool decision
SL/traffic class is associated with configured QP pools and selected by policy. A practical design uses distinct HIGH and LOW named QP pools. It should not claim per-WQE hardware preemption. End-to-end network differentiation also requires matching switch DCB/PFC/ETS configuration.
Goals
Non-goals
Common semantic contract
All three options need the same semantic plumbing:
The concrete names and ABI should reuse #2865 and #2856 rather than introduce a second public schema. The important integration requirement is end-to-end propagation:
Unknown legacy callers should be visible as
UNKNOWNin metrics. A compatibility default may be necessary during rollout, but silently treating every Store request as HIGH should not be the steady state.Resource accounting should distinguish at least:
A non-GDR remote write is a staged pipeline rather than one resource charge:
Option A: route all storage data movement through TENT
Design
Expand TENT into a general data-movement runtime. P2D, remote memory, remote SSD, local SSD, accelerator/host copies, and prefix fetches are represented as logical transfer DAGs scheduled by one resource-aware runtime.
A logical request would contain ordered stages, stable buffer ownership, resource charges, priority/intent, completion, and cancellation metadata. The Execution Plan work in #2863 is the natural representation boundary.
Scheduling rules:
Required implementation work
Benefits
Risks
Option B: layered QoS with unified admission and existing executors
Design
Keep TENT, memcpy workers, file workers, SPDK/NoF, and storage backends as execution owners. Extend the Admission Queue from #2132, or a shared layer above it, so every executor must acquire a resource-scoped permit before submitting its next slice.
Example permit:
Rules:
high_pending[resource]; new conflicting LOW permits stop.Cross-process shared state should include:
The uncontended path should remain an atomic fast path. Heartbeats/generations reclaim leaked permits after process failure.
Buffer-lifetime boundary
This option still cannot defer the synchronous file-put D2H safely without source retention or owned staging memory. The path should remain explicitly
unmanageduntil that contract exists. Network and stable-buffer paths can be integrated first.Benefits
Risks
Option C: route only remote Store network traffic through TENT
Design
Address the clearest conflict first: foreground handoff and background remote Store writes sharing NIC TX.
“Remote Store” must first be classified:
StorageBackend. TENT cannot directly schedule it. The backend must expose bounded slices, completion, stable buffers, and endpoint/resource metadata; otherwise only coarse external rate limiting is possible.Minimum changes for case 1:
global_low_inflight_bytes, per-process LOW bytes, per-QP outstanding WRs, and LOW slice size;high_pendingfor processes sharing the selected NIC;The cooperative yield bound is approximately:
Reducing slice size without limiting the total number of posted LOW WQEs does not provide this bound.
Coverage boundary
Option C protects the TENT-managed network portion. It does not guarantee that:
These limitations must be visible in metrics and documentation.
Benefits
Risks
Comparison
Proposed rollout
Phase 0: semantics and observability
UNKNOWNandunmanaged_transfer_bytesmetrics.Phase 1: Option C
high_pendingand global LOW in-flight accounting.Phase 2: evaluate the remaining interference
Phase 3: Option B
Phase 4: reconsider Option A
Only proceed if maintainers want TENT to own general data movement and the executor/lifetime refactor is justified by broader use cases.
Metrics and validation
Required metrics
Validation matrix
Proposed initial acceptance targets, subject to benchmark agreement:
Relationship to existing RFCs
Open questions
Before submitting a new issue...