|
42 | 42 | import org.slf4j.LoggerFactory;
|
43 | 43 |
|
44 | 44 | import javax.annotation.Nonnull;
|
| 45 | +import java.io.BufferedWriter; |
| 46 | +import java.io.FileWriter; |
| 47 | +import java.io.IOException; |
45 | 48 | import java.util.ArrayList;
|
46 | 49 | import java.util.Comparator;
|
47 | 50 | import java.util.Random;
|
| 51 | +import java.util.concurrent.atomic.AtomicLong; |
48 | 52 |
|
49 | 53 | /**
|
50 | 54 | * Tests testing insert/update/deletes of data into/in/from {@link RTree}s.
|
@@ -147,31 +151,68 @@ public void testInliningSerialization() {
|
147 | 151 | @Test
|
148 | 152 | public void testBasicInsert() {
|
149 | 153 | final Random random = new Random(0);
|
| 154 | + final AtomicLong nextNodeId = new AtomicLong(0L); |
150 | 155 | final HNSW hnsw = new HNSW(rtSubspace.getSubspace(), TestExecutors.defaultThreadPool());
|
151 | 156 |
|
152 | 157 | db.run(tr -> {
|
153 | 158 | for (int i = 0; i < 10; i ++) {
|
154 |
| - hnsw.insert(tr, createRandomPrimaryKey(random), createRandomVector(random, 728)).join(); |
| 159 | + hnsw.insert(tr, createNextPrimaryKey(nextNodeId), createRandomVector(random, 728)).join(); |
155 | 160 | }
|
156 | 161 | return null;
|
157 | 162 | });
|
158 | 163 | }
|
159 | 164 |
|
160 | 165 | @Test
|
161 |
| - public void testBasicInsertAndScanLayer() { |
| 166 | + public void testBasicInsertAndScanLayer() throws Exception { |
162 | 167 | final Random random = new Random(0);
|
163 |
| - final HNSW hnsw = new HNSW(rtSubspace.getSubspace(), TestExecutors.defaultThreadPool()); |
| 168 | + final AtomicLong nextNodeId = new AtomicLong(0L); |
| 169 | + final HNSW hnsw = new HNSW(rtSubspace.getSubspace(), TestExecutors.defaultThreadPool(), |
| 170 | + HNSW.DEFAULT_CONFIG.toBuilder().setM(4).setMMax(4).setMMax0(10).build(), |
| 171 | + OnWriteListener.NOOP, OnReadListener.NOOP); |
164 | 172 |
|
165 | 173 | db.run(tr -> {
|
166 |
| - for (int i = 0; i < 20; i ++) { |
167 |
| - hnsw.insert(tr, createRandomPrimaryKey(random), createRandomVector(random, 728)).join(); |
| 174 | + for (int i = 0; i < 100; i ++) { |
| 175 | + hnsw.insert(tr, createNextPrimaryKey(nextNodeId), createRandomVector(random, 2)).join(); |
168 | 176 | }
|
169 | 177 | return null;
|
170 | 178 | });
|
171 | 179 |
|
172 |
| - hnsw.scanLayer(db, 0, 100, node -> { |
173 |
| - System.out.println(node); |
174 |
| - }); |
| 180 | + int layer = 0; |
| 181 | + while (true) { |
| 182 | + if (!dumpLayer(hnsw, layer++)) { |
| 183 | + break; |
| 184 | + } |
| 185 | + } |
| 186 | + } |
| 187 | + |
| 188 | + private boolean dumpLayer(final HNSW hnsw, final int layer) throws IOException { |
| 189 | + final String verticesFileName = "/Users/nseemann/Downloads/vertices-" + layer + ".csv"; |
| 190 | + final String edgesFileName = "/Users/nseemann/Downloads/edges-" + layer + ".csv"; |
| 191 | + |
| 192 | + final AtomicLong numReadAtomic = new AtomicLong(0L); |
| 193 | + try (final BufferedWriter verticesWriter = new BufferedWriter(new FileWriter(verticesFileName)); |
| 194 | + final BufferedWriter edgesWriter = new BufferedWriter(new FileWriter(edgesFileName))) { |
| 195 | + hnsw.scanLayer(db, layer, 100, node -> { |
| 196 | + final CompactNode compactNode = node.asCompactNode(); |
| 197 | + final Vector<Half> vector = compactNode.getVector(); |
| 198 | + try { |
| 199 | + verticesWriter.write(compactNode.getPrimaryKey().getLong(0) + "," + |
| 200 | + vector.getComponent(0) + "," + |
| 201 | + vector.getComponent(1)); |
| 202 | + verticesWriter.newLine(); |
| 203 | + |
| 204 | + for (final var neighbor : compactNode.getNeighbors()) { |
| 205 | + edgesWriter.write(compactNode.getPrimaryKey().getLong(0) + "," + |
| 206 | + neighbor.getPrimaryKey().getLong(0)); |
| 207 | + edgesWriter.newLine(); |
| 208 | + } |
| 209 | + numReadAtomic.getAndIncrement(); |
| 210 | + } catch (final IOException e) { |
| 211 | + throw new RuntimeException("unable to write to file", e); |
| 212 | + } |
| 213 | + }); |
| 214 | + } |
| 215 | + return numReadAtomic.get() != 0; |
175 | 216 | }
|
176 | 217 |
|
177 | 218 | private <N extends NodeReference> void writeNode(@Nonnull final Transaction transaction,
|
@@ -227,6 +268,11 @@ private static Tuple createRandomPrimaryKey(final @Nonnull Random random) {
|
227 | 268 | return Tuple.from(random.nextLong());
|
228 | 269 | }
|
229 | 270 |
|
| 271 | + @Nonnull |
| 272 | + private static Tuple createNextPrimaryKey(@Nonnull final AtomicLong nextIdAtomic) { |
| 273 | + return Tuple.from(nextIdAtomic.getAndIncrement()); |
| 274 | + } |
| 275 | + |
230 | 276 | @Nonnull
|
231 | 277 | private Vector.HalfVector createRandomVector(@Nonnull final Random random, final int dimensionality) {
|
232 | 278 | final Half[] components = new Half[dimensionality];
|
|
0 commit comments