1212package org .eclipse .rdf4j .sail .lmdb ;
1313
1414import java .util .ArrayList ;
15+ import java .util .Arrays ;
1516import java .util .List ;
1617
1718import org .eclipse .rdf4j .common .iteration .CloseableIteration ;
@@ -64,9 +65,9 @@ private final class LmdbLftjIteration extends LookAheadIteration<BindingSet> {
6465 private final LmdbQueryAccess queryAccess ;
6566 private final LmdbLftjMetrics metrics ;
6667 private final LmdbPrefixFrontierProvider frontierProvider ;
67- private final List < String > searchVariables ;
68- private final List < LmdbLftjCursor > patternCursors ;
69- private final List < List < LmdbLftjCursor >> cursorsByDepth ;
68+ private final int [] searchSlots ;
69+ private final LmdbLftjCursor [] patternCursors ;
70+ private final DepthRuntime [] depthRuntimes ;
7071 private final boolean [] initializedDepths ;
7172 private final boolean [] advanceDepths ;
7273
@@ -82,11 +83,11 @@ private LmdbLftjIteration(LmdbLftjPlan plan, LmdbLftjBindingState state, QueryEv
8283 this .queryAccess = queryAccess ;
8384 this .metrics = metrics ;
8485 this .frontierProvider = new LmdbPrefixFrontierProvider (queryAccess , state , metrics );
85- this .searchVariables = collectSearchVariables (plan , state );
86+ this .searchSlots = collectSearchSlots (plan , state );
8687 this .patternCursors = createPatternCursors (plan , frontierProvider );
87- this .cursorsByDepth = createDepthCursors (plan , searchVariables , patternCursors );
88- this .initializedDepths = new boolean [searchVariables . size () ];
89- this .advanceDepths = new boolean [searchVariables . size () ];
88+ this .depthRuntimes = createDepthRuntimes (plan , searchSlots , patternCursors );
89+ this .initializedDepths = new boolean [searchSlots . length ];
90+ this .advanceDepths = new boolean [searchSlots . length ];
9091 this .depth = 0 ;
9192 }
9293
@@ -115,7 +116,7 @@ protected void handleClose() {
115116
116117 private BindingSet computeNextElement () {
117118 while (depth >= 0 ) {
118- if (depth == searchVariables . size () ) {
119+ if (depth == searchSlots . length ) {
119120 long multiplicity = witnessMultiplicity (plan , metrics , frontierProvider );
120121 backtrackAfterLeaf ();
121122 if (multiplicity > 0 ) {
@@ -155,22 +156,23 @@ private BindingSet computeNextElement() {
155156 }
156157
157158 private boolean positionDepth (int depth , boolean advanceExisting ) {
158- String variableName = searchVariables .get (depth );
159- List <LmdbLftjCursor > cursors = cursorsByDepth .get (depth );
160- state .clear (variableName );
159+ DepthRuntime depthRuntime = depthRuntimes [depth ];
160+ int bindingSlot = depthRuntime .bindingSlot ;
161+ LmdbLftjCursor [] cursors = depthRuntime .cursors ;
162+ state .clear (bindingSlot );
161163
162- if (cursors .isEmpty () ) {
164+ if (cursors .length == 0 ) {
163165 return false ;
164166 }
165167
166168 if (!advanceExisting ) {
167169 for (LmdbLftjCursor cursor : cursors ) {
168170 metrics .recordCandidateScan ();
169- if (!cursor .open (variableName )) {
171+ if (!cursor .open (bindingSlot )) {
170172 return false ;
171173 }
172174 }
173- } else if (!cursors . get ( 0 ) .next ()) {
175+ } else if (!cursors [ 0 ] .next ()) {
174176 return false ;
175177 }
176178
@@ -183,12 +185,12 @@ private boolean positionDepth(int depth, boolean advanceExisting) {
183185 return false ;
184186 }
185187
186- state .assign (variableName , current );
188+ state .assign (bindingSlot , current );
187189 return true ;
188190 }
189191
190192 private void backtrackAfterLeaf () {
191- depth = searchVariables . size () - 1 ;
193+ depth = searchSlots . length - 1 ;
192194 if (depth >= 0 ) {
193195 advanceDepths [depth ] = true ;
194196 }
@@ -203,56 +205,58 @@ private void backtrackFromDepth(int failedDepth) {
203205 }
204206
205207 private void releaseDepth (int depth ) {
206- if (depth < 0 || depth >= searchVariables . size () ) {
208+ if (depth < 0 || depth >= searchSlots . length ) {
207209 return ;
208210 }
209- String variableName = searchVariables . get ( depth ) ;
210- state .clear (variableName );
211+ DepthRuntime depthRuntime = depthRuntimes [ depth ] ;
212+ state .clear (depthRuntime . bindingSlot );
211213 initializedDepths [depth ] = false ;
212214 advanceDepths [depth ] = false ;
213- for (LmdbLftjCursor cursor : cursorsByDepth . get ( depth ) ) {
214- cursor .release (variableName );
215+ for (LmdbLftjCursor cursor : depthRuntime . cursors ) {
216+ cursor .release (depthRuntime . bindingSlot );
215217 }
216218 }
217219 }
218220
219- private List <String > collectSearchVariables (LmdbLftjPlan plan , LmdbLftjBindingState state ) {
220- List <String > searchVariables = new ArrayList <>(plan .variableOrder ().size ());
221- for (String variableName : plan .variableOrder ()) {
222- if (!state .isBound (variableName )) {
223- searchVariables .add (variableName );
221+ private int [] collectSearchSlots (LmdbLftjPlan plan , LmdbLftjBindingState state ) {
222+ int [] searchSlots = new int [plan .variableOrder ().size ()];
223+ int count = 0 ;
224+ for (int slot = 0 ; slot < state .variableCount (); slot ++) {
225+ if (!state .isBound (slot )) {
226+ searchSlots [count ++] = slot ;
224227 }
225228 }
226- return searchVariables ;
229+ return Arrays . copyOf ( searchSlots , count ) ;
227230 }
228231
229- private List <LmdbLftjCursor > createPatternCursors (LmdbLftjPlan plan , LmdbPrefixFrontierProvider frontierProvider ) {
230- List <LmdbLftjCursor > cursors = new ArrayList <>(plan .patternPlans ().size ());
231- for (LmdbLftjPatternPlan patternPlan : plan .patternPlans ()) {
232- cursors .add (new LmdbCachedTrieCursor (patternPlan , frontierProvider ));
232+ private LmdbLftjCursor [] createPatternCursors (LmdbLftjPlan plan , LmdbPrefixFrontierProvider frontierProvider ) {
233+ LmdbLftjCursor [] cursors = new LmdbLftjCursor [plan .patternPlans ().size ()];
234+ List <LmdbLftjPatternPlan > patternPlans = plan .patternPlans ();
235+ for (int i = 0 ; i < patternPlans .size (); i ++) {
236+ cursors [i ] = new LmdbCachedTrieCursor (patternPlans .get (i ), frontierProvider );
233237 }
234238 return cursors ;
235239 }
236240
237- private List <List <LmdbLftjCursor >> createDepthCursors (LmdbLftjPlan plan , List <String > searchVariables ,
238- List <LmdbLftjCursor > patternCursors ) {
239- List <List <LmdbLftjCursor >> cursorsByDepth = new ArrayList <>(searchVariables .size ());
241+ private DepthRuntime [] createDepthRuntimes (LmdbLftjPlan plan , int [] searchSlots , LmdbLftjCursor [] patternCursors ) {
242+ DepthRuntime [] depthRuntimes = new DepthRuntime [searchSlots .length ];
240243 List <LmdbLftjPatternPlan > patternPlans = plan .patternPlans ();
241- for (String variableName : searchVariables ) {
244+ for (int depth = 0 ; depth < searchSlots .length ; depth ++) {
245+ int bindingSlot = searchSlots [depth ];
242246 List <LmdbLftjCursor > cursors = new ArrayList <>();
243247 for (int i = 0 ; i < patternPlans .size (); i ++) {
244248 LmdbLftjPatternPlan patternPlan = patternPlans .get (i );
245- if (!patternPlan .containsVariable ( variableName )) {
249+ if (!patternPlan .containsBindingSlot ( bindingSlot )) {
246250 continue ;
247251 }
248- cursors .add (patternCursors . get ( i ) );
252+ cursors .add (patternCursors [ i ] );
249253 }
250- cursorsByDepth . add ( cursors );
254+ depthRuntimes [ depth ] = new DepthRuntime ( bindingSlot , cursors . toArray ( new LmdbLftjCursor [ 0 ]) );
251255 }
252- return cursorsByDepth ;
256+ return depthRuntimes ;
253257 }
254258
255- private long align (List < LmdbLftjCursor > cursors , long target ) {
259+ private long align (LmdbLftjCursor [] cursors , long target ) {
256260 long current = target ;
257261 while (true ) {
258262 boolean allMatch = true ;
@@ -292,6 +296,16 @@ private long countMatches(LmdbLftjPatternPlan patternPlan, LmdbLftjMetrics metri
292296 return frontierProvider .countMatches (patternPlan );
293297 }
294298
299+ private static final class DepthRuntime {
300+ private final int bindingSlot ;
301+ private final LmdbLftjCursor [] cursors ;
302+
303+ private DepthRuntime (int bindingSlot , LmdbLftjCursor [] cursors ) {
304+ this .bindingSlot = bindingSlot ;
305+ this .cursors = cursors ;
306+ }
307+ }
308+
295309 private final class LazyFallbackStep {
296310
297311 private final TupleExpr fallbackExpr ;
0 commit comments