cloud-fan commented on code in PR #59758:
URL: https://github.com/apache/spark/pull/59758#discussion_r4366321426


##########
sql/core/src/main/scala/org/apache/spark/sql/execution/aggregate/HashAggregateExec.scala:
##########
@@ -918,11 +918,22 @@ case class HashAggregateExec(
     // For adaptive partial aggregation pass-through, each bypassed row is 
emitted as a single-row
     // partial buffer: start from the initial aggregation buffer, apply the 
update expressions once,
     // and output `key ++ buffer` for the Final aggregate to merge. This 
projects the initial
-    // buffer.
-    val emptyAggBufferCode = if (adaptivePartialAggEnabled) {
-      GenerateUnsafeProjection.createCode(ctx, declFunctions.flatMap(f => 
f.initialValues))
+    // buffer, in its own method: the projection's code grows with the number 
of buffer slots, and
+    // inlining it into the per-row consume method could push a wide 
aggregation's consume method
+    // past the JIT's huge-method limit.
+    val makeEmptyAggBufferFunc = if (adaptivePartialAggEnabled) {
+      val emptyAggBufferCode =

Review Comment:
   Done in bbf464a. The initial buffer is now built once per task, and each 
passed-through row resets a reusable copy with `copyFrom`, as 
`TungstenAggregationIterator` does. `makeEmptyAggBuffer` is gone.
   



##########
sql/core/src/main/scala/org/apache/spark/sql/execution/aggregate/HashAggregateExec.scala:
##########
@@ -918,11 +918,22 @@ case class HashAggregateExec(
     // For adaptive partial aggregation pass-through, each bypassed row is 
emitted as a single-row
     // partial buffer: start from the initial aggregation buffer, apply the 
update expressions once,
     // and output `key ++ buffer` for the Final aggregate to merge. This 
projects the initial
-    // buffer.
-    val emptyAggBufferCode = if (adaptivePartialAggEnabled) {
-      GenerateUnsafeProjection.createCode(ctx, declFunctions.flatMap(f => 
f.initialValues))
+    // buffer, in its own method: the projection's code grows with the number 
of buffer slots, and
+    // inlining it into the per-row consume method could push a wide 
aggregation's consume method
+    // past the JIT's huge-method limit.
+    val makeEmptyAggBufferFunc = if (adaptivePartialAggEnabled) {
+      val emptyAggBufferCode =
+        GenerateUnsafeProjection.createCode(ctx, declFunctions.flatMap(f => 
f.initialValues))

Review Comment:
   Fixed by the change for item 1: the reset is now a single `copyFrom` call, 
so none of the generated code grows with the number of buffer slots.
   



##########
sql/core/src/main/scala/org/apache/spark/sql/execution/aggregate/HashAggregateExec.scala:
##########
@@ -918,11 +918,22 @@ case class HashAggregateExec(
     // For adaptive partial aggregation pass-through, each bypassed row is 
emitted as a single-row
     // partial buffer: start from the initial aggregation buffer, apply the 
update expressions once,
     // and output `key ++ buffer` for the Final aggregate to merge. This 
projects the initial
-    // buffer.
-    val emptyAggBufferCode = if (adaptivePartialAggEnabled) {
-      GenerateUnsafeProjection.createCode(ctx, declFunctions.flatMap(f => 
f.initialValues))
+    // buffer, in its own method: the projection's code grows with the number 
of buffer slots, and
+    // inlining it into the per-row consume method could push a wide 
aggregation's consume method
+    // past the JIT's huge-method limit.
+    val makeEmptyAggBufferFunc = if (adaptivePartialAggEnabled) {
+      val emptyAggBufferCode =
+        GenerateUnsafeProjection.createCode(ctx, declFunctions.flatMap(f => 
f.initialValues))
+      val makeEmptyAggBuffer = ctx.freshName("makeEmptyAggBuffer")

Review Comment:
   Done in bbf464a. Both buffers are registered in `doProduceWithKeys`, so the 
children of a fused Union share them. Each child's consume code keeps only its 
own one-line `copyFrom` call.
   



##########
sql/core/src/main/scala/org/apache/spark/sql/execution/aggregate/HashAggregateExec.scala:
##########
@@ -918,11 +918,22 @@ case class HashAggregateExec(
     // For adaptive partial aggregation pass-through, each bypassed row is 
emitted as a single-row
     // partial buffer: start from the initial aggregation buffer, apply the 
update expressions once,
     // and output `key ++ buffer` for the Final aggregate to merge. This 
projects the initial
-    // buffer.
-    val emptyAggBufferCode = if (adaptivePartialAggEnabled) {
-      GenerateUnsafeProjection.createCode(ctx, declFunctions.flatMap(f => 
f.initialValues))
+    // buffer, in its own method: the projection's code grows with the number 
of buffer slots, and
+    // inlining it into the per-row consume method could push a wide 
aggregation's consume method
+    // past the JIT's huge-method limit.
+    val makeEmptyAggBufferFunc = if (adaptivePartialAggEnabled) {
+      val emptyAggBufferCode =
+        GenerateUnsafeProjection.createCode(ctx, declFunctions.flatMap(f => 
f.initialValues))
+      val makeEmptyAggBuffer = ctx.freshName("makeEmptyAggBuffer")
+      ctx.addNewFunction(makeEmptyAggBuffer,

Review Comment:
   Added `pass-through resets its buffer with copyFrom from buffers registered 
once`. It checks the generated code of an aggregate over a fused two-child 
Union: each child resets the buffer with `copyFrom`, and both use the same 
buffers.
   



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