Skip to content

Commit 71ab6b7

Browse files
committed
new best
1 parent e831cc8 commit 71ab6b7

14 files changed

Lines changed: 872 additions & 519 deletions

core/sail/lmdb/src/main/java/org/eclipse/rdf4j/sail/lmdb/LmdbCachedTrieCursor.java

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -28,14 +28,14 @@ final class LmdbCachedTrieCursor implements LmdbLftjCursor {
2828
}
2929

3030
@Override
31-
public boolean open(String variableName) {
32-
LmdbCachedFrontier frontier = provider.frontier(patternPlan, variableName);
31+
public boolean open(int bindingSlot) {
32+
LmdbCachedFrontier frontier = provider.frontier(patternPlan, bindingSlot);
3333
if (frontier.isEmpty()) {
3434
return false;
3535
}
3636

3737
Frame frame = stack[stackSize++];
38-
frame.variableName = variableName;
38+
frame.bindingSlot = bindingSlot;
3939
frame.frontier = frontier;
4040
frame.position = 0;
4141
return true;
@@ -85,12 +85,12 @@ public long value() {
8585
}
8686

8787
@Override
88-
public void release(String variableName) {
88+
public void release(int bindingSlot) {
8989
if (stackSize == 0) {
9090
return;
9191
}
9292
Frame frame = stack[stackSize - 1];
93-
if (!frame.matches(variableName)) {
93+
if (!frame.matches(bindingSlot)) {
9494
return;
9595
}
9696
stack[--stackSize].reset();
@@ -111,18 +111,18 @@ private Frame currentFrame() {
111111
}
112112

113113
private static final class Frame {
114-
private String variableName;
114+
private int bindingSlot = -1;
115115
private LmdbCachedFrontier frontier;
116116
private int position;
117117

118118
private void reset() {
119-
variableName = null;
119+
bindingSlot = -1;
120120
frontier = null;
121121
position = -1;
122122
}
123123

124-
private boolean matches(String variableName) {
125-
return this.variableName != null && this.variableName.equals(variableName);
124+
private boolean matches(int bindingSlot) {
125+
return this.bindingSlot == bindingSlot;
126126
}
127127
}
128128
}

core/sail/lmdb/src/main/java/org/eclipse/rdf4j/sail/lmdb/LmdbLftjBindingState.java

Lines changed: 34 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ final class LmdbLftjBindingState {
2525
private final LmdbLftjPlan plan;
2626
private final BindingSet inputBindings;
2727
private final LmdbQueryAccess queryAccess;
28+
private final String[] variableNames;
2829
private final Map<String, Integer> variableSlots = new HashMap<>();
2930
private final long[] fixedValues;
3031
private final boolean[] fixedPresent;
@@ -38,13 +39,14 @@ final class LmdbLftjBindingState {
3839
this.plan = plan;
3940
this.inputBindings = inputBindings;
4041
this.queryAccess = queryAccess;
41-
int variableCount = plan.variableOrder().size();
42+
this.variableNames = plan.variableOrder().toArray(new String[0]);
43+
int variableCount = variableNames.length;
4244
this.fixedValues = new long[variableCount];
4345
this.fixedPresent = new boolean[variableCount];
4446
this.assignedValues = new long[variableCount];
4547
this.assignedPresent = new boolean[variableCount];
4648
for (int i = 0; i < variableCount; i++) {
47-
variableSlots.put(plan.variableOrder().get(i), i);
49+
variableSlots.put(variableNames[i], i);
4850
}
4951
}
5052

@@ -63,7 +65,7 @@ boolean initialize() {
6365
}
6466
}
6567
}
66-
for (String variableName : plan.variableOrder()) {
68+
for (String variableName : variableNames) {
6769
if (inputBindings.hasBinding(variableName)) {
6870
long id = queryAccess.resolveId(inputBindings.getValue(variableName));
6971
if (id == LmdbValue.UNKNOWN_ID) {
@@ -86,26 +88,39 @@ TxnManager.Txn txn() {
8688
}
8789

8890
boolean isBound(String variableName) {
89-
int slot = slot(variableName);
91+
return isBound(slot(variableName));
92+
}
93+
94+
boolean isBound(int slot) {
9095
return assignedPresent[slot] || fixedPresent[slot];
9196
}
9297

9398
long value(String variableName) {
94-
int slot = slot(variableName);
99+
return value(slot(variableName));
100+
}
101+
102+
long value(int slot) {
95103
if (assignedPresent[slot]) {
96104
return assignedValues[slot];
97105
}
98106
return fixedValues[slot];
99107
}
100108

101109
void assign(String variableName, long value) {
102-
int slot = slot(variableName);
110+
assign(slot(variableName), value);
111+
}
112+
113+
void assign(int slot, long value) {
103114
assignedValues[slot] = value;
104115
assignedPresent[slot] = true;
105116
}
106117

107118
void clear(String variableName) {
108-
assignedPresent[slot(variableName)] = false;
119+
clear(slot(variableName));
120+
}
121+
122+
void clear(int slot) {
123+
assignedPresent[slot] = false;
109124
}
110125

111126
long fixedId(LmdbLftjPatternPlan.TermRef term) {
@@ -126,14 +141,23 @@ long fixedId(LmdbLftjPatternPlan.TermRef term) {
126141

127142
BindingSet materialize(QueryEvaluationContext context) {
128143
MutableBindingSet result = context.createBindingSet(inputBindings);
129-
for (String variableName : plan.variableOrder()) {
130-
if (!result.hasBinding(variableName) && isBound(variableName)) {
131-
context.setBinding(variableName).accept(queryAccess.resolveValue(value(variableName)), result);
144+
for (int slot = 0; slot < variableNames.length; slot++) {
145+
String variableName = variableNames[slot];
146+
if (!result.hasBinding(variableName) && isBound(slot)) {
147+
context.setBinding(variableName).accept(queryAccess.resolveValue(value(slot)), result);
132148
}
133149
}
134150
return result;
135151
}
136152

153+
int variableCount() {
154+
return variableNames.length;
155+
}
156+
157+
String variableName(int slot) {
158+
return variableNames[slot];
159+
}
160+
137161
void close() {
138162
if (txn != null) {
139163
queryAccess.releaseReadTxn(txn);

core/sail/lmdb/src/main/java/org/eclipse/rdf4j/sail/lmdb/LmdbLftjCursor.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,15 +13,15 @@
1313

1414
interface LmdbLftjCursor extends AutoCloseable {
1515

16-
boolean open(String variableName);
16+
boolean open(int bindingSlot);
1717

1818
boolean seek(long target);
1919

2020
boolean next();
2121

2222
long value();
2323

24-
void release(String variableName);
24+
void release(int bindingSlot);
2525

2626
@Override
2727
void close();

core/sail/lmdb/src/main/java/org/eclipse/rdf4j/sail/lmdb/LmdbLftjExecutor.java

Lines changed: 54 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
package org.eclipse.rdf4j.sail.lmdb;
1313

1414
import java.util.ArrayList;
15+
import java.util.Arrays;
1516
import java.util.List;
1617

1718
import 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

Comments
 (0)