From 1db5e63af2ff16ff6eb227e04457983bc51c7e05 Mon Sep 17 00:00:00 2001 From: Andrew Kane Date: Mon, 5 Oct 2026 19:34:36 -0700 Subject: [PATCH] Added support [skip ci] --- src/hnsw.h | 5 +++-- src/hnswscan.c | 9 +++++---- src/hnswutils.c | 19 ++++++++++--------- 3 files changed, 18 insertions(+), 15 deletions(-) diff --git a/src/hnsw.h b/src/hnsw.h index bf3ddca..adc5466 100644 --- a/src/hnsw.h +++ b/src/hnsw.h @@ -410,6 +410,7 @@ typedef union typedef struct HnswSearchState { HnswQuery q; + HnswSupport *support; } HnswSearchState; typedef struct HnswScanOpaqueData @@ -468,14 +469,14 @@ bool HnswCheckNorm(HnswSupport * support, Datum value); Buffer HnswNewBuffer(Relation index, ForkNumber forkNum); void HnswInitPage(Buffer buf, Page page); void HnswInit(void); -List *HnswSearchLayer(char *base, HnswSearchState * searchState, List *ep, int ef, int lc, Relation index, HnswSupport * support, int m, bool inserting, HnswElement skipElement, visited_hash * v, pairingheap **discarded, bool initVisited, int64 *tuples); +List *HnswSearchLayer(char *base, HnswSearchState * searchState, List *ep, int ef, int lc, Relation index, int m, bool inserting, HnswElement skipElement, visited_hash * v, pairingheap **discarded, bool initVisited, int64 *tuples); HnswElement HnswGetEntryPoint(Relation index); void HnswGetMetaPageInfo(Relation index, int *m, int *dimensions, HnswElement * entryPoint); void *HnswAlloc(HnswAllocator * allocator, Size size); HnswElement HnswInitElement(char *base, ItemPointer tid, int m, double ml, int maxLevel, HnswAllocator * alloc); HnswElement HnswInitElementFromBlock(BlockNumber blkno, OffsetNumber offno); void HnswFindElementNeighbors(char *base, HnswElement element, HnswElement entryPoint, Relation index, HnswSupport * support, int m, int efConstruction, bool existing); -HnswSearchCandidate *HnswEntryCandidate(char *base, HnswElement entryPoint, HnswSearchState * searchState, Relation index, HnswSupport * support, bool loadVec); +HnswSearchCandidate *HnswEntryCandidate(char *base, HnswElement entryPoint, HnswSearchState * searchState, Relation index, bool loadVec); void HnswUpdateMetaPage(Relation index, int updateEntry, HnswElement entryPoint, BlockNumber insertPage, ForkNumber forkNum, bool building); void HnswSetNeighborTuple(char *base, HnswNeighborTuple ntup, HnswElement e, int m); void HnswAddHeapTid(HnswElement element, ItemPointer heaptid); diff --git a/src/hnswscan.c b/src/hnswscan.c index 5a8d459..42cfa12 100644 --- a/src/hnswscan.c +++ b/src/hnswscan.c @@ -44,20 +44,21 @@ GetScanItems(IndexScanDesc scan, Datum value) HnswCheckDim(dimensions, so->typeInfo, support->collation, value); searchState->q.value = value; + searchState->support = support; so->m = m; if (entryPoint == NULL) return NIL; - ep = list_make1(HnswEntryCandidate(base, entryPoint, searchState, index, support, false)); + ep = list_make1(HnswEntryCandidate(base, entryPoint, searchState, index, false)); for (int lc = entryPoint->level; lc >= 1; lc--) { - w = HnswSearchLayer(base, searchState, ep, 1, lc, index, support, m, false, NULL, NULL, NULL, true, NULL); + w = HnswSearchLayer(base, searchState, ep, 1, lc, index, m, false, NULL, NULL, NULL, true, NULL); ep = w; } - return HnswSearchLayer(base, searchState, ep, hnsw_ef_search, 0, index, support, m, false, NULL, &so->v, hnsw_iterative_scan != HNSW_ITERATIVE_SCAN_OFF ? &so->discarded : NULL, true, &so->tuples); + return HnswSearchLayer(base, searchState, ep, hnsw_ef_search, 0, index, m, false, NULL, &so->v, hnsw_iterative_scan != HNSW_ITERATIVE_SCAN_OFF ? &so->discarded : NULL, true, &so->tuples); } /* @@ -88,7 +89,7 @@ ResumeScanItems(IndexScanDesc scan) ep = lappend(ep, sc); } - return HnswSearchLayer(base, &so->searchState, ep, batch_size, 0, index, &so->support, so->m, false, NULL, &so->v, &so->discarded, false, &so->tuples); + return HnswSearchLayer(base, &so->searchState, ep, batch_size, 0, index, so->m, false, NULL, &so->v, &so->discarded, false, &so->tuples); } /* diff --git a/src/hnswutils.c b/src/hnswutils.c index 7446d8e..f4b5168 100644 --- a/src/hnswutils.c +++ b/src/hnswutils.c @@ -612,15 +612,15 @@ HnswInitSearchCandidate(char *base, HnswElement element, double distance) * Create a candidate for the entry point */ HnswSearchCandidate * -HnswEntryCandidate(char *base, HnswElement entryPoint, HnswSearchState * searchState, Relation index, HnswSupport * support, bool loadVec) +HnswEntryCandidate(char *base, HnswElement entryPoint, HnswSearchState * searchState, Relation index, bool loadVec) { bool inMemory = index == NULL; double distance; if (inMemory) - distance = GetElementDistance(base, entryPoint, &searchState->q, support); + distance = GetElementDistance(base, entryPoint, &searchState->q, searchState->support); else - HnswLoadElement(entryPoint, &distance, &searchState->q, index, support, loadVec, NULL); + HnswLoadElement(entryPoint, &distance, &searchState->q, index, searchState->support, loadVec, NULL); return HnswInitSearchCandidate(base, entryPoint, distance); } @@ -825,7 +825,7 @@ HnswLoadUnvisitedFromDisk(HnswElement element, HnswUnvisited * unvisited, int *u * Algorithm 2 from paper */ List * -HnswSearchLayer(char *base, HnswSearchState * searchState, List *ep, int ef, int lc, Relation index, HnswSupport * support, int m, bool inserting, HnswElement skipElement, visited_hash * v, pairingheap **discarded, bool initVisited, int64 *tuples) +HnswSearchLayer(char *base, HnswSearchState * searchState, List *ep, int ef, int lc, Relation index, int m, bool inserting, HnswElement skipElement, visited_hash * v, pairingheap **discarded, bool initVisited, int64 *tuples) { List *w = NIL; pairingheap *C = pairingheap_allocate(CompareNearestCandidates, NULL); @@ -920,7 +920,7 @@ HnswSearchLayer(char *base, HnswSearchState * searchState, List *ep, int ef, int if (inMemory) { eElement = unvisited[i].element; - eDistance = GetElementDistance(base, eElement, &searchState->q, support); + eDistance = GetElementDistance(base, eElement, &searchState->q, searchState->support); } else { @@ -930,7 +930,7 @@ HnswSearchLayer(char *base, HnswSearchState * searchState, List *ep, int ef, int /* Avoid any allocations if not adding */ eElement = NULL; - HnswLoadElementImpl(blkno, offno, &eDistance, &searchState->q, index, support, inserting, alwaysAdd || discarded != NULL ? NULL : &f->distance, &eElement); + HnswLoadElementImpl(blkno, offno, &eDistance, &searchState->q, index, searchState->support, inserting, alwaysAdd || discarded != NULL ? NULL : &f->distance, &eElement); if (eElement == NULL) continue; @@ -1292,6 +1292,7 @@ HnswFindElementNeighbors(char *base, HnswElement element, HnswElement entryPoint bool inMemory = index == NULL; searchState.q.value = HnswGetValue(base, element); + searchState.support = support; /* Precompute hash */ if (inMemory) @@ -1302,13 +1303,13 @@ HnswFindElementNeighbors(char *base, HnswElement element, HnswElement entryPoint return; /* Get entry point and level */ - ep = list_make1(HnswEntryCandidate(base, entryPoint, &searchState, index, support, true)); + ep = list_make1(HnswEntryCandidate(base, entryPoint, &searchState, index, true)); entryLevel = entryPoint->level; /* 1st phase: greedy search to insert level */ for (int lc = entryLevel; lc >= level + 1; lc--) { - w = HnswSearchLayer(base, &searchState, ep, 1, lc, index, support, m, true, skipElement, NULL, NULL, true, NULL); + w = HnswSearchLayer(base, &searchState, ep, 1, lc, index, m, true, skipElement, NULL, NULL, true, NULL); ep = w; } @@ -1327,7 +1328,7 @@ HnswFindElementNeighbors(char *base, HnswElement element, HnswElement entryPoint List *lw = NIL; ListCell *lc2; - w = HnswSearchLayer(base, &searchState, ep, efConstruction, lc, index, support, m, true, skipElement, NULL, NULL, true, NULL); + w = HnswSearchLayer(base, &searchState, ep, efConstruction, lc, index, m, true, skipElement, NULL, NULL, true, NULL); /* Convert search candidates to candidates */ foreach(lc2, w)