Skip to content

[CELEBORN-2378] Fix CongestionController never resuming due to Netty pool overhead in getTotalPendingBytes()#3756

Open
Deegue wants to merge 1 commit into
apache:mainfrom
Deegue:CELEBORN-2378
Open

[CELEBORN-2378] Fix CongestionController never resuming due to Netty pool overhead in getTotalPendingBytes()#3756
Deegue wants to merge 1 commit into
apache:mainfrom
Deegue:CELEBORN-2378

Conversation

@Deegue

@Deegue Deegue commented Jul 10, 2026

Copy link
Copy Markdown

What changes were proposed in this pull request?

Change CongestionController.getTotalPendingBytes() from MemoryManager.instance().getMemoryUsage() to MemoryManager.instance().getPinnedMemory().

Why are the changes needed?

getMemoryUsage() returns nettyUsedDirectMemory + sortMemory, which includes Netty's pooled allocator overhead.

Change to getPinnedMemory() whcih returns nettyPinnedDirectMemory + sortMemory instead.

Does this PR resolve a correctness bug?

  • Yes, the worker is supposed to resume when pending data drops below the low watermark.

Does this PR introduce any user-facing change?

No API change.
Workers with congestion control will now correctly resume from congestion state when actual pending data drops below the low watermark.

How was this patch tested?

UTs

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Updates worker congestion-control pending-bytes calculation to avoid Netty pooled allocator overhead so the worker can correctly resume once actual pending data drops below the low watermark.

Changes:

  • Switch CongestionController.getTotalPendingBytes() from MemoryManager.getMemoryUsage() to MemoryManager.getPinnedMemory().

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 205 to 207
public long getTotalPendingBytes() {
return MemoryManager.instance().getMemoryUsage();
return MemoryManager.instance().getPinnedMemory();
}
Comment on lines 205 to 207
public long getTotalPendingBytes() {
return MemoryManager.instance().getMemoryUsage();
return MemoryManager.instance().getPinnedMemory();
}
@leixm

leixm commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

It's ok for me, but if we change getMemoryUsage to getPinnedMemory, we should instruct users in migration.md to lower the watermark to avoid off-heap OOM (Out of Memory) errors. Also, we should address the issue of calling getPinnedMemory at 10ms intervals. cc @RexXiong WDYT.

@leixm leixm requested review from RexXiong and leixm July 10, 2026 09:43

@zaynt4606 zaynt4606 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.

In non-POOLED mode (UNPOOLED or ADAPTIVE), pooledByteBufAllocators stays empty because both fill sites guard with if (allocatorType == POOLED).
So getNettyPinnedDirectMemory() sums an empty list and returns 0, making getTotalPendingBytes() underestimate pending data.

Suggested fix:
fall back to PlatformDependent.usedDirectMemory() when no pooled allocators exist, so non-POOLED configs retain the old behavior.

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.

4 participants