Skip to content

[CORE] Share taskIdMapsForShuffle between ColumnarShuffleManager and its block resolver - #13072

Open
acvictor wants to merge 2 commits into
apache:mainfrom
acvictor:acvictor/csmShareTaskIdMaps
Open

acvictor wants to merge 2 commits into
apache:mainfrom
acvictor:acvictor/csmShareTaskIdMaps

Conversation

@acvictor

Copy link
Copy Markdown
Contributor

What changes are proposed in this pull request?

ColumnarShuffleManager built its IndexShuffleBlockResolver with the single-arg constructor, so the resolver allocated its own taskIdMapsForShuffle while the manager kept a second, separate map. The resolver records blocks migrated in during executor decommissioning into its map, but unregisterShuffle reads the manager's map to delete map output. With two maps, migrated blocks were recorded where nothing read them, so their files were never deleted and leaked disk on decommissioned executors. Spark wires a single shared map in SortShuffleManager.

taskIdMapsForShuffle is now declared before shuffleBlockResolver -- order matters, since Scala initializes vals in declaration order and the previous ordering would capture null -- and passed to the resolver. unregisterShuffle now iterates under mapTaskIds.synchronized, matching Spark, because the block-migration path mutates the same set under that lock. stop() now defers to super.stop(), which stops the resolver.

Adds a ColumnarShuffleManagerSuite case that inserts an entry through the resolver's map and asserts unregisterShuffle clears it, which fails if the two maps are ever unshared again.

How was this patch tested?

UT

Was this patch authored or co-authored using generative AI tooling?

Co-authored by GitHub Copilot CLI 1.0.86

…its block resolver

## Summary
ColumnarShuffleManager built its IndexShuffleBlockResolver with the single-arg
constructor, so the resolver allocated its own taskIdMapsForShuffle while the
manager kept a second, separate map. The resolver records blocks migrated in
during executor decommissioning into its map, but unregisterShuffle reads the
manager's map to delete map output. With two maps, migrated blocks were
recorded where nothing read them, so their files were never deleted and leaked
disk on decommissioned executors. Spark wires a single shared map in
SortShuffleManager.

taskIdMapsForShuffle is now declared before shuffleBlockResolver -- order
matters, since Scala initializes vals in declaration order and the previous
ordering would capture null -- and passed to the resolver. unregisterShuffle
now iterates under mapTaskIds.synchronized, matching Spark, because the
block-migration path mutates the same set under that lock. stop() now defers to
super.stop(), which stops the resolver.

Adds a ColumnarShuffleManagerSuite case that inserts an entry through the
resolver's map and asserts unregisterShuffle clears it, which fails if the two
maps are ever unshared again.

## Prompting Intent
Follow-up to the ColumnarShuffleManager work merged in apache#13039, which extended
SortShuffleManager to restore Spark's zero-copy row-based write path. That
change landed only the first of two related parity fixes; the engineer asked to
port the second one. Instructed to keep the change limited to what applies
upstream.

## Rationale
The resolver argument is passed positionally rather than by name. Spark 3.4 and
3.5 default both _blockManager and taskIdMapsForShuffle, so a named argument
compiles there, but Spark 4.0 and 4.1 declare _blockManager with no default and
a named-only call would not compile. The positional form satisfies every Spark
version Gluten builds against (3.4, 3.5, 4.0, 4.1), so no shim is needed;
ConcurrentHashMap conforms to both the java.util.Map parameter type used
through 4.0 and the java.util.concurrent.ConcurrentMap type used in 4.1.

Keeping the manager's own map and instead teaching unregisterShuffle to also
drain the resolver's map was rejected: it would leave two sources of truth and
diverge further from SortShuffleManager, which is the behaviour this class is
meant to match.

The test asserts the sharing through public behaviour rather than reference
identity, so it still holds if the wiring is later expressed differently.
@github-actions github-actions Bot added the CORE works for Gluten Core label Sep 21, 2026
@github-actions

Copy link
Copy Markdown

Run Gluten Clickhouse CI on x86

@acvictor
acvictor marked this pull request as ready for review September 21, 2026 13:12
Copilot AI lite review requested due to automatic review settings September 21, 2026 13:12

Copilot AI 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.

Copilot encountered an error: Your billing is not configured or you have Copilot licenses from multiple standalone organizations or enterprises. To use premium requests, select a billing entity via the GitHub site, under Settings > Copilot > Features.

Copilot AI 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.

Copilot review overview

🟡 Changes recommended

The three-argument resolver constructor is unavailable in Spark 3.4/3.5 profiles, causing compilation failures.

Get a fresh assessment by requesting another Copilot review.

Review effort: Lite
Findings: 1 High severity

Open (1)

Copilot AI review requested due to automatic review settings September 22, 2026 10:43
@github-actions

Copy link
Copy Markdown

Run Gluten Clickhouse CI on x86

Copilot AI 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.

Copilot review overview

🔵 Needs a closer look

The new resolver constructor is incompatible with supported Spark 3.4/3.5 profiles.

Review effort: Lite
Findings: None

Resolved since last review (1)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CORE works for Gluten Core

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants