mirror of
https://github.com/kvcache-ai/Mooncake.git
synced 2026-11-05 01:17:55 +00:00
[GH-ISSUE #4995] [RFC]: Faster io_uring SSD reads for offload: sliding-window submission, cross-bucket batching and dedicated read threads #1267
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#1267
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 @SnowLegend-star on GitHub (Oct 27, 2026).
Original GitHub issue: https://github.com/kvcache-ai/Mooncake/issues/4995
Changes proposed
Title: [RFC]: Faster io_uring SSD reads for offload: sliding-window submission, cross-bucket batching and dedicated read threads
Changes proposed
Motivation
We serve GLM-style MLA models with SGLang HiCache + Mooncake standalone (SSD offload as L3). Prefill throughput is bounded by how fast one
real_clientcan load cold KV from SSD. WithMOONCAKE_OFFLOAD_USE_URING=trueon a single NVMe drive, one reader gets ~3.0 GB/s, while the drive can do ~6 GB/s. Profiling the read path (FileStorage::BatchGet→BucketStorageBackend::BatchLoad→UringFile::batch_read) shows three limits:SharedUringRing::batch_readsubmits up toQUEUE_DEPTH(32) reads, then waits for the whole group before it submits the next one. So the slowest read in each group sets the pace, and the queue drains between groups.BatchLoadcallsbatch_readonce per bucket file, one after another. A batch whose keys span many buckets becomes many small serial submissions.coro_iopool threads (hardware_concurrency()of them; 128 on our host). After splitting the arena into <=1 GiB iovecs (same idea as #4862), we saw ~200 registrations of a 10 GiB arena at cold start. Each one pins ~2.6M pages, so early reads time out (-706), and single-reader throughput drops from 3.0 to 1.3 GB/s until the threads are warm. #4788 fixes this withio_uring_clone_buffers(), but that needs kernel 6.12+; many production hosts (ours included) run 5.10.Proposal
All changes are inside the io_uring path. POSIX reads and the write path are unchanged.
SharedUringRing::batch_read_multi(items, window). It fills the ring up towindowin-flight SQEs, then submits one more each time a CQE completes. Each item records its own result. On a ring-level error it drains the ring and resets it, as today. The window and ring size come fromMOONCAKE_OFFLOAD_URING_QUEUE_DEPTH(default 32, ring capped at 4096).BucketStorageBackend::BatchLoadopens every bucket file the batch needs, collects allReadDescs with their file, and issues a singleUringFile::batch_read_multicall. The completion, short-read and pointer-offset checks after the read stay the same.UringFile::start_read_workers(threads, queue_depth), controlled byMOONCAKE_OFFLOAD_URING_READ_THREADS(proposed default 8;0keeps the current behavior of reading on the caller thread). When enabled:register_global_bufferpublishes it, and one thread at a time (a mutex), because concurrent pinning of the same arena was much slower than serial on 5.10;threads × arena, notpool size × arena.Results
Setup: kernel 5.10, one NVMe drive, staging arena 10 GiB, lease 5 s, 16 client threads, ~1.8 MB per object, ~430 MB per
BatchGet. One reader with N concurrent batch reads. Unique bytes / wall time, GB/s:-706until all pool threads registeredWith 8 read threads, average SSD load per batch is ~70 ms at N=1. At N=4 the drive is close to saturated. Every run verifies the data it reads back.
Plan
I'd split the code into separate PRs (about 450 non-test lines in total, plus tests):
batch_read_multi+ cross-bucket batching inBatchLoad. This works without the other two parts and is useful on its own.Each PR adds unit tests for >1 GiB fixed buffers, multi-file batch reads, concurrent callers on read workers, and multi-bucket
BatchLoadover uring.Questions for maintainers
UringFile, or would you prefer the reads to stay on caller threads? One alternative is to fall back to #4788's clone approach when the kernel supports it.MOONCAKE_OFFLOAD_URING_READ_THREADS: should it be 8 when uring is enabled, or 0 (opt-in)?:)
Before submitting a new issue...
@github-actions[bot] commented on GitHub (Oct 27, 2026):
Thanks for opening this issue, @SnowLegend-star!
60999643A maintainer will triage this when possible. To help us respond faster, please include:
Useful links: Documentation · Contributing guide