From 8cec1aa1ab9a0dcbca321eebf36a1de0c3fac2ea Mon Sep 17 00:00:00 2001 From: Shaun Patterson Date: Thu, 28 May 2026 14:13:31 -0400 Subject: [PATCH] perf(algo): pre-size heap in internalMergeSortWithBuffer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Build the heap slice and call heap.Init (O(n)) instead of n×heap.Push (per-element interface boxing). BenchmarkMergeSorted/MergeSorted (10000 lists × 100 uids): allocs/op 20.02k -> 10.01k (-50.03%, p=0.002) B/op 11.46Mi -> 8.86Mi (-22.70%, p=0.002) --- algo/uidlist.go | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/algo/uidlist.go b/algo/uidlist.go index 7aba70ba4a2..0ddf2d74d59 100644 --- a/algo/uidlist.go +++ b/algo/uidlist.go @@ -394,18 +394,21 @@ func internalMergeSortWithBuffer(lists []*pb.List, buffer []uint64) *pb.List { return &pb.List{Uids: buffer[:0]} } - h := &uint64Heap{} - heap.Init(h) - + // Pre-size the heap to avoid grow-and-copy. Building the slice directly and + // calling heap.Init (O(n)) is also cheaper than n × heap.Push (each O(log n) + // + interface boxing). + hs := make(uint64Heap, 0, len(lists)) for i, l := range lists { if l == nil || len(l.Uids) == 0 { continue } - heap.Push(h, elem{ + hs = append(hs, elem{ val: l.Uids[0], listIdx: i, }) } + h := &hs + heap.Init(h) // Use the provided buffer output := buffer[:0]