22// SPDX-FileCopyrightText: Copyright the Vortex contributors
33
44use std:: sync:: Arc ;
5- use std:: sync:: atomic:: AtomicU64 ;
6- use std:: sync:: atomic:: Ordering ;
75
86use arrow_array:: ArrayRef as ArrowArrayRef ;
97use arrow_array:: GenericListArray ;
@@ -19,6 +17,7 @@ use crate::ArrayRef;
1917use crate :: Canonical ;
2018use crate :: DynArray ;
2119use crate :: ExecutionCtx ;
20+ use crate :: arrays:: Chunked ;
2221use crate :: arrays:: List ;
2322use crate :: arrays:: ListArray ;
2423use crate :: arrays:: ListView ;
@@ -33,31 +32,6 @@ use crate::dtype::NativePType;
3332use crate :: dtype:: Nullability ;
3433use crate :: vtable:: ValidityHelper ;
3534
36- static LIST_TO_LIST_COUNT : AtomicU64 = AtomicU64 :: new ( 0 ) ;
37- static LIST_VIEW_ZCTL_COUNT : AtomicU64 = AtomicU64 :: new ( 0 ) ;
38- static EXECUTE_LIST_VIEW_COUNT : AtomicU64 = AtomicU64 :: new ( 0 ) ;
39-
40- #[ derive( Debug , Clone , Copy , Default ) ]
41- pub struct ListArrowPathCounters {
42- pub list_to_list : u64 ,
43- pub list_view_zctl : u64 ,
44- pub execute_list_view : u64 ,
45- }
46-
47- pub ( crate ) fn reset_list_arrow_path_counters ( ) {
48- LIST_TO_LIST_COUNT . store ( 0 , Ordering :: Relaxed ) ;
49- LIST_VIEW_ZCTL_COUNT . store ( 0 , Ordering :: Relaxed ) ;
50- EXECUTE_LIST_VIEW_COUNT . store ( 0 , Ordering :: Relaxed ) ;
51- }
52-
53- pub ( crate ) fn list_arrow_path_counters ( ) -> ListArrowPathCounters {
54- ListArrowPathCounters {
55- list_to_list : LIST_TO_LIST_COUNT . load ( Ordering :: Relaxed ) ,
56- list_view_zctl : LIST_VIEW_ZCTL_COUNT . load ( Ordering :: Relaxed ) ,
57- execute_list_view : EXECUTE_LIST_VIEW_COUNT . load ( Ordering :: Relaxed ) ,
58- }
59- }
60-
6135/// Convert a Vortex array into an Arrow GenericBinaryArray.
6236pub ( super ) fn to_arrow_list < O : OffsetSizeTrait + NativePType > (
6337 array : ArrayRef ,
@@ -66,14 +40,12 @@ pub(super) fn to_arrow_list<O: OffsetSizeTrait + NativePType>(
6640) -> VortexResult < ArrowArrayRef > {
6741 // If the Vortex array is already in List format, we can directly convert it.
6842 if let Some ( array) = array. as_opt :: < List > ( ) {
69- LIST_TO_LIST_COUNT . fetch_add ( 1 , Ordering :: Relaxed ) ;
7043 return list_to_list :: < O > ( array, elements_field, ctx) ;
7144 }
7245
7346 // If the Vortex array is a ListViewArray, rebuild to ZCTL if needed and convert.
7447 let array = match array. try_into :: < ListView > ( ) {
7548 Ok ( array) => {
76- LIST_VIEW_ZCTL_COUNT . fetch_add ( 1 , Ordering :: Relaxed ) ;
7749 let zctl = if array. is_zero_copy_to_list ( ) {
7850 array
7951 } else {
@@ -84,18 +56,34 @@ pub(super) fn to_arrow_list<O: OffsetSizeTrait + NativePType>(
8456 Err ( a) => a,
8557 } ;
8658
59+ // Handle ChunkedArray by converting each chunk individually.
60+ // This preserves the fast list_to_list path for inner ListArray chunks
61+ // instead of falling through to the expensive execute::<ListViewArray> path.
62+ if let Some ( chunked) = array. as_opt :: < Chunked > ( ) {
63+ let mut arrow_chunks: Vec < ArrowArrayRef > = Vec :: with_capacity ( chunked. nchunks ( ) ) ;
64+ for chunk in chunked. chunks ( ) {
65+ arrow_chunks. push ( to_arrow_list :: < O > ( chunk. clone ( ) , elements_field, ctx) ?) ;
66+ }
67+ if arrow_chunks. len ( ) == 1 {
68+ return Ok ( arrow_chunks
69+ . into_iter ( )
70+ . next ( )
71+ . vortex_expect ( "known length" ) ) ;
72+ }
73+ let refs: Vec < & dyn arrow_array:: Array > = arrow_chunks. iter ( ) . map ( |a| a. as_ref ( ) ) . collect ( ) ;
74+ return Ok ( arrow_select:: concat:: concat ( & refs) ?) ;
75+ }
76+
8777 // Otherwise, we execute the array to become a ListViewArray, then rebuild to ZCTL.
8878 // Note: arrow_cast::cast supports ListView → List (apache/arrow-rs#8735), but it
8979 // unconditionally uses take. Our rebuild uses a heuristic that picks list-by-list
9080 // for large lists, which avoids materializing a large index buffer.
91- EXECUTE_LIST_VIEW_COUNT . fetch_add ( 1 , Ordering :: Relaxed ) ;
9281 let list_view = array. execute :: < ListViewArray > ( ctx) ?;
9382 let zctl = if list_view. is_zero_copy_to_list ( ) {
9483 list_view
9584 } else {
9685 list_view. rebuild ( ListViewRebuildMode :: MakeZeroCopyToList ) ?
9786 } ;
98- LIST_VIEW_ZCTL_COUNT . fetch_add ( 1 , Ordering :: Relaxed ) ;
9987 list_view_zctl :: < O > ( zctl, elements_field, ctx)
10088}
10189
0 commit comments