[ 
https://issues.apache.org/jira/browse/SPARK-59261?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=18111676#comment-18111676
 ] 

Peter Toth commented on SPARK-59261:
------------------------------------

I'm working on this.

> Memoize outputPartitioning on the projection and SPJ grouping nodes
> -------------------------------------------------------------------
>
>                 Key: SPARK-59261
>                 URL: https://issues.apache.org/jira/browse/SPARK-59261
>             Project: Spark
>          Issue Type: Improvement
>          Components: SQL
>    Affects Versions: 5.0.0
>            Reporter: Peter Toth
>            Priority: Major
>
> h2. Problem
> Two physical nodes recompute {{outputPartitioning}} on every call, and the 
> planner asks for it many times per node. Both do real work in the body and 
> both read only values fixed for the instance.
> Counted by instrumenting the bodies and running 
> {{KeyGroupedPartitioningSuite}}, each measured with the previous change 
> applied:
> || node || body executions as {{def}} || as {{lazy val}} ||
> | {{PartitioningPreservingUnaryExecNode.outputPartitioning}} 
> ({{sql/core/src/main/scala/org/apache/spark/sql/execution/AliasAwareOutputExpression.scala}})
>  | 23,512 | 3,663 |
> | {{GroupPartitionsExec.outputPartitioning}} 
> ({{sql/core/src/main/scala/org/apache/spark/sql/execution/datasources/v2/GroupPartitionsExec.scala}})
>  | 8,821 | 1,326 |
> h2. What the bodies cost
> {{PartitioningPreservingUnaryExecNode}} flattens and partitions the child's 
> partitioning, allocates an {{AttributeSet}} and an {{ExpressionSet}} per key 
> position, cross-products the per-position alternatives through {{LazyList}}s, 
> and calls {{kps.head.project(positions)}}, which walks all N partition keys 
> building a {{mutable.HashMap}} whenever a position is dropped. It is the 
> single biggest caller of the scan's {{outputPartitioning}}: 19,105 of that 
> method's 33,051 reads arrive through it, mostly as {{Project -> Filter -> 
> scan}}.
> {{GroupPartitionsExec}} rebuilds every {{KeyedPartitioning}} in the child's 
> partitioning through {{p.transform}}.
> h2. Why memoizing is sound
> The planner already treats {{outputPartitioning}} as a property of the node 
> rather than a question to re-ask. {{ValidateRequirements}} reads one child's 
> partitioning twice and compares specs built from the two reads. 
> {{EnsureRequirements}} reads it at five points and threads the results 
> between them, and at {{EnsureRequirements.scala:335}} it is the pruning 
> predicate of a {{multiTransformDownWithPruning}}, re-evaluated per generated 
> alternative, which is only sound if the answer is fixed.
> Neither node freezes a config it does not already freeze. 
> {{PartitioningPreservingUnaryExecNode}} reads {{child.outputPartitioning}}, 
> {{outputExpressions}} and {{aliasCandidateLimit}}, and that last one is 
> already a {{protected val}} read at construction. 
> {{GroupPartitionsExec.outputPartitioning}} reads {{child.outputPartitioning}} 
> and its own {{grouping}}, itself a {{lazy val}}, and no config at all.
> {{BroadcastHashJoinExec}}, {{AQEShuffleReadExec}} and {{FileSourceScanExec}} 
> already override {{outputPartitioning}} as a {{lazy val}}.
> {{PartitioningPreservingUnaryExecNode.outputPartitioning}} is {{final 
> override def}} today, so it becomes {{final override lazy val}}.
> h2. Not in scope
> {{GroupPartitionsExec.outputOrdering}} stays a {{def}}: it reads 
> {{conf.v2BucketingPreserveKeyOrderingOnCoalesceEnabled}}, so memoizing it 
> would freeze a config, which is a separate question from this one.
> h2. Context
> Split out of [SPARK-59252|https://issues.apache.org/jira/browse/SPARK-59252]. 
> That one turned out to fix a crash and needs backporting, so the two pure 
> performance changes were separated from it to keep the bugfix minimal.



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

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

Reply via email to