|
11 | 11 | // Some portions generated by Codex |
12 | 12 | package org.eclipse.rdf4j.sail.lmdb; |
13 | 13 |
|
| 14 | +import java.util.ArrayDeque; |
| 15 | +import java.util.Arrays; |
| 16 | +import java.util.Deque; |
14 | 17 | import java.util.HashMap; |
15 | 18 | import java.util.Map; |
16 | 19 | import java.util.Objects; |
17 | 20 |
|
18 | 21 | public final class LmdbDerivedBinaryRelation { |
19 | 22 |
|
| 23 | + private static final ThreadLocal<Deque<RelationScratch>> SCRATCH_POOL = ThreadLocal.withInitial(ArrayDeque::new); |
| 24 | + |
20 | 25 | private final int sourceComponent; |
21 | 26 | private final int targetComponent; |
22 | 27 | private final LmdbCachedFrontier rootFrontier; |
@@ -58,6 +63,24 @@ public long count(long sourceValue, long targetValue) { |
58 | 63 | return frontier(sourceValue).countFor(targetValue); |
59 | 64 | } |
60 | 65 |
|
| 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 | + |
61 | 84 | public static final class Builder { |
62 | 85 |
|
63 | 86 | private final int sourceComponent; |
@@ -190,4 +213,123 @@ void clear() { |
190 | 213 | size = 0; |
191 | 214 | } |
192 | 215 | } |
| 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 | + } |
193 | 335 | } |
0 commit comments