Skip to content

[TENT] Integrate receiver-credit pull control with adaptive dispatch protection#2925

Draft
catyans wants to merge 51 commits into
kvcache-ai:mainfrom
catyans:receiver-credit-production-control
Draft

[TENT] Integrate receiver-credit pull control with adaptive dispatch protection#2925
catyans wants to merge 51 commits into
kvcache-ai:mainfrom
catyans:receiver-credit-production-control

Conversation

@catyans

@catyans catyans commented Jul 15, 2026

Copy link
Copy Markdown
Collaborator

Summary

Connect the receiver-credit model to a production-shaped sender-pull control path and protect queued RDMA dispatch with an adaptive owner-window limiter.

This is a stacked follow-up to #2860, #2861, and #2862. Until those prerequisites merge, GitHub will temporarily show their commits in this PR. The branch will be rebased and the visible diff reduced after the stack lands.

Related RFC: #2849
Benchmark harness: #2859

What this adds

  • typed ControlClient -> ControlService -> ReceiverCreditAllocator pull RPC
  • receiver-global byte/slot allocation with session, epoch, sequence, and sender fencing
  • demand-driven, coalesced credit refill and batched completion reporting
  • direct remote RDMA WRITE dispatch integration
  • default-disabled and fail-closed configuration
  • pull latency accounting and RPC benchmark/harness coverage
  • adaptive dispatch protection driven by RPC health
  • multiplicative reduction, additive recovery, and two-event learned-ceiling hysteresis
  • clamp to runtime_queue/max_dispatch_owners
  • tebench controls for dispatch/adaptive settings, RDMA-device filtering, and NUMA placement

Why

Independent sender-local limits cannot bound aggregate receiver occupancy under many-to-one load. Receiver-owned credits provide the aggregate capacity contract, but the first TCP control rollout must also preserve control progress while TCP RPC and RDMA payload share an mlx5 path. The adaptive limiter prevents a persistently unsafe data window from repeatedly triggering TCP RTO-scale stalls.

Real-cluster results

Two-node H20/RoCE cluster, one NUMA node, one reachable mlx5_0 rail, four submit threads, 4 MiB WRITE, batch size 1, 20-second measurement interval:

Case Throughput Pull maximum Pulls >100 ms Result
Runtime queue only, static owner limit 2 40.967 GB/s n/a n/a matched baseline
Receiver credit, default adaptive limit 2 41.043 GB/s 1.764 ms 0 / 12,814 owners=2, ceiling=2
Receiver credit, deliberately start/max at 3 39.362 GB/s 208.085 ms 2 / 11,992 learned/recovered to 2
Receiver credit, old static owner limit 3 19.032 GB/s 209.819 ms 12 / 1,617 no automatic recovery

The default adaptive case was +0.19% versus the matched no-credit/static-2 baseline. Starting at the known-unsafe level improved throughput by 106.82% versus static-3 behavior and reduced RTO-scale pulls from 12 to 2.

Control RPC measurements

  • two-resource codec request/response: 136/148 bytes
  • captured framed TCP request/response: 167/171 bytes
  • 1 sender: about 20k pulls/s, 64.7 us P99
  • 4 senders: about 79.4k aggregate pulls/s
  • 16 senders: about 165k aggregate pulls/s
  • receiver processing: about 5.8--7.3 us/pull
  • safe two-owner campaign: maximum pull latency 722/592/584 us across three credit runs, with none above 1 ms

Dual-endpoint packet capture showed that the roughly 200 ms outliers were TCP retransmission events: the request was visible at the sender but first appeared at the receiver 201--207 ms later; once received, the receiver replied in roughly 10--50 us. DSCP 46 alone did not remove the unsafe-window loss on this VPC.

Validation

Remote-only validation on the H20 cluster:

  • receiver_credit_test
  • receiver_credit_control_test
  • receiver_credit_protocol_test
  • receiver_credit_allocator_test
  • receiver_credit_config_test
  • receiver_credit_control_service_test
  • receiver_credit_controller_test
  • receiver_credit_dispatch_test
  • tent_runtime_queue_dispatch_test

Result: 9/9 suites passed.

Compatibility

Receiver credits remain disabled by default. When enabled, runtime queue support and installed control state are required; incomplete setup fails closed rather than treating missing receiver capacity as unlimited.

Claims boundary

The primary demonstrated benefit is receiver-capacity protection and bounded recovery from an unsafe dispatch window without a measured healthy-path throughput regression in this setup. This PR does not yet claim SGLang/vLLM TTFT improvement.

The adaptive limiter bounds repeated damage but cannot guarantee zero first-loss if an operator raises the ceiling above a validated level. A typed independent control QP with reserved WR/CQ capacity remains the durable follow-up for eliminating shared-path TCP progress dependence.

Stack note

This draft intentionally opens before prerequisite merge, per the current development workflow. Merge conflicts and duplicate prerequisite commits will be cleaned after #2860--#2862 land.

