[
https://issues.apache.org/jira/browse/SPARK-59558?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
Wenchen Fan resolved SPARK-59558.
---------------------------------
Fix Version/s: 4.4.0
Resolution: Fixed
Issue resolved by pull request 58844
[https://github.com/apache/spark/pull/58844]
> Use ArrayDeque instead of LinkedList for the whole-stage codegen row buffer
> ---------------------------------------------------------------------------
>
> Key: SPARK-59558
> URL: https://issues.apache.org/jira/browse/SPARK-59558
> Project: Spark
> Issue Type: Improvement
> Components: SQL
> Affects Versions: 4.1.0
> Reporter: David Mollitor
> Assignee: David Mollitor
> Priority: Trivial
> Labels: pull-request-available
> Fix For: 4.4.0
>
>
> h2. Summary
> {{BufferedRowIterator.currentRows}} is the output buffer for whole-stage
> codegen: every generated iterator ({{GeneratedIteratorForCodegenStageN
> extends BufferedRowIterator}}) pushes its output rows into it. It is declared
> as a {{java.util.LinkedList<InternalRow>}} and used purely as a FIFO queue:
> * {{append(row)}} -> {{currentRows.add(row)}}
> * {{next()}} -> {{currentRows.remove()}}
> * {{hasNext()}} / {{shouldStop()}} -> {{currentRows.isEmpty()}}
> Because {{shouldStop()}} returns as soon as the buffer is non-empty, the
> steady-state pattern is "append one row, poll one row" per output row, so
> {{LinkedList}} allocates and discards one {{LinkedList$Node}} for every row
> every codegen pipeline emits.
> This changes the field to a {{java.util.ArrayDeque}} (referenced through the
> {{Queue}}
> interface). {{ArrayDeque}} allocates its backing array once and reuses it
> across add/remove, eliminating the per-row node allocation, with better cache
> locality. Its JavaDoc notes it is "likely to be faster than {{LinkedList}}
> when used as a queue."
> h2. Why
> JFR allocation profiling of {{JoinBenchmark}} showed
> {{java.util.LinkedList.linkLast}} as a significant allocation site on the
> codegen output path -- ~25% of sampled allocation across the full suite
> (amplified by high-fan-out operators), and ~4.8% in a focused duplicated
> broadcast-hash-join case. This is per-row garbage on the path shared by
> essentially every query that uses whole-stage codegen, so removing it reduces
> GC pressure fleet-wide.
--
This message was sent by Atlassian Jira
(v8.20.10#820010)
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]