diff --git a/freelist_hmap.go b/freelist_hmap.go index 6e01bc116..57e1e950b 100644 --- a/freelist_hmap.go +++ b/freelist_hmap.go @@ -80,12 +80,20 @@ func (f *freelist) hashmapGetFreePageIDs() []common.Pgid { } m := make([]common.Pgid, 0, count) - for start, size := range f.forwardMap { - for i := 0; i < int(size); i++ { - m = append(m, start+common.Pgid(i)) + + startPageIds := make([]common.Pgid, 0, len(f.forwardMap)) + for k := range f.forwardMap { + startPageIds = append(startPageIds, k) + } + sort.Sort(common.Pgids(startPageIds)) + + for _, start := range startPageIds { + if size, ok := f.forwardMap[start]; ok { + for i := 0; i < int(size); i++ { + m = append(m, start+common.Pgid(i)) + } } } - sort.Sort(common.Pgids(m)) return m } diff --git a/freelist_test.go b/freelist_test.go index 1fffff2ff..ab848dd1d 100644 --- a/freelist_test.go +++ b/freelist_test.go @@ -434,3 +434,52 @@ func newTestFreelist() *freelist { return newFreelist(freelistType) } + +func Test_freelist_hashmapGetFreePageIDs(t *testing.T) { + f := newTestFreelist() + if f.freelistType == common.FreelistArrayType { + t.Skip() + } + + N := int32(100000) + fm := make(map[common.Pgid]uint64) + i := int32(0) + val := int32(0) + for i = 0; i < N; { + val = rand.Int31n(1000) + fm[common.Pgid(i)] = uint64(val) + i += val + } + + f.forwardMap = fm + res := f.hashmapGetFreePageIDs() + + if !sort.SliceIsSorted(res, func(i, j int) bool { return res[i] < res[j] }) { + t.Fatalf("pgids not sorted") + } +} + +func Benchmark_freelist_hashmapGetFreePageIDs(b *testing.B) { + f := newTestFreelist() + if f.freelistType == common.FreelistArrayType { + b.Skip() + } + + N := int32(100000) + fm := make(map[common.Pgid]uint64) + i := int32(0) + val := int32(0) + for i = 0; i < N; { + val = rand.Int31n(1000) + fm[common.Pgid(i)] = uint64(val) + i += val + } + + f.forwardMap = fm + + b.ReportAllocs() + b.ResetTimer() + for n := 0; n < b.N; n++ { + f.hashmapGetFreePageIDs() + } +}