Skip to content

Commit 1c3c1cd

Browse files
Simplify OnDiskGraphIndex.View to avoid code duplication (#458)
* Simplify ODGI.View.getVector to avoid code duplication * Simplify computation of file offsets so that it is clearer.
1 parent 7250a3b commit 1c3c1cd

File tree

1 file changed

+17
-25
lines changed

1 file changed

+17
-25
lines changed

jvector-base/src/main/java/io/github/jbellis/jvector/graph/disk/OnDiskGraphIndex.java

Lines changed: 17 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,6 @@
4949
import java.util.Set;
5050
import java.util.concurrent.atomic.AtomicReference;
5151
import java.util.stream.Collectors;
52-
import java.util.stream.IntStream;
5352
import org.slf4j.Logger;
5453
import org.slf4j.LoggerFactory;
5554

@@ -279,7 +278,7 @@ public RandomAccessVectorValues copy() {
279278
throw new UnsupportedOperationException(); // need to copy reader
280279
}
281280

282-
protected long offsetFor(int node, FeatureId featureId) {
281+
private long offsetFor(int node, FeatureId featureId) {
283282
Feature feature = features.get(featureId);
284283

285284
// Separated features are just global offset + node offset
@@ -289,26 +288,31 @@ protected long offsetFor(int node, FeatureId featureId) {
289288
}
290289

291290
// Inline features are in layer 0 only
292-
return neighborsOffset +
293-
(node * ((long) Integer.BYTES // ids
294-
+ inlineBlockSize // inline elements
295-
+ (Integer.BYTES * (long) (layerInfo.get(0).degree + 1)) // neighbor count + neighbors)
296-
)) + Integer.BYTES + // id
297-
inlineOffsets.get(featureId);
291+
// skip node ID and get to the desired inline feature
292+
long skipInNode = Integer.BYTES + inlineOffsets.get(featureId);
293+
return baseNodeOffsetFor(node) + skipInNode;
298294
}
299295

300296
private long neighborsOffsetFor(int level, int node) {
301297
assert level == 0; // higher layers are in memory
302-
int degree = layerInfo.get(level).degree;
298+
299+
// skip node ID + inline features
300+
long skipInline = Integer.BYTES + inlineBlockSize;
301+
return baseNodeOffsetFor(node) + skipInline;
302+
}
303+
304+
private long baseNodeOffsetFor(int node) {
305+
int degree = layerInfo.get(0).degree;
303306

304307
// skip node ID + inline features
305308
long skipInline = Integer.BYTES + inlineBlockSize;
306309
long blockBytes = skipInline + (long) Integer.BYTES * (degree + 1);
307310

308311
long offsetWithinLayer = blockBytes * node;
309-
return neighborsOffset + offsetWithinLayer + skipInline;
312+
return neighborsOffset + offsetWithinLayer;
310313
}
311314

315+
312316
@Override
313317
public RandomAccessReader featureReaderForNode(int node, FeatureId featureId) throws IOException {
314318
long offset = offsetFor(node, featureId);
@@ -318,21 +322,9 @@ public RandomAccessReader featureReaderForNode(int node, FeatureId featureId) th
318322

319323
@Override
320324
public VectorFloat<?> getVector(int node) {
321-
var feature = features.get(FeatureId.INLINE_VECTORS);
322-
if (feature == null) {
323-
feature = features.get(FeatureId.SEPARATED_VECTORS);
324-
}
325-
if (feature == null) {
326-
throw new UnsupportedOperationException("No full-resolution vectors in this graph");
327-
}
328-
329-
try {
330-
long offset = offsetFor(node, feature.id());
331-
reader.seek(offset);
332-
return vectorTypeSupport.readFloatVector(reader, dimension);
333-
} catch (IOException e) {
334-
throw new UncheckedIOException(e);
335-
}
325+
VectorFloat<?> vec = vectorTypeSupport.createFloatVector(dimension);
326+
getVectorInto(node, vec, 0);
327+
return vec;
336328
}
337329

338330
@Override

0 commit comments

Comments
 (0)