Skip to content

Commit 8cc530f

Browse files
committed
fastest yet, with codegen
1 parent e0e8b68 commit 8cc530f

23 files changed

Lines changed: 2681 additions & 127 deletions
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
/*******************************************************************************
2+
* Copyright (c) 2026 Eclipse RDF4J contributors.
3+
*
4+
* All rights reserved. This program and the accompanying materials
5+
* are made available under the terms of the Eclipse Distribution License v1.0
6+
* which accompanies this distribution, and is available at
7+
* http://www.eclipse.org/org/documents/edl-v10.php.
8+
*
9+
* SPDX-License-Identifier: BSD-3-Clause
10+
*******************************************************************************/
11+
// Some portions generated by Codex
12+
package org.eclipse.rdf4j.sail.lmdb;
13+
14+
import org.eclipse.rdf4j.common.iteration.LookAheadIteration;
15+
import org.eclipse.rdf4j.query.BindingSet;
16+
import org.eclipse.rdf4j.query.QueryEvaluationException;
17+
import org.eclipse.rdf4j.query.algebra.evaluation.impl.QueryEvaluationContext;
18+
19+
public abstract class AbstractLmdbFullStackCompiledLftjIteration extends LookAheadIteration<BindingSet> {
20+
21+
private final LmdbLftjPlan plan;
22+
private final LmdbLftjExecutionShape shape;
23+
private final LmdbLftjBindingState state;
24+
private final QueryEvaluationContext context;
25+
private final LmdbQueryAccess queryAccess;
26+
private final LmdbLftjMetrics metrics;
27+
28+
private BindingSet repeatedBinding;
29+
private long repeatedCount;
30+
31+
protected AbstractLmdbFullStackCompiledLftjIteration(LmdbLftjPlan plan, LmdbLftjExecutionShape shape,
32+
LmdbLftjBindingState state, QueryEvaluationContext context, LmdbQueryAccess queryAccess,
33+
LmdbLftjMetrics metrics) {
34+
this.plan = plan;
35+
this.shape = shape;
36+
this.state = state;
37+
this.context = context;
38+
this.queryAccess = queryAccess;
39+
this.metrics = metrics;
40+
}
41+
42+
@Override
43+
protected final BindingSet getNextElement() {
44+
if (repeatedCount > 0) {
45+
repeatedCount--;
46+
metrics.recordEmitted(1);
47+
return repeatedBinding;
48+
}
49+
50+
try {
51+
return computeNextElement();
52+
} catch (RuntimeException e) {
53+
throw new QueryEvaluationException("LMDB LFTJ full-stack compiled iteration failed", e);
54+
}
55+
}
56+
57+
@Override
58+
protected final void handleClose() {
59+
closeResources();
60+
state.close();
61+
}
62+
63+
protected abstract BindingSet computeNextElement();
64+
65+
protected abstract void closeResources();
66+
67+
protected final LmdbLftjPlan plan() {
68+
return plan;
69+
}
70+
71+
protected final LmdbLftjExecutionShape shape() {
72+
return shape;
73+
}
74+
75+
protected final LmdbLftjBindingState state() {
76+
return state;
77+
}
78+
79+
protected final QueryEvaluationContext context() {
80+
return context;
81+
}
82+
83+
protected final LmdbQueryAccess queryAccess() {
84+
return queryAccess;
85+
}
86+
87+
protected final LmdbLftjMetrics metrics() {
88+
return metrics;
89+
}
90+
91+
protected final void recordCandidateScan() {
92+
metrics.recordCandidateScan();
93+
}
94+
95+
protected final void recordWitnessScan() {
96+
metrics.recordWitnessScan();
97+
}
98+
99+
protected final BindingSet emitCurrent(long multiplicity) {
100+
BindingSet result = state.materialize(context);
101+
repeatedBinding = result;
102+
repeatedCount = multiplicity - 1;
103+
metrics.recordEmitted(1);
104+
return result;
105+
}
106+
}

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

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@
1515

