[SPARK-59444][CORE] Retain execution-memory task registration while allocations wait - #58747
Open
sunchao wants to merge 1 commit into
Open
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why are the changes needed?
An execution-memory task can have no bytes reserved while still waiting to acquire memory.
ExecutionMemoryPoolcurrently treats releasing the last byte as the end of the task's participation. If another acquisition for that task is waiting, it wakes up and indexes a task entry that has already been removed, throwingNoSuchElementException.For example, consider a 1,000-byte pool:
This interleaving is reproducible through Spark's
MemoryConsumerandTaskMemoryManagerAPIs in both memory modes; it does not require an external execution engine. It requires concurrent memory operations within the same task. The tests reproduce the allocator/API schedule, not an end-to-end SQL or Python query failure.Tracks SPARK-59444.
What changes were proposed in this pull request?
Keep a task registered until its waiting acquisitions have finished, even if it temporarily owns zero bytes. After B releases 300 bytes in the example, A can acquire its requested 300 bytes normally.
The pool records a waiter only when an acquisition first needs to wait. All updates use the existing memory-manager monitor. Multiple waiters still count as one task for fairness, and a
finallyblock removes each waiter on success, interruption, or an exception. When the last waiter leaves, an empty task entry is removed and other contenders are notified; a nonempty reservation remains charged.The waiter map is allocated lazily and discarded when empty. Non-waiting acquisitions do not access it. The fair-share limits, storage-reclamation callbacks, and lock ordering remain unchanged. The release-all documentation now distinguishes freeing currently reserved bytes from canceling outstanding acquisitions.
How was this patch tested?
Built and tested against Apache Spark master
80479fa48a25a28519456e5707b818f66c5d3f02, using JDK 21:42 tests passed: all 18 new regression cases and 24 existing unified-memory tests. One existing unified-memory test was canceled by its Apple Silicon platform guard.
The new suite covers last-byte release, release-all, multiple waiters, partial release, interruption, callback failure after waiting, and two public memory consumers sharing one task manager. Every case runs in both on-heap and off-heap mode. Worker waits and cleanup are bounded.
As a negative control, I compiled the unmodified master
ExecutionMemoryPoolseparately and ran the new suite against it, using the same freshly built master dependencies. 16 cases failed and the two partial-release controls passed. The failures detect the removed task entry or stale zero-byte fairness participation. The fixed allocator passed all 18 cases. This control did not change the reviewed checkout.Does this PR introduce any user-facing change?
Yes: the concurrent release/wait schedule described above no longer fails the memory allocation. There is no API or configuration change.
Was this patch authored or co-authored using generative AI tooling?
Generated-by: OpenAI Codex (tool version not recorded).
Codex assisted with implementation, tests, review, and this description.