彦纾 added 30 commits July 11, 2026 21:55
Snapshot receiver credit identity and charge at queue admission, reserve atomically before dispatch, and roll back exact reservations when transport submission fails. Add a default-off configuration and ownership-safe installation API, plus queue, restart, exhaustion, rollback, and multi-owner coverage.
# Conflicts:
#	mooncake-transfer-engine/tent/tests/CMakeLists.txt
# Conflicts:
#	mooncake-transfer-engine/tent/tests/CMakeLists.txt
# Conflicts:
#	mooncake-transfer-engine/tent/src/runtime/transfer_engine_impl.cpp
# Conflicts:
#	mooncake-transfer-engine/tent/tests/CMakeLists.txt

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a receiver-credit flow control mechanism for the Mooncake Transfer Engine (TENT) to manage outstanding bytes and request slots between senders and receivers. It adds key components including SenderCreditLedger, ReceiverCreditAllocator, ReceiverCreditPullController, and an adaptive dispatch limiter, integrating them into the transfer engine and admission queue. The review feedback highlights two critical issues: a protocol loop and credit leak when a sender restarts while the receiver remains active, and a potential null pointer dereference of the remote segment descriptor that could lead to a segmentation fault.

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.

Comment thread mooncake-transfer-engine/tent/src/runtime/receiver_credit_allocator.cpp Outdated
Comment thread mooncake-transfer-engine/tent/src/runtime/transfer_engine_impl.cpp
# Conflicts:
#	mooncake-transfer-engine/benchmark/tent_backend.cpp
#	mooncake-transfer-engine/benchmark/utils.cpp
#	mooncake-transfer-engine/benchmark/utils.h
#	mooncake-transfer-engine/tent/include/tent/runtime/receiver_credit.h
#	mooncake-transfer-engine/tent/src/runtime/receiver_credit.cpp
#	mooncake-transfer-engine/tent/tests/CMakeLists.txt
#	mooncake-transfer-engine/tent/tests/receiver_credit_test.cpp
@catyans
catyans force-pushed the receiver-credit-production-control branch from 2561043 to 24a6510 Compare July 15, 2026 07:25
@catyans

catyans commented Jul 15, 2026

Copy link
Copy Markdown
Collaborator Author

Updated in 24a6510:

  • merged current main to clear the dirty state
  • fixed sender restart handling in ReceiverCreditAllocator: an initial-session restart now reclaims the stale outstanding grant budget, erases the old entry, and allows a fresh allocation instead of looping on SessionChanged
  • added InitialSessionRestartReclaimsOutstandingGrant coverage
  • added a defensive null check after getRemoteCached before reading receiver_credit_versions
  • preserved current main tebench flags: deadline arbitration / intent type / QoS metrics, plus this PR's receiver-credit runtime-queue flags

Cluster validation on lingjun-100 / codex_mooncake_pr_eval:

cmake -S . -B /root/mooncake-pr2925-build -G Ninja \
  -DWITH_TE=ON -DWITH_STORE=OFF -DWITH_STORE_RUST=OFF \
  -DUSE_TENT=ON -DBUILD_UNIT_TESTS=ON -DBUILD_EXAMPLES=OFF \
  -DUSE_CUDA=OFF -DUSE_HIP=OFF -DUSE_ASCEND=OFF
cmake --build /root/mooncake-pr2925-build --target \
  receiver_credit_test receiver_credit_control_test receiver_credit_protocol_test \
  receiver_credit_allocator_test receiver_credit_config_test \
  receiver_credit_control_service_test receiver_credit_controller_test \
  receiver_credit_dispatch_test admission_queue_test bw_arbitration_test tebench -j 16

Executed tests:

  • receiver_credit_test: 16/16 passed
  • receiver_credit_control_test: 25/25 passed
  • receiver_credit_protocol_test: 8/8 passed
  • receiver_credit_allocator_test: 12/12 passed
  • receiver_credit_config_test: 12/12 passed
  • receiver_credit_dispatch_test: 5/5 passed
  • admission_queue_test: 36/36 passed
  • bw_arbitration_test: 7/7 passed
  • receiver_credit_control_service_test: 3/3 passed
  • receiver_credit_controller_test: 6/6 passed
  • tebench built; help output includes receiver_credit_mode, tent_intent_type, and deadline_bw_arbitration flags.

@codecov-commenter

Copy link
Copy Markdown

⚠️ Please install the 'codecov app svg image' to ensure uploads and comments are reliably processed by Codecov.

Codecov Report

❌ Patch coverage is 47.16981% with 28 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
mooncake-transfer-engine/benchmark/utils.cpp 0.00% 14 Missing ⚠️
...e-transfer-engine/tests/graceful_shutdown_test.cpp 64.10% 14 Missing ⚠️

📢 Thoughts on this report? Let us know!

@catyans
catyans marked this pull request as ready for review July 16, 2026 01:42
@catyans
catyans marked this pull request as draft July 16, 2026 06:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants