@@ -112,6 +112,12 @@ typedef union
112
112
tidhash_hash * tids ;
113
113
} visited_hash ;
114
114
115
+ typedef union
116
+ {
117
+ HnswElement element ;
118
+ ItemPointerData indextid ;
119
+ } HnswUnvisited ;
120
+
115
121
/*
116
122
* Get the max number of connections in an upper layer for each element in the index
117
123
*/
@@ -547,19 +553,19 @@ HnswLoadElementFromTuple(HnswElement element, HnswElementTuple etup, bool loadHe
547
553
/*
548
554
* Load an element and optionally get its distance from q
549
555
*/
550
- void
551
- HnswLoadElement ( HnswElement element , float * distance , Datum * q , Relation index , FmgrInfo * procinfo , Oid collation , bool loadVec , float * maxDistance )
556
+ static void
557
+ HnswLoadElementImpl ( BlockNumber blkno , OffsetNumber offno , float * distance , Datum * q , Relation index , FmgrInfo * procinfo , Oid collation , bool loadVec , float * maxDistance , HnswElement * element )
552
558
{
553
559
Buffer buf ;
554
560
Page page ;
555
561
HnswElementTuple etup ;
556
562
557
563
/* Read vector */
558
- buf = ReadBuffer (index , element -> blkno );
564
+ buf = ReadBuffer (index , blkno );
559
565
LockBuffer (buf , BUFFER_LOCK_SHARE );
560
566
page = BufferGetPage (buf );
561
567
562
- etup = (HnswElementTuple ) PageGetItem (page , PageGetItemId (page , element -> offno ));
568
+ etup = (HnswElementTuple ) PageGetItem (page , PageGetItemId (page , offno ));
563
569
564
570
Assert (HnswIsElementTuple (etup ));
565
571
@@ -574,11 +580,25 @@ HnswLoadElement(HnswElement element, float *distance, Datum *q, Relation index,
574
580
575
581
/* Load element */
576
582
if (distance == NULL || maxDistance == NULL || * distance < * maxDistance )
577
- HnswLoadElementFromTuple (element , etup , true, loadVec );
583
+ {
584
+ if (* element == NULL )
585
+ * element = HnswInitElementFromBlock (blkno , offno );
586
+
587
+ HnswLoadElementFromTuple (* element , etup , true, loadVec );
588
+ }
578
589
579
590
UnlockReleaseBuffer (buf );
580
591
}
581
592
593
+ /*
594
+ * Load an element and optionally get its distance from q
595
+ */
596
+ void
597
+ HnswLoadElement (HnswElement element , float * distance , Datum * q , Relation index , FmgrInfo * procinfo , Oid collation , bool loadVec , float * maxDistance )
598
+ {
599
+ HnswLoadElementImpl (element -> blkno , element -> offno , distance , q , index , procinfo , collation , loadVec , maxDistance , & element );
600
+ }
601
+
582
602
/*
583
603
* Get the distance for an element
584
604
*/
@@ -720,7 +740,7 @@ CountElement(char *base, HnswElement skipElement, HnswElement e)
720
740
* Load unvisited neighbors from memory
721
741
*/
722
742
static void
723
- HnswLoadUnvisitedFromMemory (char * base , HnswElement element , HnswElement * unvisited , int * unvisitedLength , visited_hash * v , int lc , HnswNeighborArray * neighborhoodData , Size neighborhoodSize )
743
+ HnswLoadUnvisitedFromMemory (char * base , HnswElement element , HnswUnvisited * unvisited , int * unvisitedLength , visited_hash * v , int lc , HnswNeighborArray * neighborhoodData , Size neighborhoodSize )
724
744
{
725
745
/* Get the neighborhood at layer lc */
726
746
HnswNeighborArray * neighborhood = HnswGetNeighbors (base , element , lc );
@@ -741,15 +761,15 @@ HnswLoadUnvisitedFromMemory(char *base, HnswElement element, HnswElement * unvis
741
761
AddToVisited (base , v , hc -> element , NULL , & found );
742
762
743
763
if (!found )
744
- unvisited [(* unvisitedLength )++ ] = HnswPtrAccess (base , hc -> element );
764
+ unvisited [(* unvisitedLength )++ ]. element = HnswPtrAccess (base , hc -> element );
745
765
}
746
766
}
747
767
748
768
/*
749
769
* Load unvisited neighbors from disk
750
770
*/
751
771
static void
752
- HnswLoadUnvisitedFromDisk (HnswElement element , HnswElement * unvisited , int * unvisitedLength , visited_hash * v , Relation index , int m , int lm , int lc )
772
+ HnswLoadUnvisitedFromDisk (HnswElement element , HnswUnvisited * unvisited , int * unvisitedLength , visited_hash * v , Relation index , int m , int lm , int lc )
753
773
{
754
774
Buffer buf ;
755
775
Page page ;
@@ -782,7 +802,7 @@ HnswLoadUnvisitedFromDisk(HnswElement element, HnswElement * unvisited, int *unv
782
802
tidhash_insert (v -> tids , * indextid , & found );
783
803
784
804
if (!found )
785
- unvisited [(* unvisitedLength )++ ] = HnswInitElementFromBlock ( ItemPointerGetBlockNumber ( indextid ), ItemPointerGetOffsetNumber ( indextid )) ;
805
+ unvisited [(* unvisitedLength )++ ]. indextid = * indextid ;
786
806
}
787
807
}
788
808
@@ -801,7 +821,7 @@ HnswSearchLayer(char *base, Datum q, List *ep, int ef, int lc, Relation index, F
801
821
HnswNeighborArray * neighborhoodData = NULL ;
802
822
Size neighborhoodSize = 0 ;
803
823
int lm = HnswGetLayerM (m , lc );
804
- HnswElement * unvisited = palloc (lm * sizeof (HnswElement ));
824
+ HnswUnvisited * unvisited = palloc (lm * sizeof (HnswUnvisited ));
805
825
int unvisitedLength ;
806
826
807
827
InitVisited (base , & v , index , ef , m );
@@ -853,16 +873,27 @@ HnswSearchLayer(char *base, Datum q, List *ep, int ef, int lc, Relation index, F
853
873
854
874
for (int i = 0 ; i < unvisitedLength ; i ++ )
855
875
{
856
- HnswElement eElement = unvisited [ i ] ;
876
+ HnswElement eElement ;
857
877
float eDistance ;
858
878
bool alwaysAdd = wlen < ef ;
859
879
860
880
f = HnswGetPairingHeapCandidate (w_node , pairingheap_first (W ));
861
881
862
882
if (index == NULL )
883
+ {
884
+ eElement = unvisited [i ].element ;
863
885
eDistance = GetElementDistance (base , eElement , q , procinfo , collation );
886
+ }
864
887
else
865
- HnswLoadElement (eElement , & eDistance , & q , index , procinfo , collation , inserting , alwaysAdd ? NULL : & f -> distance );
888
+ {
889
+ ItemPointer indextid = & unvisited [i ].indextid ;
890
+ BlockNumber blkno = ItemPointerGetBlockNumber (indextid );
891
+ OffsetNumber offno = ItemPointerGetOffsetNumber (indextid );
892
+
893
+ /* Avoid any allocations if not adding */
894
+ eElement = NULL ;
895
+ HnswLoadElementImpl (blkno , offno , & eDistance , & q , index , procinfo , collation , inserting , alwaysAdd ? NULL : & f -> distance , & eElement );
896
+ }
866
897
867
898
if (eDistance < f -> distance || alwaysAdd )
868
899
{
0 commit comments