Skip to content

Commit 08538bb

Browse files
authored
Fix silly inefficiencies in HnswGraph.NodesIterator implementation (#15425)
1 parent ba455f2 commit 08538bb

File tree

15 files changed

+103
-75
lines changed

15 files changed

+103
-75
lines changed

lucene/CHANGES.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,8 @@ Improvements
187187

188188
* GITHUB#15332: Add PhraseQuery.Builder.setMaxTerms() method to limit the maximum number of terms and excessive memory use (linyunanit)
189189

190+
* GITHUB#15425: Refactoring internal HnswGraph.NodesIterator to avoid unneeded copying and sorting (Mike Sokolov)
191+
190192
Optimizations
191193
---------------------
192194
* GITHUB#15140: Optimize TopScoreDocCollector with TernaryLongHeap for improved performance over Binary-LongHeap. (Ramakrishna Chilaka)

lucene/backward-codecs/src/java/org/apache/lucene/backward_codecs/lucene91/Lucene91HnswVectorsReader.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -575,9 +575,9 @@ public int entryNode() {
575575
@Override
576576
public NodesIterator getNodesOnLevel(int level) {
577577
if (level == 0) {
578-
return new ArrayNodesIterator(size());
578+
return new DenseNodesIterator(size());
579579
} else {
580-
return new ArrayNodesIterator(nodesByLevel[level], nodesByLevel[level].length);
580+
return new ArrayNodesIterator(nodesByLevel[level]);
581581
}
582582
}
583583
}

lucene/backward-codecs/src/java/org/apache/lucene/backward_codecs/lucene91/Lucene91OnHeapHnswGraph.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,7 @@ public int entryNode() {
173173
@Override
174174
public NodesIterator getNodesOnLevel(int level) {
175175
if (level == 0) {
176-
return new ArrayNodesIterator(size());
176+
return new DenseNodesIterator(size());
177177
} else {
178178
return new ArrayNodesIterator(nodesByLevel.get(level), graph.get(level).size());
179179
}

lucene/backward-codecs/src/java/org/apache/lucene/backward_codecs/lucene92/Lucene92HnswVectorsReader.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -485,9 +485,9 @@ public int entryNode() {
485485
@Override
486486
public NodesIterator getNodesOnLevel(int level) {
487487
if (level == 0) {
488-
return new ArrayNodesIterator(size());
488+
return new DenseNodesIterator(size());
489489
} else {
490-
return new ArrayNodesIterator(nodesByLevel[level], nodesByLevel[level].length);
490+
return new ArrayNodesIterator(nodesByLevel[level]);
491491
}
492492
}
493493
}

lucene/backward-codecs/src/java/org/apache/lucene/backward_codecs/lucene94/Lucene94HnswVectorsReader.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -537,9 +537,9 @@ public int maxConn() {
537537
@Override
538538
public NodesIterator getNodesOnLevel(int level) {
539539
if (level == 0) {
540-
return new ArrayNodesIterator(size());
540+
return new DenseNodesIterator(size());
541541
} else {
542-
return new ArrayNodesIterator(nodesByLevel[level], nodesByLevel[level].length);
542+
return new ArrayNodesIterator(nodesByLevel[level]);
543543
}
544544
}
545545
}

lucene/backward-codecs/src/java/org/apache/lucene/backward_codecs/lucene95/Lucene95HnswVectorsReader.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -566,9 +566,9 @@ public int maxConn() {
566566
@Override
567567
public NodesIterator getNodesOnLevel(int level) {
568568
if (level == 0) {
569-
return new ArrayNodesIterator(size());
569+
return new DenseNodesIterator(size());
570570
} else {
571-
return new ArrayNodesIterator(nodesByLevel[level], nodesByLevel[level].length);
571+
return new ArrayNodesIterator(nodesByLevel[level]);
572572
}
573573
}
574574
}

lucene/backward-codecs/src/test/org/apache/lucene/backward_codecs/lucene91/Lucene91HnswVectorsWriter.java

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -230,11 +230,11 @@ private void writeMeta(
230230
} else {
231231
meta.writeInt(graph.numLevels());
232232
for (int level = 0; level < graph.numLevels(); level++) {
233-
int[] sortedNodes = HnswGraph.NodesIterator.getSortedNodes(graph.getNodesOnLevel(level));
234-
meta.writeInt(sortedNodes.length); // number of nodes on a level
233+
HnswGraph.NodesIterator sortedNodes = graph.getSortedNodes(level);
234+
meta.writeInt(sortedNodes.size()); // number of nodes on a level
235235
if (level > 0) {
236-
for (int node : sortedNodes) {
237-
meta.writeInt(node); // list of nodes on a level
236+
while (sortedNodes.hasNext()) {
237+
meta.writeInt(sortedNodes.next()); // list of nodes on a level
238238
}
239239
}
240240
}
@@ -259,9 +259,9 @@ private Lucene91OnHeapHnswGraph writeGraph(
259259
// write vectors' neighbours on each level into the vectorIndex file
260260
int countOnLevel0 = graph.size();
261261
for (int level = 0; level < graph.numLevels(); level++) {
262-
int[] sortedNodes = HnswGraph.NodesIterator.getSortedNodes(graph.getNodesOnLevel(level));
263-
for (int node : sortedNodes) {
264-
Lucene91NeighborArray neighbors = graph.getNeighbors(level, node);
262+
HnswGraph.NodesIterator sortedNodes = graph.getSortedNodes(level);
263+
while (sortedNodes.hasNext()) {
264+
Lucene91NeighborArray neighbors = graph.getNeighbors(level, sortedNodes.next());
265265
int size = neighbors.size();
266266
vectorIndex.writeInt(size);
267267
// Destructively modify; it's ok we are discarding it after this

lucene/backward-codecs/src/test/org/apache/lucene/backward_codecs/lucene92/Lucene92HnswVectorsWriter.java

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -267,11 +267,11 @@ private void writeMeta(
267267
} else {
268268
meta.writeInt(graph.numLevels());
269269
for (int level = 0; level < graph.numLevels(); level++) {
270-
int[] sortedNodes = HnswGraph.NodesIterator.getSortedNodes(graph.getNodesOnLevel(level));
271-
meta.writeInt(sortedNodes.length); // number of nodes on a level
270+
HnswGraph.NodesIterator sortedNodes = graph.getSortedNodes(level);
271+
meta.writeInt(sortedNodes.size()); // number of nodes on a level
272272
if (level > 0) {
273-
for (int node : sortedNodes) {
274-
meta.writeInt(node); // list of nodes on a level
273+
while (sortedNodes.hasNext()) {
274+
meta.writeInt(sortedNodes.next()); // list of nodes on a level
275275
}
276276
}
277277
}
@@ -295,9 +295,9 @@ private OnHeapHnswGraph writeGraph(
295295
int countOnLevel0 = graph.size();
296296
for (int level = 0; level < graph.numLevels(); level++) {
297297
int maxConnOnLevel = level == 0 ? (M * 2) : M;
298-
int[] sortedNodes = HnswGraph.NodesIterator.getSortedNodes(graph.getNodesOnLevel(level));
299-
for (int node : sortedNodes) {
300-
NeighborArray neighbors = graph.getNeighbors(level, node);
298+
HnswGraph.NodesIterator sortedNodes = graph.getSortedNodes(level);
299+
while (sortedNodes.hasNext()) {
300+
NeighborArray neighbors = graph.getNeighbors(level, sortedNodes.next());
301301
int size = neighbors.size();
302302
vectorIndex.writeInt(size);
303303
// Destructively modify; it's ok we are discarding it after this

lucene/backward-codecs/src/test/org/apache/lucene/backward_codecs/lucene94/Lucene94HnswVectorsWriter.java

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -354,7 +354,7 @@ public NodesIterator getNodesOnLevel(int level) {
354354
if (level == 0) {
355355
return graph.getNodesOnLevel(0);
356356
} else {
357-
return new ArrayNodesIterator(nodesByLevel.get(level), nodesByLevel.get(level).length);
357+
return new ArrayNodesIterator(nodesByLevel.get(level));
358358
}
359359
}
360360
};
@@ -492,9 +492,9 @@ private void writeGraph(OnHeapHnswGraph graph) throws IOException {
492492
int countOnLevel0 = graph.size();
493493
for (int level = 0; level < graph.numLevels(); level++) {
494494
int maxConnOnLevel = level == 0 ? (M * 2) : M;
495-
int[] sortedNodes = HnswGraph.NodesIterator.getSortedNodes(graph.getNodesOnLevel(level));
496-
for (int node : sortedNodes) {
497-
NeighborArray neighbors = graph.getNeighbors(level, node);
495+
HnswGraph.NodesIterator sortedNodes = graph.getSortedNodes(level);
496+
while (sortedNodes.hasNext()) {
497+
NeighborArray neighbors = graph.getNeighbors(level, sortedNodes.next());
498498
int size = neighbors.size();
499499
vectorIndex.writeInt(size);
500500
// Destructively modify; it's ok we are discarding it after this
@@ -578,11 +578,11 @@ private void writeMeta(
578578
} else {
579579
meta.writeInt(graph.numLevels());
580580
for (int level = 0; level < graph.numLevels(); level++) {
581-
int[] sortedNodes = HnswGraph.NodesIterator.getSortedNodes(graph.getNodesOnLevel(level));
582-
meta.writeInt(sortedNodes.length); // number of nodes on a level
581+
HnswGraph.NodesIterator sortedNodes = graph.getSortedNodes(level);
582+
meta.writeInt(sortedNodes.size()); // number of nodes on a level
583583
if (level > 0) {
584-
for (int node : sortedNodes) {
585-
meta.writeInt(node); // list of nodes on a level
584+
while (sortedNodes.hasNext()) {
585+
meta.writeInt(sortedNodes.next()); // list of nodes on a level
586586
}
587587
}
588588
}

lucene/backward-codecs/src/test/org/apache/lucene/backward_codecs/lucene95/Lucene95HnswVectorsWriter.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -381,7 +381,7 @@ public NodesIterator getNodesOnLevel(int level) {
381381
if (level == 0) {
382382
return graph.getNodesOnLevel(0);
383383
} else {
384-
return new ArrayNodesIterator(nodesByLevel.get(level), nodesByLevel.get(level).length);
384+
return new ArrayNodesIterator(nodesByLevel.get(level));
385385
}
386386
}
387387
};
@@ -539,11 +539,11 @@ private int[][] writeGraph(OnHeapHnswGraph graph) throws IOException {
539539
int countOnLevel0 = graph.size();
540540
int[][] offsets = new int[graph.numLevels()][];
541541
for (int level = 0; level < graph.numLevels(); level++) {
542-
int[] sortedNodes = HnswGraph.NodesIterator.getSortedNodes(graph.getNodesOnLevel(level));
543-
offsets[level] = new int[sortedNodes.length];
542+
HnswGraph.NodesIterator sortedNodes = graph.getSortedNodes(level);
543+
offsets[level] = new int[sortedNodes.size()];
544544
int nodeOffsetId = 0;
545-
for (int node : sortedNodes) {
546-
NeighborArray neighbors = graph.getNeighbors(level, node);
545+
while (sortedNodes.hasNext()) {
546+
NeighborArray neighbors = graph.getNeighbors(level, sortedNodes.next());
547547
int size = neighbors.size();
548548
// Write size in VInt as the neighbors list is typically small
549549
long offsetStart = vectorIndex.getFilePointer();

0 commit comments

Comments
 (0)