Skip to content

Commit 9f0d330

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

5 files changed

Lines changed: 492 additions & 155 deletions

File tree

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

Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,17 @@
1111
// Some portions generated by Codex
1212
package org.eclipse.rdf4j.sail.lmdb;
1313

14+
import java.util.ArrayDeque;
15+
import java.util.Arrays;
16+
import java.util.Deque;
1417
import java.util.HashMap;
1518
import java.util.Map;
1619
import java.util.Objects;
1720

1821
public final class LmdbDerivedBinaryRelation {
1922

23+
private static final ThreadLocal<Deque<RelationScratch>> SCRATCH_POOL = ThreadLocal.withInitial(ArrayDeque::new);
24+
2025
private final int sourceComponent;
2126
private final int targetComponent;
2227
private final LmdbCachedFrontier rootFrontier;
@@ -58,6 +63,24 @@ public long count(long sourceValue, long targetValue) {
5863
return frontier(sourceValue).countFor(targetValue);
5964
}
6065

66+
public int sourceCount() {
67+
return adjacency.size();
68+
}
69+
70+
public int rootFrontierSize() {
71+
return rootFrontier.size();
72+
}
73+
74+
public static RelationScratch borrowScratch() {
75+
RelationScratch scratch = SCRATCH_POOL.get().pollFirst();
76+
return scratch == null ? new RelationScratch() : scratch;
77+
}
78+
79+
public static void releaseScratch(RelationScratch scratch) {
80+
scratch.release();
81+
SCRATCH_POOL.get().offerFirst(scratch);
82+
}
83+
6184
public static final class Builder {
6285

6386
private final int sourceComponent;
@@ -190,4 +213,123 @@ void clear() {
190213
size = 0;
191214
}
192215
}
216+
217+
public static final class RelationScratch {
218+
private static final int MIN_CAPACITY = 8;
219+
220+
private long[] frontierKeys = new long[MIN_CAPACITY];
221+
private long[][] frontierValues = new long[MIN_CAPACITY][];
222+
private int[] frontierGenerations = new int[MIN_CAPACITY];
223+
private int frontierGeneration = 1;
224+
225+
private long[] countSourceKeys = new long[MIN_CAPACITY];
226+
private long[] countTargetKeys = new long[MIN_CAPACITY];
227+
private long[] countValues = new long[MIN_CAPACITY];
228+
private int[] countGenerations = new int[MIN_CAPACITY];
229+
private int countGeneration = 1;
230+
231+
public void prepare(int sourceCount, int rootFrontierSize) {
232+
int expectedEntries = Math.max(sourceCount, rootFrontierSize);
233+
ensureFrontierCapacity(tableCapacity(expectedEntries));
234+
frontierGeneration = nextGeneration(frontierGeneration, frontierGenerations);
235+
236+
ensureCountCapacity(tableCapacity(expectedEntries));
237+
countGeneration = nextGeneration(countGeneration, countGenerations);
238+
}
239+
240+
public int frontierMask() {
241+
return frontierKeys.length - 1;
242+
}
243+
244+
public boolean frontierUsed(int slot) {
245+
return frontierGenerations[slot] == frontierGeneration;
246+
}
247+
248+
public long frontierKey(int slot) {
249+
return frontierKeys[slot];
250+
}
251+
252+
public long[] frontierValue(int slot) {
253+
return frontierValues[slot];
254+
}
255+
256+
public void storeFrontier(int slot, long key, long[] values) {
257+
frontierGenerations[slot] = frontierGeneration;
258+
frontierKeys[slot] = key;
259+
frontierValues[slot] = values;
260+
}
261+
262+
public int countMask() {
263+
return countSourceKeys.length - 1;
264+
}
265+
266+
public boolean countUsed(int slot) {
267+
return countGenerations[slot] == countGeneration;
268+
}
269+
270+
public long countSourceKey(int slot) {
271+
return countSourceKeys[slot];
272+
}
273+
274+
public long countTargetKey(int slot) {
275+
return countTargetKeys[slot];
276+
}
277+
278+
public long countValue(int slot) {
279+
return countValues[slot];
280+
}
281+
282+
public void storeCount(int slot, long sourceKey, long targetKey, long value) {
283+
countGenerations[slot] = countGeneration;
284+
countSourceKeys[slot] = sourceKey;
285+
countTargetKeys[slot] = targetKey;
286+
countValues[slot] = value;
287+
}
288+
289+
void release() {
290+
Arrays.fill(frontierValues, null);
291+
Arrays.fill(frontierGenerations, 0);
292+
Arrays.fill(countGenerations, 0);
293+
frontierGeneration = 1;
294+
countGeneration = 1;
295+
}
296+
297+
private void ensureFrontierCapacity(int requestedCapacity) {
298+
if (frontierKeys.length >= requestedCapacity) {
299+
return;
300+
}
301+
frontierKeys = new long[requestedCapacity];
302+
frontierValues = new long[requestedCapacity][];
303+
frontierGenerations = new int[requestedCapacity];
304+
frontierGeneration = 1;
305+
}
306+
307+
private void ensureCountCapacity(int requestedCapacity) {
308+
if (countSourceKeys.length >= requestedCapacity) {
309+
return;
310+
}
311+
countSourceKeys = new long[requestedCapacity];
312+
countTargetKeys = new long[requestedCapacity];
313+
countValues = new long[requestedCapacity];
314+
countGenerations = new int[requestedCapacity];
315+
countGeneration = 1;
316+
}
317+
318+
private static int tableCapacity(int expectedEntries) {
319+
int requested = Math.max(MIN_CAPACITY, expectedEntries << 1);
320+
int capacity = MIN_CAPACITY;
321+
while (capacity < requested) {
322+
capacity <<= 1;
323+
}
324+
return capacity;
325+
}
326+
327+
private static int nextGeneration(int generation, int[] slots) {
328+
if (generation == Integer.MAX_VALUE) {
329+
Arrays.fill(slots, 0);
330+
return 1;
331+
}
332+
return generation + 1;
333+
}
334+
}
193335
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919

2020
public final class LmdbLftjExecutionShape {
2121

22-
private static final int FULL_STACK_TEMPLATE_VERSION = 2;
22+
private static final int FULL_STACK_TEMPLATE_VERSION = 3;
2323

2424
private final int variableCount;
2525
private final int[][] cursorOrdinalsBySlot;

0 commit comments

Comments
 (0)