diff --git a/src/hnsw.h b/src/hnsw.h index b538284..4a06085 100644 --- a/src/hnsw.h +++ b/src/hnsw.h @@ -96,6 +96,8 @@ /* Ensure fits on page and in uint8 */ #define HnswGetMaxLevel(m) Min(((BLCKSZ - MAXALIGN(SizeOfPageHeaderData) - MAXALIGN(sizeof(HnswPageOpaqueData)) - offsetof(HnswNeighborTupleData, indextids) - sizeof(ItemIdData)) / (sizeof(ItemPointerData)) / m) - 2, 255) +#define HnswGetNeighbors(element, lc) (AssertMacro((element)->level >= (lc)), &(element)->neighbors[lc]) + /* Variables */ extern int hnsw_ef_search; extern bool hnsw_enable_parallel_build; diff --git a/src/hnswbuild.c b/src/hnswbuild.c index 1aedfe4..35c03d0 100644 --- a/src/hnswbuild.c +++ b/src/hnswbuild.c @@ -322,7 +322,7 @@ HnswElementMemory(HnswElement e, int m) static bool HnswFindDuplicateInMemory(HnswElement element) { - HnswNeighborArray *neighbors = &element->neighbors[0]; + HnswNeighborArray *neighbors = HnswGetNeighbors(element, 0); for (int i = 0; i < neighbors->length; i++) { @@ -398,7 +398,7 @@ InsertTupleInMemory(Relation index, Datum *values, ItemPointer heaptid, HnswBuil for (int lc = element->level; lc >= 0; lc--) { int lm = HnswGetLayerM(m, lc); - HnswNeighborArray *neighbors = &element->neighbors[lc]; + HnswNeighborArray *neighbors = HnswGetNeighbors(element, lc); for (int i = 0; i < neighbors->length; i++) HnswUpdateConnection(element, &neighbors->items[i], lm, lc, NULL, NULL, procinfo, collation); diff --git a/src/hnswinsert.c b/src/hnswinsert.c index d411dd2..55c29fb 100644 --- a/src/hnswinsert.c +++ b/src/hnswinsert.c @@ -343,7 +343,7 @@ HnswUpdateNeighborPages(Relation index, FmgrInfo *procinfo, Oid collation, HnswE for (int lc = e->level; lc >= 0; lc--) { int lm = HnswGetLayerM(m, lc); - HnswNeighborArray *neighbors = &e->neighbors[lc]; + HnswNeighborArray *neighbors = HnswGetNeighbors(e, lc); for (int i = 0; i < neighbors->length; i++) { @@ -513,7 +513,7 @@ HnswAddDuplicate(Relation index, HnswElement element, HnswElement dup, bool buil static bool HnswFindDuplicate(Relation index, HnswElement element, bool building) { - HnswNeighborArray *neighbors = &element->neighbors[0]; + HnswNeighborArray *neighbors = HnswGetNeighbors(element, 0); for (int i = 0; i < neighbors->length; i++) { diff --git a/src/hnswutils.c b/src/hnswutils.c index 3888765..7bee1fb 100644 --- a/src/hnswutils.c +++ b/src/hnswutils.c @@ -390,7 +390,7 @@ HnswSetNeighborTuple(HnswNeighborTuple ntup, HnswElement e, int m) for (int lc = e->level; lc >= 0; lc--) { - HnswNeighborArray *neighbors = &e->neighbors[lc]; + HnswNeighborArray *neighbors = HnswGetNeighbors(e, lc); int lm = HnswGetLayerM(m, lc); for (int i = 0; i < lm; i++) @@ -448,7 +448,7 @@ LoadNeighborsFromPage(HnswElement element, Relation index, Page page, int m) if (level < 0) level = 0; - neighbors = &element->neighbors[level]; + neighbors = HnswGetNeighbors(element, level); hc = &neighbors->items[neighbors->length++]; hc->element = e; } @@ -671,7 +671,7 @@ HnswSearchLayer(Datum q, List *ep, int ef, int lc, Relation index, FmgrInfo *pro HnswLoadNeighbors(c->element, index, m); /* Get the neighborhood at layer lc */ - neighborhood = &c->element->neighbors[lc]; + neighborhood = HnswGetNeighbors(c->element, lc); for (int i = 0; i < neighborhood->length; i++) { @@ -774,23 +774,23 @@ HnswGetDistance(HnswElement a, HnswElement b, int lc, FmgrInfo *procinfo, Oid co /* Look for cached distance */ if (a->neighbors != NULL) { - Assert(a->level >= lc); + HnswNeighborArray *neighbors = HnswGetNeighbors(a, lc); - for (int i = 0; i < a->neighbors[lc].length; i++) + for (int i = 0; i < neighbors->length; i++) { - if (a->neighbors[lc].items[i].element == b) - return a->neighbors[lc].items[i].distance; + if (neighbors->items[i].element == b) + return neighbors->items[i].distance; } } if (b->neighbors != NULL) { - Assert(b->level >= lc); + HnswNeighborArray *neighbors = HnswGetNeighbors(b, lc); - for (int i = 0; i < b->neighbors[lc].length; i++) + for (int i = 0; i < neighbors->length; i++) { - if (b->neighbors[lc].items[i].element == a) - return b->neighbors[lc].items[i].distance; + if (neighbors->items[i].element == a) + return neighbors->items[i].distance; } } @@ -826,7 +826,8 @@ SelectNeighbors(List *c, int m, int lc, FmgrInfo *procinfo, Oid collation, HnswE List *r = NIL; List *w = list_copy(c); pairingheap *wd; - bool mustCalculate = !e2->neighbors[lc].closerSet; + HnswNeighborArray *neighbors = HnswGetNeighbors(e2, lc); + bool mustCalculate = !neighbors->closerSet; List *added = NIL; bool removedAny = false; @@ -890,7 +891,7 @@ SelectNeighbors(List *c, int m, int lc, FmgrInfo *procinfo, Oid collation, HnswE } /* Cached value can only be used in future if sorted deterministically */ - e2->neighbors[lc].closerSet = sortCandidates; + neighbors->closerSet = sortCandidates; /* Keep pruned connections */ while (!pairingheap_is_empty(wd) && list_length(r) < m) @@ -915,7 +916,7 @@ static void AddConnections(HnswElement element, List *neighbors, int m, int lc) { ListCell *lc2; - HnswNeighborArray *a = &element->neighbors[lc]; + HnswNeighborArray *a = HnswGetNeighbors(element, lc); foreach(lc2, neighbors) a->items[a->length++] = *((HnswCandidate *) lfirst(lc2)); @@ -927,7 +928,7 @@ AddConnections(HnswElement element, List *neighbors, int m, int lc) void HnswUpdateConnection(HnswElement element, HnswCandidate * hc, int m, int lc, int *updateIdx, Relation index, FmgrInfo *procinfo, Oid collation) { - HnswNeighborArray *currentNeighbors = &hc->element->neighbors[lc]; + HnswNeighborArray *currentNeighbors = HnswGetNeighbors(hc->element, lc); HnswCandidate hc2;