1616
final class LmdbCachedFrontier {
1717

18-
static final LmdbCachedFrontier EMPTY = new LmdbCachedFrontier(new long[0], null);
18+
static final long[] EMPTY_VALUES = new long[0];
19+
static final LmdbCachedFrontier EMPTY = new LmdbCachedFrontier(EMPTY_VALUES, null);
1920

2021
private final long[] values;
2122
private final long[] counts;
@@ -33,6 +34,10 @@ int size() {
3334
return values.length;
3435
}
3536

37+
long[] values() {
38+
return values;
39+
}
40+
3641
long valueAt(int index) {
3742
return values[index];
3843
}

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

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,14 @@
1515
import java.util.Map;
1616
import java.util.Objects;
1717

18-
final class LmdbDerivedBinaryRelation {
18+
public final class LmdbDerivedBinaryRelation {
1919

2020
private final int sourceComponent;
2121
private final int targetComponent;
2222
private final LmdbCachedFrontier rootFrontier;
2323
private final Map<Long, LmdbCachedFrontier> adjacency;
2424

25-
LmdbDerivedBinaryRelation(int sourceComponent, int targetComponent, LmdbCachedFrontier rootFrontier,
25+
public LmdbDerivedBinaryRelation(int sourceComponent, int targetComponent, LmdbCachedFrontier rootFrontier,
2626
Map<Long, LmdbCachedFrontier> adjacency) {
2727
this.sourceComponent = sourceComponent;
2828
this.targetComponent = targetComponent;
@@ -42,15 +42,23 @@ LmdbCachedFrontier rootFrontier() {
4242
return rootFrontier;
4343
}
4444

45+
public long[] rootFrontierValues() {
46+
return rootFrontier.values();
47+
}
48+
4549
LmdbCachedFrontier frontier(long sourceValue) {
4650
return adjacency.getOrDefault(sourceValue, LmdbCachedFrontier.EMPTY);
4751
}
4852

49-
long count(long sourceValue, long targetValue) {
53+
public long[] frontierValues(long sourceValue) {
54+
return frontier(sourceValue).values();
55+
}
56+
57+
public long count(long sourceValue, long targetValue) {
5058
return frontier(sourceValue).countFor(targetValue);
5159
}
5260

53-
static final class Builder {
61+
public static final class Builder {
5462

5563
private final int sourceComponent;
5664
private final int targetComponent;
@@ -65,12 +73,12 @@ static final class Builder {
6573
private long currentTarget;
6674
private long currentCount;
6775

68-
Builder(int sourceComponent, int targetComponent) {
76+
public Builder(int sourceComponent, int targetComponent) {
6977
this.sourceComponent = sourceComponent;
7078
this.targetComponent = targetComponent;
7179
}
7280

73-
void add(long sourceValue, long targetValue) {
81+
public void add(long sourceValue, long targetValue) {
7482
if (!sourceOpen || sourceValue != currentSource) {
7583
finishPair();
7684
finishSource();
@@ -90,7 +98,7 @@ void add(long sourceValue, long targetValue) {
9098
currentCount++;
9199
}
92100

93-
LmdbDerivedBinaryRelation build() {
101+
public LmdbDerivedBinaryRelation build() {
94102
finishPair();
95103
finishSource();
96104
return new LmdbDerivedBinaryRelation(sourceComponent, targetComponent,

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

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ public final class LmdbLftjBindingState {
5454
}
5555
}
5656

57-
boolean initialize() {
57+
public boolean initialize() {
5858
for (LmdbLftjPatternPlan patternPlan : plan.patternPlans()) {
5959
for (LmdbLftjPatternPlan.TermRef term : patternPlan.terms()) {
6060
if (term.isConstant() && !constantIds.containsKey(term)) {
@@ -83,31 +83,31 @@ boolean initialize() {
8383
return true;
8484
}
8585

86-
void attachTxn(TxnManager.Txn txn) {
86+
public void attachTxn(TxnManager.Txn txn) {
8787
this.txn = txn;
8888
}
8989

90-
TxnManager.Txn txn() {
90+
public TxnManager.Txn txn() {
9191
return txn;
9292
}
9393

9494
boolean isBound(String variableName) {
9595
return isBound(slot(variableName));
9696
}
9797

98-
boolean isBound(int slot) {
98+
public boolean isBound(int slot) {
9999
return assignedPresent[slot] || fixedPresent[slot];
100100
}
101101

102-
boolean isFixed(int slot) {
102+
public boolean isFixed(int slot) {
103103
return fixedPresent[slot];
104104
}
105105

106106
long value(String variableName) {
107107
return value(slot(variableName));
108108
}
109109

110-
long value(int slot) {
110+
public long value(int slot) {
111111
if (assignedPresent[slot]) {
112112
return assignedValues[slot];
113113
}
@@ -147,7 +147,7 @@ long fixedId(LmdbLftjPatternPlan.TermRef term) {
147147
return -1;
148148
}
149149

150-
BindingSet materialize(QueryEvaluationContext context) {
150+
public BindingSet materialize(QueryEvaluationContext context) {
151151
MutableBindingSet result = context.createBindingSet(inputBindings);
152152
BiConsumer<Value, MutableBindingSet>[] setters = bindingSetters(context);
153153
for (int slot = 0; slot < variableNames.length; slot++) {
@@ -158,21 +158,25 @@ BindingSet materialize(QueryEvaluationContext context) {
158158
return result;
159159
}
160160

161-
int variableCount() {
161+
public int variableCount() {
162162
return variableNames.length;
163163
}
164164

165-
String variableName(int slot) {
165+
public String variableName(int slot) {
166166
return variableNames[slot];
167167
}
168168

169-
void close() {
169+
public void close() {
170170
if (txn != null) {
171171
queryAccess.releaseReadTxn(txn);
172172
txn = null;
173173
}
174174
}
175175

176+
public long fixedIdForComponent(int patternOrdinal, int component) {
177+
return fixedId(plan.patternPlans().get(patternOrdinal).termForComponent(component));
178+
}
179+
176180
@SuppressWarnings("unchecked")
177181
private BiConsumer<Value, MutableBindingSet>[] bindingSetters(QueryEvaluationContext context) {
178182
if (bindingSetters != null && bindingSettersContext == context) {

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

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,21 @@ class LmdbLftjCodegenCompiler {
2222
private static final AtomicLong CLASS_COUNTER = new AtomicLong();
2323
private static final String PACKAGE_NAME = LmdbLftjCodegenCompiler.class.getPackageName();
2424

25+
String cacheKey(LmdbLftjPlan plan, LmdbLftjExecutionShape shape, boolean includeInferred) {
26+
return plan.executionKey();
27+
}
28+
2529
LmdbCompiledLftjFactory compile(LmdbLftjPlan plan, LmdbLftjExecutionShape shape) {
2630
String simpleClassName = "GeneratedLmdbLftjFactory" + CLASS_COUNTER.incrementAndGet();
27-
String source = new SourceBuilder(simpleClassName, shape).build();
31+
String source = sourceFor(simpleClassName, plan, shape, false);
32+
return compileSource(plan.executionKey(), simpleClassName, source);
33+
}
34+
35+
LmdbCompiledLftjFactory compile(LmdbLftjPlan plan, LmdbLftjExecutionShape shape, boolean includeInferred) {
36+
return compile(plan, shape);
37+
}
38+
39+
protected final LmdbCompiledLftjFactory compileSource(String executionKey, String simpleClassName, String source) {
2840
try {
2941
SimpleCompiler compiler = new SimpleCompiler();
3042
compiler.setParentClassLoader(LmdbLftjCodegenCompiler.class.getClassLoader());
@@ -34,11 +46,20 @@ LmdbCompiledLftjFactory compile(LmdbLftjPlan plan, LmdbLftjExecutionShape shape)
3446
constructor.setAccessible(true);
3547
return (LmdbCompiledLftjFactory) constructor.newInstance();
3648
} catch (Exception e) {
37-
throw new IllegalArgumentException("Unable to compile LMDB LFTJ codegen for " + plan.executionKey(), e);
49+
throw new IllegalArgumentException("Unable to compile LMDB LFTJ codegen for " + executionKey, e);
3850
}
3951
}
4052

41-
private static final class SourceBuilder {
53+
String sourceFor(LmdbLftjPlan plan, LmdbLftjExecutionShape shape, boolean includeInferred) {
54+
return sourceFor("GeneratedLmdbLftjSource", plan, shape, includeInferred);
55+
}
56+
57+
protected String sourceFor(String simpleClassName, LmdbLftjPlan plan, LmdbLftjExecutionShape shape,
58+
boolean includeInferred) {
59+
return new SourceBuilder(simpleClassName, shape).build();
60+
}
61+
62+
protected static final class SourceBuilder {
4263

4364
private final String simpleClassName;
4465
private final LmdbLftjExecutionShape shape;

0 commit comments

Comments
 (0)