Skip to content

Commit cd99450

Browse files
taiyang-liAimeliyang.127
authored
[GLUTEN-12465][CORE] Support optional stage InputStats plumbing in scan/input-iterator transformers (#12433)
* [GLUTEN][CORE] Support optional stage InputStats plumbing in scan/input-iterator transformers Introduce an opt-in framework to pass stage input statistics (scan / shuffle / broadcast) to the native engine as estimated row-size hints. - Add InputStats / InputStatsKind / ShuffleStageWrapper and ApplyStageInputStatsRule. - Add RelNode.childNode() with implementations across all rel nodes; carry rowSize / inputStats on ReadRelNode and InputIteratorRelNode; expose PlanNode.getRelNodes() and AdvancedExtensionNode optimization/enhancement getters. - Add BasicScanExecTransformer.getInputStats hook and optional inputStats field on FileSourceScanExecTransformer; thread wsContext through genFirstStageIterator and the whole-stage RDDs; inject shuffle/broadcast stats in InputIteratorTransformer. - Gate everything behind spark.gluten.sql.enablePassStageInputStats (default false), so velox / clickhouse behavior is unchanged. Generated-by: TraeCli openrouter-3o Co-Authored-By: Aime <aime@bytedance.com> Change-Id: I7cd0a5abc98b6c41857230131513bfcb5ec6bf95 * change as request --------- Co-authored-by: Aime <aime@bytedance.com> Co-authored-by: liyang.127 <liyang.127@bytedance.com>
1 parent 4017ec9 commit cd99450

31 files changed

Lines changed: 532 additions & 14 deletions

backends-clickhouse/src/main/scala/org/apache/gluten/backendsapi/clickhouse/CHIteratorApi.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -277,7 +277,8 @@ class CHIteratorApi extends IteratorApi with Logging with LogLevelUtil {
277277
updateNativeMetrics: IMetrics => Unit,
278278
partitionIndex: Int,
279279
inputIterators: Seq[Iterator[ColumnarBatch]] = Seq(),
280-
enableCudf: Boolean = false
280+
enableCudf: Boolean = false,
281+
wsContext: WholeStageTransformContext = null
281282
): Iterator[ColumnarBatch] = {
282283

283284
require(

backends-velox/src/main/scala/org/apache/gluten/backendsapi/velox/VeloxIteratorApi.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,8 @@ class VeloxIteratorApi extends IteratorApi with Logging {
190190
updateNativeMetrics: IMetrics => Unit,
191191
partitionIndex: Int,
192192
inputIterators: Seq[Iterator[ColumnarBatch]] = Seq(),
193-
enableCudf: Boolean = false): Iterator[ColumnarBatch] = {
193+
enableCudf: Boolean = false,
194+
wsContext: WholeStageTransformContext = null): Iterator[ColumnarBatch] = {
194195
assert(
195196
inputPartition.isInstanceOf[GlutenPartition],
196197
"Velox backend only accept GlutenPartition.")
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
package org.apache.spark.sql.execution.adaptive
18+
19+
import org.apache.spark.MapOutputStatistics
20+
import org.apache.spark.internal.Logging
21+
import org.apache.spark.sql.catalyst.trees.TreeNodeTag
22+
import org.apache.spark.sql.execution.SparkPlan
23+
import org.apache.spark.sql.execution.exchange.ENSURE_REQUIREMENTS
24+
25+
/**
26+
* Represents stage input stats, eg scan or shuffle
27+
*
28+
* @param known
29+
* @param sizeInBytes
30+
* @param rowCount
31+
* @param bytesByPartitionId
32+
*/
33+
sealed trait InputStatsKind
34+
case object ScanInputStats extends InputStatsKind
35+
case object BroadcastStats extends InputStatsKind
36+
case object ShuffleStats extends InputStatsKind
37+
case object UnknownStats extends InputStatsKind
38+
case class InputStats(
39+
known: Boolean,
40+
sizeInBytes: BigInt,
41+
rowCount: BigInt,
42+
bytesByPartitionId: Array[Long],
43+
inputStatsKind: InputStatsKind)
44+
extends Serializable {
45+
override def toString: String = {
46+
s"known : ($known) sizeInBytes:($sizeInBytes), rowCount: ($rowCount), " +
47+
s"bytesByPartitionId: [${bytesByPartitionId.mkString(",")}], statsKind: $inputStatsKind"
48+
}
49+
}
50+
object ShuffleStageWrapper extends Logging {
51+
val INPUT_STATS: TreeNodeTag[java.util.List[InputStats]] = TreeNodeTag("InputStats")
52+
def unapply(plan: SparkPlan): Option[ShuffleQueryStageRuntimeStats] = plan match {
53+
case s: ShuffleQueryStageExec
54+
if s.isMaterialized && s.mapStats.isDefined &&
55+
s.shuffle.shuffleOrigin == ENSURE_REQUIREMENTS =>
56+
logInfo("hit InputIteratorTransformer ShuffleQueryStageExec with stats")
57+
Some(
58+
ShuffleQueryStageRuntimeStats(
59+
s.getRuntimeStatistics.sizeInBytes,
60+
s.getRuntimeStatistics.rowCount,
61+
s.mapStats))
62+
case a: AQEShuffleReadExec if a.child.isInstanceOf[ShuffleQueryStageExec] =>
63+
logInfo("hit InputIteratorTransformer AQEShuffleReadExec with stats")
64+
val queryStageExec = a.child.asInstanceOf[ShuffleQueryStageExec]
65+
Some(
66+
ShuffleQueryStageRuntimeStats(
67+
queryStageExec.getRuntimeStatistics.sizeInBytes,
68+
queryStageExec.getRuntimeStatistics.rowCount,
69+
queryStageExec.mapStats))
70+
case b: BroadcastQueryStageExec if b.isMaterialized =>
71+
logInfo("hit InputIteratorTransformer BroadcastQueryStageExec with stats")
72+
Some(
73+
ShuffleQueryStageRuntimeStats(
74+
b.getRuntimeStatistics.sizeInBytes,
75+
b.getRuntimeStatistics.rowCount,
76+
None))
77+
case _ => None
78+
}
79+
}
80+
case class ShuffleQueryStageRuntimeStats(
81+
sizeInBytes: BigInt,
82+
rowCount: Option[BigInt] = None,
83+
mapOutputStatistics: Option[MapOutputStatistics] = None)

gluten-substrait/src/main/java/org/apache/gluten/substrait/extensions/AdvancedExtensionNode.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,14 @@ public AdvancedExtensionNode(Any optimization, Any enhancement) {
4040
this.enhancement = enhancement;
4141
}
4242

43+
public Any getOptimization() {
44+
return optimization;
45+
}
46+
47+
public Any getEnhancement() {
48+
return enhancement;
49+
}
50+
4351
public AdvancedExtension toProtobuf() {
4452
AdvancedExtension.Builder extensionBuilder = AdvancedExtension.newBuilder();
4553
if (optimization != null) {

gluten-substrait/src/main/java/org/apache/gluten/substrait/plan/PlanNode.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,4 +77,8 @@ public Plan toProtobuf() {
7777
}
7878
return planBuilder.build();
7979
}
80+
81+
public List<RelNode> getRelNodes() {
82+
return relNodes;
83+
}
8084
}

gluten-substrait/src/main/java/org/apache/gluten/substrait/rel/AggregateRelNode.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626

2727
import java.io.Serializable;
2828
import java.util.ArrayList;
29+
import java.util.Collections;
2930
import java.util.List;
3031

3132
public class AggregateRelNode implements RelNode, Serializable {
@@ -83,4 +84,9 @@ public Rel toProtobuf() {
8384
builder.setAggregate(aggBuilder.build());
8485
return builder.build();
8586
}
87+
88+
@Override
89+
public List<RelNode> childNodes() {
90+
return Collections.singletonList(input);
91+
}
8692
}

gluten-substrait/src/main/java/org/apache/gluten/substrait/rel/CrossRelNode.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@
2424
import io.substrait.proto.RelCommon;
2525

2626
import java.io.Serializable;
27+
import java.util.ArrayList;
28+
import java.util.List;
2729

2830
public class CrossRelNode implements RelNode, Serializable {
2931
private final RelNode left;
@@ -69,4 +71,12 @@ public Rel toProtobuf() {
6971
}
7072
return Rel.newBuilder().setCross(crossRelBuilder.build()).build();
7173
}
74+
75+
@Override
76+
public List<RelNode> childNodes() {
77+
List<RelNode> children = new ArrayList<>();
78+
children.add(left);
79+
children.add(right);
80+
return children;
81+
}
7282
}

gluten-substrait/src/main/java/org/apache/gluten/substrait/rel/ExpandRelNode.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525

2626
import java.io.Serializable;
2727
import java.util.ArrayList;
28+
import java.util.Collections;
2829
import java.util.List;
2930

3031
public class ExpandRelNode implements RelNode, Serializable {
@@ -76,4 +77,9 @@ public Rel toProtobuf() {
7677
builder.setExpand(expandBuilder.build());
7778
return builder.build();
7879
}
80+
81+
@Override
82+
public List<RelNode> childNodes() {
83+
return Collections.singletonList(input);
84+
}
7985
}

gluten-substrait/src/main/java/org/apache/gluten/substrait/rel/FetchRelNode.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@
2323
import io.substrait.proto.RelCommon;
2424

2525
import java.io.Serializable;
26+
import java.util.Collections;
27+
import java.util.List;
2628

2729
public class FetchRelNode implements RelNode, Serializable {
2830
private final RelNode input;
@@ -66,4 +68,9 @@ public Rel toProtobuf() {
6668
relBuilder.setFetch(fetchRelBuilder.build());
6769
return relBuilder.build();
6870
}
71+
72+
@Override
73+
public List<RelNode> childNodes() {
74+
return Collections.singletonList(input);
75+
}
6976
}

gluten-substrait/src/main/java/org/apache/gluten/substrait/rel/FilterRelNode.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@
2424
import io.substrait.proto.RelCommon;
2525

2626
import java.io.Serializable;
27+
import java.util.Collections;
28+
import java.util.List;
2729

2830
public class FilterRelNode implements RelNode, Serializable {
2931
private final RelNode input;
@@ -60,4 +62,9 @@ public Rel toProtobuf() {
6062
builder.setFilter(filterBuilder.build());
6163
return builder.build();
6264
}
65+
66+
@Override
67+
public List<RelNode> childNodes() {
68+
return Collections.singletonList(input);
69+
}
6370
}

0 commit comments

Comments
 (0)