mirror of
https://github.com/VictoriaMetrics/VictoriaMetrics.git
synced 2024-12-15 00:13:30 +01:00
lib/uint64set: reduce memory allocations in Set.AppendTo
This commit is contained in:
parent
476c7fb109
commit
ab4d5d72eb
@ -660,14 +660,18 @@ func (b *bucket16) delFromSmallPool(x uint16) bool {
|
|||||||
func (b *bucket16) appendTo(dst []uint64, hi uint32, hi16 uint16) []uint64 {
|
func (b *bucket16) appendTo(dst []uint64, hi uint32, hi16 uint16) []uint64 {
|
||||||
hi64 := uint64(hi)<<32 | uint64(hi16)<<16
|
hi64 := uint64(hi)<<32 | uint64(hi16)<<16
|
||||||
if b.bits == nil {
|
if b.bits == nil {
|
||||||
a := b.smallPool[:b.smallPoolLen]
|
// Use uint16Sorter instead of sort.Slice here in order to reduce memory allocations.
|
||||||
if len(a) > 1 {
|
a := uint16SorterPool.Get().(*uint16Sorter)
|
||||||
sort.Slice(a, func(i, j int) bool { return a[i] < a[j] })
|
*a = uint16Sorter(b.smallPool[:b.smallPoolLen])
|
||||||
|
if len(*a) > 1 && !sort.IsSorted(a) {
|
||||||
|
sort.Sort(a)
|
||||||
}
|
}
|
||||||
for _, v := range a {
|
for _, v := range *a {
|
||||||
x := hi64 | uint64(v)
|
x := hi64 | uint64(v)
|
||||||
dst = append(dst, x)
|
dst = append(dst, x)
|
||||||
}
|
}
|
||||||
|
*a = nil
|
||||||
|
uint16SorterPool.Put(a)
|
||||||
return dst
|
return dst
|
||||||
}
|
}
|
||||||
var wordNum uint64
|
var wordNum uint64
|
||||||
@ -691,6 +695,22 @@ func (b *bucket16) appendTo(dst []uint64, hi uint32, hi16 uint16) []uint64 {
|
|||||||
return dst
|
return dst
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var uint16SorterPool = &sync.Pool{
|
||||||
|
New: func() interface{} {
|
||||||
|
return &uint16Sorter{}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
type uint16Sorter []uint16
|
||||||
|
|
||||||
|
func (s uint16Sorter) Len() int { return len(s) }
|
||||||
|
func (s uint16Sorter) Less(i, j int) bool {
|
||||||
|
return s[i] < s[j]
|
||||||
|
}
|
||||||
|
func (s uint16Sorter) Swap(i, j int) {
|
||||||
|
s[i], s[j] = s[j], s[i]
|
||||||
|
}
|
||||||
|
|
||||||
func getWordNumBitMask(x uint16) (uint16, uint64) {
|
func getWordNumBitMask(x uint16) (uint16, uint64) {
|
||||||
wordNum := x / 64
|
wordNum := x / 64
|
||||||
bitMask := uint64(1) << (x & 63)
|
bitMask := uint64(1) << (x & 63)
|
||||||
|
@ -240,6 +240,38 @@ func testSetBasicOps(t *testing.T, itemsCount int) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Verify UnionMayOwn
|
||||||
|
{
|
||||||
|
const unionOffset = 12345
|
||||||
|
var s1, s2 Set
|
||||||
|
for i := 0; i < itemsCount; i++ {
|
||||||
|
s1.Add(uint64(i) + offset)
|
||||||
|
s2.Add(uint64(i) + offset + unionOffset)
|
||||||
|
}
|
||||||
|
s1.UnionMayOwn(&s2)
|
||||||
|
expectedLen := 2 * itemsCount
|
||||||
|
if itemsCount > unionOffset {
|
||||||
|
expectedLen = itemsCount + unionOffset
|
||||||
|
}
|
||||||
|
if n := s1.Len(); n != expectedLen {
|
||||||
|
t.Fatalf("unexpected s1.Len() after union; got %d; want %d", n, expectedLen)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify union on empty set.
|
||||||
|
var s3 Set
|
||||||
|
expectedLen = s1.Len()
|
||||||
|
s3.UnionMayOwn(&s1)
|
||||||
|
if n := s3.Len(); n != expectedLen {
|
||||||
|
t.Fatalf("unexpected s3.Len() after union with empty set; got %d; want %d", n, expectedLen)
|
||||||
|
}
|
||||||
|
var s4 Set
|
||||||
|
expectedLen = s3.Len()
|
||||||
|
s3.UnionMayOwn(&s4)
|
||||||
|
if n := s3.Len(); n != expectedLen {
|
||||||
|
t.Fatalf("unexpected s3.Len() after union with empty set; got %d; want %d", n, expectedLen)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Verify intersect
|
// Verify intersect
|
||||||
{
|
{
|
||||||
// Verify s1.Intersect(s2) and s2.Intersect(s1)
|
// Verify s1.Intersect(s2) and s2.Intersect(s1)
|
||||||
|
Loading…
Reference in New Issue
Block a user