[ 
https://issues.apache.org/jira/browse/SPARK-59558?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Wenchen Fan reassigned SPARK-59558:
-----------------------------------

    Assignee: David Mollitor

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

Reply via email to