Skip to content

Commit 3875334

Browse files
committed
better dumping of HNSW layers upon failure
1 parent bde3495 commit 3875334

File tree

3 files changed

+49
-21
lines changed

3 files changed

+49
-21
lines changed

fdb-extensions/src/main/java/com/apple/foundationdb/async/hnsw/AbstractStorageAdapter.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,20 @@ public InliningStorageAdapter asInliningStorageAdapter() {
113113
return (InliningStorageAdapter)this;
114114
}
115115

116+
@Override
117+
public boolean isCompactStorageAdapter() {
118+
final boolean isCompactStorageAdapter = getNodeFactory().getNodeKind() == NodeKind.COMPACT;
119+
Verify.verify(!isCompactStorageAdapter || this instanceof CompactStorageAdapter);
120+
return isCompactStorageAdapter;
121+
}
122+
123+
@Nonnull
124+
@Override
125+
public CompactStorageAdapter asCompactStorageAdapter() {
126+
Verify.verify(isCompactStorageAdapter());
127+
return (CompactStorageAdapter)this;
128+
}
129+
116130
@Override
117131
@Nonnull
118132
public Subspace getSubspace() {

fdb-extensions/src/main/java/com/apple/foundationdb/async/hnsw/StorageAdapter.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,11 @@ interface StorageAdapter<N extends NodeReference> {
9898
@Nonnull
9999
InliningStorageAdapter asInliningStorageAdapter();
100100

101+
boolean isCompactStorageAdapter();
102+
103+
@Nonnull
104+
CompactStorageAdapter asCompactStorageAdapter();
105+
101106
/**
102107
* Get the subspace used to store this HNSW structure.
103108
* @return the subspace

fdb-extensions/src/test/java/com/apple/foundationdb/async/hnsw/HNSWTest.java

Lines changed: 30 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,10 @@
5252
import org.junit.jupiter.api.Tag;
5353
import org.junit.jupiter.api.Test;
5454
import org.junit.jupiter.api.extension.AfterTestExecutionCallback;
55+
import org.junit.jupiter.api.extension.ExtendWith;
5556
import org.junit.jupiter.api.extension.ExtensionContext;
5657
import org.junit.jupiter.api.extension.RegisterExtension;
58+
import org.junit.jupiter.api.io.TempDir;
5759
import org.junit.jupiter.api.parallel.Execution;
5860
import org.junit.jupiter.api.parallel.ExecutionMode;
5961
import org.junit.jupiter.params.ParameterInfo;
@@ -67,9 +69,9 @@
6769
import javax.annotation.Nonnull;
6870
import javax.annotation.Nullable;
6971
import java.io.BufferedWriter;
70-
import java.io.FileWriter;
7172
import java.io.IOException;
7273
import java.nio.channels.FileChannel;
74+
import java.nio.file.Files;
7375
import java.nio.file.Path;
7476
import java.nio.file.Paths;
7577
import java.nio.file.StandardOpenOption;
@@ -116,6 +118,9 @@ class HNSWTest {
116118
@RegisterExtension
117119
TestSubspaceExtension rtSecondarySubspace = new TestSubspaceExtension(dbExtension);
118120

121+
@TempDir
122+
Path tempDir;
123+
119124
private Database db;
120125

121126
@BeforeEach
@@ -316,7 +321,7 @@ void testBasicInsert(final long seed, final Config config) {
316321
Assertions.assertThat(readIds.size()).isBetween(10, 50);
317322
}
318323

319-
//@ExtendWith(HNSWTest.DumpLayersIfFailure.class)
324+
@ExtendWith(HNSWTest.DumpLayersIfFailure.class)
320325
@ParameterizedTest
321326
@MethodSource("randomSeedsWithConfig")
322327
void testBasicInsertDelete(final long seed, final Config config) {
@@ -404,11 +409,6 @@ void testBasicInsertDelete(final long seed, final Config config) {
404409
onReadListener.getNodeCountByLayer(), onReadListener.getBytesReadByLayer(),
405410
String.format(Locale.ROOT, "%.2f", recall * 100.0d));
406411

407-
if (recall <= 0.9) {
408-
db.run(tr ->
409-
hnsw.kNearestNeighborsSearch(tr, k, 100, true, queryVector).join());
410-
}
411-
412412
Assertions.assertThat(recall).isGreaterThan(0.9);
413413

414414
final long remainingNumNodes = countNodesOnLayer(config, 0);
@@ -710,28 +710,37 @@ private void scanLayer(@Nonnull final Config config,
710710

711711
private boolean dumpLayer(@Nonnull final Config config,
712712
@Nonnull final String prefix, final int layer) throws IOException {
713-
final String verticesFileName = "/Users/nseemann/Downloads/vertices-" + prefix + "-" + layer + ".csv";
714-
final String edgesFileName = "/Users/nseemann/Downloads/edges-" + prefix + "-" + layer + ".csv";
713+
final Path verticesFile = tempDir.resolve("vertices-" + prefix + "-" + layer + ".csv");
714+
final Path edgesFile = tempDir.resolve("edges-" + prefix + "-" + layer + ".csv");
715+
716+
final StorageAdapter<? extends NodeReference> storageAdapter =
717+
HNSW.storageAdapterForLayer(config, rtSubspace.getSubspace(),
718+
OnWriteListener.NOOP, OnReadListener.NOOP, layer);
715719

716720
final AtomicLong numReadAtomic = new AtomicLong(0L);
717-
try (final BufferedWriter verticesWriter = new BufferedWriter(new FileWriter(verticesFileName));
718-
final BufferedWriter edgesWriter = new BufferedWriter(new FileWriter(edgesFileName))) {
721+
try (final BufferedWriter verticesWriter = Files.newBufferedWriter(verticesFile);
722+
final BufferedWriter edgesWriter = Files.newBufferedWriter(edgesFile)) {
719723
scanLayer(config, layer, 100, node -> {
720-
final CompactNode compactNode = node.asCompactNode();
721-
final Transformed<RealVector> vector = compactNode.getVector();
724+
@Nullable final Transformed<RealVector> vector =
725+
storageAdapter.isCompactStorageAdapter()
726+
? node.asCompactNode().getVector()
727+
: null;
722728
try {
723-
verticesWriter.write(compactNode.getPrimaryKey().getLong(0) + ",");
724-
final RealVector realVector = vector.getUnderlyingVector();
725-
for (int i = 0; i < realVector.getNumDimensions(); i++) {
726-
if (i != 0) {
727-
verticesWriter.write(",");
729+
verticesWriter.write(Long.toString(node.getPrimaryKey().getLong(0)));
730+
if (vector != null) {
731+
verticesWriter.write(",");
732+
final RealVector realVector = vector.getUnderlyingVector();
733+
for (int i = 0; i < realVector.getNumDimensions(); i++) {
734+
if (i != 0) {
735+
verticesWriter.write(",");
736+
}
737+
verticesWriter.write(String.valueOf(realVector.getComponent(i)));
728738
}
729-
verticesWriter.write(String.valueOf(realVector.getComponent(i)));
730739
}
731740
verticesWriter.newLine();
732741

733-
for (final var neighbor : compactNode.getNeighbors()) {
734-
edgesWriter.write(compactNode.getPrimaryKey().getLong(0) + "," +
742+
for (final var neighbor : node.getNeighbors()) {
743+
edgesWriter.write(node.getPrimaryKey().getLong(0) + "," +
735744
neighbor.getPrimaryKey().getLong(0));
736745
edgesWriter.newLine();
737746
}

0 commit comments

Comments
 (0)