Is your feature request related to a problem or challenge? Please describe what you are trying to do.
Follow up to #10141, which made RowSelection optionally backed by a BooleanBuffer bitmap.
For mask-backed selections, RowSelection::iter() lazily materializes an RLE selector cache inside MaskSelection (a OnceLock<Vec<RowSelector>>). However, RowSelection::into_selectors_vec() (used by From<RowSelection> for Vec<RowSelector> and From<RowSelection> for VecDeque<RowSelector>) ignores that cache and calls mask_to_selectors() a second time. selectors_mut() has the same issue when promoting a mask-backed selection to selector backing in place.
This means a caller that first iterates a selection and then consumes it converts the entire bitmap to RLE twice. DataFusion's ParquetAccessPlan::into_overall_row_selection does exactly this sequence: it calls iter() for validation and then converts the selection into selectors.
Originally reported by @hhhizzz in #10141 (comment)
Describe the solution you'd like
When the lazy cache has already been populated, consume it instead of re-running the conversion, e.g. take the OnceLock's value in into_selectors_vec() / selectors_mut() (OnceLock::into_inner / OnceLock::take) and fall back to mask_to_selectors() only when the cache is empty.
Describe alternatives you've considered
Leave as is — the conversion is O(bitmap) either way, but doing it twice is pure waste for large selections.
Additional context
Per review feedback on #10141, this should land with benchmark coverage, e.g. extending parquet/benches/row_selection_cursor.rs with an "iterate-then-consume" scenario over a mask-backed selection (cargo bench -p parquet --bench row_selection_cursor).
Is your feature request related to a problem or challenge? Please describe what you are trying to do.
Follow up to #10141, which made
RowSelectionoptionally backed by aBooleanBufferbitmap.For mask-backed selections,
RowSelection::iter()lazily materializes an RLE selector cache insideMaskSelection(aOnceLock<Vec<RowSelector>>). However,RowSelection::into_selectors_vec()(used byFrom<RowSelection> for Vec<RowSelector>andFrom<RowSelection> for VecDeque<RowSelector>) ignores that cache and callsmask_to_selectors()a second time.selectors_mut()has the same issue when promoting a mask-backed selection to selector backing in place.This means a caller that first iterates a selection and then consumes it converts the entire bitmap to RLE twice. DataFusion's
ParquetAccessPlan::into_overall_row_selectiondoes exactly this sequence: it callsiter()for validation and then converts the selection into selectors.Originally reported by @hhhizzz in #10141 (comment)
Describe the solution you'd like
When the lazy cache has already been populated, consume it instead of re-running the conversion, e.g. take the
OnceLock's value ininto_selectors_vec()/selectors_mut()(OnceLock::into_inner/OnceLock::take) and fall back tomask_to_selectors()only when the cache is empty.Describe alternatives you've considered
Leave as is — the conversion is O(bitmap) either way, but doing it twice is pure waste for large selections.
Additional context
Per review feedback on #10141, this should land with benchmark coverage, e.g. extending
parquet/benches/row_selection_cursor.rswith an "iterate-then-consume" scenario over a mask-backed selection (cargo bench -p parquet --bench row_selection_cursor).