@@ -7,6 +7,7 @@ use std::sync::Arc;
77
88use flatbuffers:: Follow ;
99use itertools:: Itertools ;
10+ use once_cell:: sync:: OnceCell ;
1011use vortex_array:: dtype:: DType ;
1112use vortex_error:: VortexResult ;
1213use vortex_error:: vortex_bail;
@@ -105,6 +106,7 @@ pub(crate) struct ViewedLayoutChildren {
105106 layout_read_ctx : ReadContext ,
106107 layouts : LayoutRegistry ,
107108 allow_unknown : bool ,
109+ cache : Arc < [ OnceCell < LayoutRef > ] > ,
108110}
109111
110112impl ViewedLayoutChildren {
@@ -121,13 +123,22 @@ impl ViewedLayoutChildren {
121123 layouts : LayoutRegistry ,
122124 allow_unknown : bool ,
123125 ) -> Self {
126+ // SAFETY: guaranteed by caller
127+ let nchildren = unsafe {
128+ fbl:: Layout :: follow ( flatbuffer. as_ref ( ) , flatbuffer_loc)
129+ . children ( )
130+ . unwrap_or_default ( )
131+ . len ( )
132+ } ;
133+ let cache = vec ! [ OnceCell :: new( ) ; nchildren] . into_boxed_slice ( ) . into ( ) ;
124134 Self {
125135 flatbuffer,
126136 flatbuffer_loc,
127137 array_read_ctx,
128138 layout_read_ctx,
129139 layouts,
130140 allow_unknown,
141+ cache,
131142 }
132143 }
133144
@@ -181,50 +192,58 @@ impl LayoutChildren for ViewedLayoutChildren {
181192 }
182193
183194 fn child ( & self , idx : usize , dtype : & DType ) -> VortexResult < LayoutRef > {
184- if idx >= self . nchildren ( ) {
185- vortex_bail ! ( "Child index out of bounds: {} of {}" , idx, self . nchildren ( ) ) ;
195+ if idx >= self . cache . len ( ) {
196+ vortex_bail ! ( "Child index out of bounds: {} of {}" , idx, self . cache . len ( ) ) ;
186197 }
187- let fb_child = self . flatbuffer ( ) . children ( ) . unwrap_or_default ( ) . get ( idx) ;
188-
189- let viewed_children = ViewedLayoutChildren {
190- flatbuffer : self . flatbuffer . clone ( ) ,
191- flatbuffer_loc : fb_child. _tab . loc ( ) ,
192- array_read_ctx : self . array_read_ctx . clone ( ) ,
193- layout_read_ctx : self . layout_read_ctx . clone ( ) ,
194- layouts : self . layouts . clone ( ) ,
195- allow_unknown : self . allow_unknown ,
196- } ;
197198
198- let encoding_id = self
199- . layout_read_ctx
200- . resolve ( fb_child. encoding ( ) )
201- . ok_or_else ( || vortex_err ! ( "Encoding not found: {}" , fb_child. encoding( ) ) ) ?;
202- let Some ( encoding) = self . layouts . find ( & encoding_id) else {
203- if self . allow_unknown {
204- return viewed_children. foreign_layout_from_fb ( fb_child, dtype) ;
205- }
206- return Err ( vortex_err ! (
207- "Encoding not found in registry: {}" ,
208- fb_child. encoding( )
209- ) ) ;
210- } ;
199+ let layout_ref = self . cache [ idx] . get_or_try_init ( || {
200+ let fb_child = self . flatbuffer ( ) . children ( ) . unwrap_or_default ( ) . get ( idx) ;
211201
212- encoding. build (
213- dtype,
214- fb_child. row_count ( ) ,
215- fb_child
216- . metadata ( )
217- . map ( |m| m. bytes ( ) )
218- . unwrap_or_else ( || & [ ] ) ,
219- fb_child
220- . segments ( )
221- . unwrap_or_default ( )
222- . iter ( )
223- . map ( SegmentId :: from)
224- . collect_vec ( ) ,
225- & viewed_children,
226- & self . array_read_ctx ,
227- )
202+ // SAFETY: same validated flatbuffer; fb_child._tab.loc() is a valid offset
203+ // We need this to avoid re-initializing cache here
204+ let viewed_children = unsafe {
205+ ViewedLayoutChildren :: new_unchecked (
206+ self . flatbuffer . clone ( ) ,
207+ fb_child. _tab . loc ( ) ,
208+ self . array_read_ctx . clone ( ) ,
209+ self . layout_read_ctx . clone ( ) ,
210+ self . layouts . clone ( ) ,
211+ self . allow_unknown ,
212+ )
213+ } ;
214+
215+ let encoding_id = self
216+ . layout_read_ctx
217+ . resolve ( fb_child. encoding ( ) )
218+ . ok_or_else ( || vortex_err ! ( "Encoding not found: {}" , fb_child. encoding( ) ) ) ?;
219+ let Some ( encoding) = self . layouts . find ( & encoding_id) else {
220+ if self . allow_unknown {
221+ return viewed_children. foreign_layout_from_fb ( fb_child, dtype) ;
222+ }
223+ return Err ( vortex_err ! (
224+ "Encoding not found in registry: {}" ,
225+ fb_child. encoding( )
226+ ) ) ;
227+ } ;
228+
229+ encoding. build (
230+ dtype,
231+ fb_child. row_count ( ) ,
232+ fb_child
233+ . metadata ( )
234+ . map ( |m| m. bytes ( ) )
235+ . unwrap_or_else ( || & [ ] ) ,
236+ fb_child
237+ . segments ( )
238+ . unwrap_or_default ( )
239+ . iter ( )
240+ . map ( SegmentId :: from)
241+ . collect_vec ( ) ,
242+ & viewed_children,
243+ & self . array_read_ctx ,
244+ )
245+ } ) ?;
246+ Ok ( Arc :: clone ( layout_ref) )
228247 }
229248
230249 fn child_row_count ( & self , idx : usize ) -> u64 {
0 commit comments