jerrypeng commented on code in PR #59523:
URL: https://github.com/apache/spark/pull/59523#discussion_r4429446712


##########
sql/core/src/main/scala/org/apache/spark/sql/execution/exchange/EnablePipelinedShuffle.scala:
##########
@@ -127,24 +131,26 @@ object EnablePipelinedShuffle extends Rule[SparkPlan] {
    * True if any [[ShuffleExchangeExec]] in `plan` is read by an operator the 
channel transport
    * cannot serve. The unsupported operators (see class doc for why each is 
fatal) are
    * `CoalesceExec`, `CartesianProductExec`, and the limit operators 
`CollectLimitExec` /
-   * `CollectTailExec` / `TakeOrderedAndProjectExec`. For each such operator 
anywhere in the plan,
-   * check whether a shuffle is reachable below it.
-   *
-   * The reachability walk descends through EVERY child of a non-exchange node 
-- not only unary
-   * children -- so a shuffle behind a `UnionExec`/join (a `BinaryExecNode`) 
beneath the operator
-   * is still found. It stops at the FIRST [[ShuffleExchangeExec]] on each 
path: a shuffle deeper
-   * than that first one is not read by this operator (the intervening 
exchange's own reader reads
-   * one reduce partition per task), so it is not this operator's concern.
+   * `CollectTailExec` / `TakeOrderedAndProjectExec`, plus cached 
`AttachDistributedSequenceExec`.
+   * A shuffle above an unsupported operator with shuffle-free input does not 
disqualify the plan.
    */
-  private def readsShuffleThroughUnsupportedConsumer(plan: SparkPlan): Boolean 
= {
-    def reachesShuffle(p: SparkPlan): Boolean = p match {
-      case _: ShuffleExchangeExec => true
-      case other => other.children.exists(reachesShuffle)
-    }
-    plan.exists {
-      case p if PipelinedShuffleEligibility.isUnsupportedConsumer(p) =>
-        p.children.exists(reachesShuffle)
-      case _ => false
+  private[exchange] def readsShuffleThroughUnsupportedConsumer(plan: 
SparkPlan): Boolean = {

Review Comment:
   Agreed that the captured mutable flag and manual iterator added unnecessary 
complexity. I replaced them with a top-down traversal using `children.exists` 
and an immutable flag indicating an unsupported ancestor on the current path. 
Reaching a shuffle with that flag set returns true; sibling branches keep 
independent state.
   
   This preserves early exit and linear traversal work. I retained the semantic 
tests and reduced the counted-work grid to one depth-128 regression. That test 
guards against repeated subtree scans; it does not establish a measured 
planning-latency improvement.



-- 
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]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to