@@ -139,7 +139,7 @@ func (fw *fixupWorker) splitPartition(
139139 }
140140
141141 log .VEventf (ctx , 2 , "splitting partition %d with %d vectors (parent=%d, state=%s)" ,
142- partitionKey , parentPartitionKey , partition .Count (), metadata .StateDetails .String ())
142+ partitionKey , partition .Count (), parentPartitionKey , metadata .StateDetails .String ())
143143
144144 // Update partition's state to Splitting.
145145 if metadata .StateDetails .State == ReadyState {
@@ -454,13 +454,13 @@ func (fw *fixupWorker) createSplitSubPartition(
454454 partitionKey PartitionKey ,
455455 centroid vector.T ,
456456) (targetMetadata PartitionMetadata , err error ) {
457- const format = "creating split sub-partition %d, with parent %d "
457+ const format = "creating split sub-partition %d (source=%d, parent=%d) "
458458
459459 defer func () {
460- err = errors .Wrapf (err , format , partitionKey , parentPartitionKey )
460+ err = errors .Wrapf (err , format , partitionKey , sourcePartitionKey , parentPartitionKey )
461461 }()
462462
463- log .VEventf (ctx , 2 , format , partitionKey , parentPartitionKey )
463+ log .VEventf (ctx , 2 , format , partitionKey , sourcePartitionKey , parentPartitionKey )
464464
465465 // Create an empty partition in the Updating state.
466466 targetMetadata = PartitionMetadata {
@@ -548,15 +548,15 @@ func (fw *fixupWorker) addToParentPartition(
548548func (fw * fixupWorker ) deletePartition (
549549 ctx context.Context , parentPartitionKey , partitionKey PartitionKey ,
550550) (err error ) {
551- const format = "deleting partition %d (parent=%d, state=%d )"
551+ const format = "deleting partition %d (parent=%d, state=%s )"
552552 var parentMetadata PartitionMetadata
553553
554554 defer func () {
555555 err = errors .Wrapf (err , format ,
556- partitionKey , parentPartitionKey , parentMetadata .StateDetails .State )
556+ partitionKey , parentPartitionKey , parentMetadata .StateDetails .String () )
557557 }()
558558
559- // Load parent partition to verify that it's in a state that allows inserts .
559+ // Load parent partition to verify that it's in a state that allows removes .
560560 var parentPartition * Partition
561561 parentPartition , err = fw .getPartition (ctx , parentPartitionKey )
562562 if err != nil {
@@ -566,7 +566,8 @@ func (fw *fixupWorker) deletePartition(
566566 parentMetadata = * parentPartition .Metadata ()
567567 }
568568
569- log .VEventf (ctx , 2 , format , partitionKey , parentPartitionKey , parentMetadata .StateDetails .State )
569+ log .VEventf (ctx , 2 , format ,
570+ partitionKey , parentPartitionKey , parentMetadata .StateDetails .String ())
570571
571572 if ! parentMetadata .StateDetails .State .AllowAddOrRemove () {
572573 // Child could not be removed from the parent because it doesn't exist or
@@ -640,21 +641,16 @@ func (fw *fixupWorker) copyToSplitSubPartitions(
640641 leftOffsets , rightOffsets = kmeans .AssignPartitions (
641642 vectors , leftMetadata .Centroid , rightMetadata .Centroid , tempOffsets )
642643
643- // Sort vectors into contiguous left and right groupings.
644- sortVectors (& fw .workspace , vectors , leftOffsets , rightOffsets )
644+ // Assign vectors and associated keys and values into contiguous left and right groupings.
645+ childKeys := slices .Clone (sourcePartition .ChildKeys ())
646+ valueBytes := slices .Clone (sourcePartition .ValueBytes ())
647+ splitPartitionData (& fw .workspace , vectors , childKeys , valueBytes , leftOffsets , rightOffsets )
645648 leftVectors := vectors
646649 rightVectors := leftVectors .SplitAt (len (leftOffsets ))
647-
648- childKeys := make ([]ChildKey , vectors .Count )
649- valueBytes := make ([]ValueBytes , vectors .Count )
650- leftChildKeys := copyByOffsets (
651- sourcePartition .ChildKeys (), childKeys [:len (leftOffsets )], leftOffsets )
652- rightChildKeys := copyByOffsets (
653- sourcePartition .ChildKeys (), childKeys [len (leftOffsets ):], rightOffsets )
654- leftValueBytes := copyByOffsets (
655- sourcePartition .ValueBytes (), valueBytes [:len (leftOffsets )], leftOffsets )
656- rightValueBytes := copyByOffsets (
657- sourcePartition .ValueBytes (), valueBytes [len (leftOffsets ):], rightOffsets )
650+ leftChildKeys := childKeys [:len (leftOffsets )]
651+ rightChildKeys := childKeys [len (leftOffsets ):]
652+ leftValueBytes := valueBytes [:len (leftOffsets )]
653+ rightValueBytes := valueBytes [len (leftOffsets ):]
658654
659655 log .VEventf (ctx , 2 , format ,
660656 len (leftOffsets ), sourceState .Target1 , len (rightOffsets ), sourceState .Target2 )
@@ -740,63 +736,63 @@ func suppressRaceErrors(err error) (PartitionMetadata, error) {
740736 return PartitionMetadata {}, err
741737}
742738
743- // sortVectors sorts the input vectors in-place, according to the provided left
744- // and right offsets, which reference vectors by position. Vectors at left
745- // offsets are sorted at the beginning of the slice, followed by vectors at
746- // right offsets. The internal ordering among left and right vectors is not
747- // defined.
739+ // splitPartitionData groups the provided partition data according to the left
740+ // and right offsets. All data referenced by left offsets will be moved to the
741+ // left of each set or slice. All data referenced by right offsets will be moved
742+ // to the right. The internal ordering of elements on each side is not defined.
748743//
749- // NOTE: The left and right offsets are modified in-place with the updated
750- // positions of the vectors.
751- func sortVectors (w * workspace.T , vectors vector.Set , leftOffsets , rightOffsets []uint64 ) {
744+ // TODO(andyk): Passing in left and right offsets makes this overly complex. It
745+ // would be better to pass an assignments slice of the same length as the
746+ // partition data, where 0=left and 1=right.
747+ func splitPartitionData (
748+ w * workspace.T ,
749+ vectors vector.Set ,
750+ childKeys []ChildKey ,
751+ valueBytes []ValueBytes ,
752+ leftOffsets , rightOffsets []uint64 ,
753+ ) {
752754 tempVector := w .AllocFloats (vectors .Dims )
753755 defer w .FreeFloats (tempVector )
754756
755- // Sort left and right offsets.
756- slices .Sort (leftOffsets )
757- slices .Sort (rightOffsets )
758-
759- // Any left offsets that point beyond the end of the left list indicate that
760- // a vector needs to be moved from the right half of vectors to the left half.
761- // The reverse is true for right offsets. Because the left and right offsets
762- // are in sorted order, out-of-bounds offsets must be at the end of the left
763- // list and the beginning of the right list. Therefore, the algorithm just
764- // needs to iterate over those out-of-bounds offsets and swap the positions
765- // of the referenced vectors.
766- li := len (leftOffsets ) - 1
767- ri := 0
768-
769- var rightToLeft , leftToRight vector.T
770- for li >= 0 {
771- left := int (leftOffsets [li ])
772- if left < len (leftOffsets ) {
773- break
757+ left := 0
758+ right := 0
759+ for {
760+ // Find a misplaced "right" element from the left side.
761+ var leftOffset int
762+ for {
763+ if left >= len (leftOffsets ) {
764+ return
765+ }
766+ leftOffset = int (leftOffsets [left ])
767+ left ++
768+ if leftOffset >= len (leftOffsets ) {
769+ break
770+ }
774771 }
775772
776- right := int (rightOffsets [ri ])
777- if right >= len (leftOffsets ) {
778- panic (errors .AssertionFailedf (
779- "expected equal number of left and right offsets that need to be swapped" ))
773+ // There must be a misplaced "left" element from the right side.
774+ var rightOffset int
775+ for {
776+ rightOffset = int (rightOffsets [right ])
777+ right ++
778+ if rightOffset < len (leftOffsets ) {
779+ break
780+ }
780781 }
781782
782- // Swap vectors .
783- rightToLeft = vectors .At (left )
784- leftToRight = vectors .At (right )
783+ // Swap the two elements .
784+ rightToLeft : = vectors .At (leftOffset )
785+ leftToRight : = vectors .At (rightOffset )
785786 copy (tempVector , rightToLeft )
786787 copy (rightToLeft , leftToRight )
787788 copy (leftToRight , tempVector )
788789
789- leftOffsets [li ] = uint64 (left )
790- rightOffsets [ri ] = uint64 (right )
791-
792- li --
793- ri ++
794- }
795- }
790+ tempChildKey := childKeys [leftOffset ]
791+ childKeys [leftOffset ] = childKeys [rightOffset ]
792+ childKeys [rightOffset ] = tempChildKey
796793
797- func copyByOffsets [ T any ]( source , target [] T , offsets [] uint64 ) [] T {
798- for i := range offsets {
799- target [ i ] = source [ offsets [ i ]]
794+ tempValueBytes := valueBytes [ leftOffset ]
795+ valueBytes [ leftOffset ] = valueBytes [ rightOffset ]
796+ valueBytes [ rightOffset ] = tempValueBytes
800797 }
801- return target
802798}
0 commit comments