s0nskar opened a new pull request, #3696:
URL: https://github.com/apache/celeborn/pull/3696
<!--
Thanks for sending a pull request! Here are some tips for you:
- Make sure the PR title start w/ a JIRA ticket, e.g. '[CELEBORN-XXXX]
Your PR title ...'.
- Be sure to keep the PR description updated to reflect all changes.
- Please write your PR title to summarize what this PR proposes.
- If possible, provide a concise example to reproduce the issue for a
faster review.
-->
### What changes were proposed in this pull request?
We are using 0.5.3 and noticed that after a worker processes a heavy shuffle
workload, its Netty direct memory metric (usedDirectMemory) spikes to a high
value and then gets stuck and never recovers — even after the all flush ends
and the worker becomes completely idle. The memory stays stuck until the worker
is restarted.
<img width="1372" height="327" alt="Screenshot 2026-05-19 at 2 25 38 PM"
src="https://github.com/user-attachments/assets/294ccb97-a1dc-4785-ad27-ecda36db0ed4"
/>
Although i noticed that there are fixes which tries to handle this by using
pinnedMemory – https://github.com/apache/celeborn/pull/3018 and
https://github.com/apache/celeborn/pull/3099 but i think that this PR is the
correct way to handle this instead of relying on pinnedMemory.
### Why are the changes needed?
`PooledByteBufAllocator` maintains a per-thread `PoolThreadCache` for each
Flusher thread. When a ByteBuf is released, instead of immediately returning
its slot to the `PoolArena`, it goes into this thread-local cache. But the
PoolArena's view of the underlying `PoolChunk` is not updated.
`usedDirectMemory` counts all `PoolChunk` native memory regardless of how much
is truly in use vs. sitting in thread caches.
The thread cache is only swept when the owning thread crosses a allocation
threshold, but since the worker is in pause state after all flush items end,
all flush thread gets blocked on workingQueue(index).take(). The cache is never
swept, `PoolChunks` in thread cache are never freed, and usedDirectMemory stays
frozen.
In this PR, we are changing take() with poll() and on poll() timeout we are
explicitly calling `allocator.trimCurrentThreadCache()` to flush cached
`PoolChunks` back to the `PoolArena`, allowing fully-free chunks to be
destroyed and usedDirectMemory to recover.
A similar pattern is already used by:
https://github.com/apache/celeborn/blob/main/worker/src/main/java/org/apache/celeborn/service/deploy/worker/memory/ReadBufferDispatcher.java#L131
### Does this PR resolve a correctness bug?
<!-- Check if yes. The `correctness` label will be added/removed
automatically. -->
- [ ] Yes
### Does this PR introduce _any_ user-facing change?
<!-- Check if yes. -->
- [ ] Yes
### How was this patch tested?
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]