mirror of
https://github.com/VictoriaMetrics/VictoriaMetrics.git
synced 2024-11-21 14:44:00 +00:00
lib/uint64set: improve benchmark for Set.Intersect
This commit is contained in:
parent
d0d258b314
commit
cd53f7d177
2 changed files with 86 additions and 34 deletions
|
@ -232,32 +232,52 @@ func testSetBasicOps(t *testing.T, itemsCount int) {
|
|||
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.Union(&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
|
||||
{
|
||||
const intersectOffset = 12345
|
||||
// Verify s1.Intersect(s2) and s2.Intersect(s1)
|
||||
var s1, s2 Set
|
||||
for i := 0; i < itemsCount; i++ {
|
||||
s1.Add(uint64(i) + offset)
|
||||
s2.Add(uint64(i) + offset + intersectOffset)
|
||||
}
|
||||
s1.Intersect(&s2)
|
||||
expectedLen := 0
|
||||
if itemsCount > intersectOffset {
|
||||
expectedLen = itemsCount - intersectOffset
|
||||
}
|
||||
if n := s1.Len(); n != expectedLen {
|
||||
t.Fatalf("unexpected s1.Len() after intersect; got %d; want %d", n, expectedLen)
|
||||
for _, intersectOffset := range []uint64{123, 12345, 1<<32 + 4343} {
|
||||
s1 = Set{}
|
||||
s2 = Set{}
|
||||
for i := 0; i < itemsCount; i++ {
|
||||
s1.Add(uint64(i) + offset)
|
||||
s2.Add(uint64(i) + offset + intersectOffset)
|
||||
}
|
||||
expectedLen := 0
|
||||
if uint64(itemsCount) > intersectOffset {
|
||||
expectedLen = int(uint64(itemsCount) - intersectOffset)
|
||||
}
|
||||
s1Copy := s1.Clone()
|
||||
s1Copy.Intersect(&s2)
|
||||
if n := s1Copy.Len(); n != expectedLen {
|
||||
t.Fatalf("unexpected s1.Len() after intersect; got %d; want %d", n, expectedLen)
|
||||
}
|
||||
s2.Intersect(&s1)
|
||||
if n := s2.Len(); n != expectedLen {
|
||||
t.Fatalf("unexpected s2.Len() after intersect; got %d; want %d", n, expectedLen)
|
||||
}
|
||||
}
|
||||
|
||||
// Verify intersect on empty set.
|
||||
var s3 Set
|
||||
s2.Intersect(&s3)
|
||||
expectedLen = 0
|
||||
if n := s2.Len(); n != 0 {
|
||||
expectedLen := 0
|
||||
if n := s2.Len(); n != expectedLen {
|
||||
t.Fatalf("unexpected s3.Len() after intersect with empty set; got %d; want %d", n, expectedLen)
|
||||
}
|
||||
var s4 Set
|
||||
s4.Intersect(&s1)
|
||||
if n := s4.Len(); n != expectedLen {
|
||||
t.Fatalf("unexpected s4.Len() after intersect with empty set; got %d; want %d", n, expectedLen)
|
||||
}
|
||||
}
|
||||
|
||||
// Verify subtract
|
||||
|
|
|
@ -8,31 +8,56 @@ import (
|
|||
"github.com/valyala/fastrand"
|
||||
)
|
||||
|
||||
func BenchmarkIntersect(b *testing.B) {
|
||||
const itemsCount = 3e6
|
||||
for _, lastBits := range []uint64{20, 24, 28, 32} {
|
||||
sa := createRandomSet(itemsCount, lastBits)
|
||||
sb := createRandomSet(itemsCount, lastBits)
|
||||
b.Run(fmt.Sprintf("lastBits_%d", lastBits), func(b *testing.B) {
|
||||
b.ReportAllocs()
|
||||
b.SetBytes(int64(sa.Len()+sb.Len()))
|
||||
b.RunParallel(func(pb *testing.PB) {
|
||||
for pb.Next() {
|
||||
saCopy := sa.Clone()
|
||||
saCopy.Intersect(sb)
|
||||
}
|
||||
})
|
||||
func BenchmarkIntersectNoOverlap(b *testing.B) {
|
||||
for _, itemsCount := range []int{1e3, 1e4, 1e5, 1e6, 1e7} {
|
||||
start := uint64(time.Now().UnixNano())
|
||||
sa := createRangeSet(start, itemsCount)
|
||||
sb := createRangeSet(start+uint64(itemsCount), itemsCount)
|
||||
b.Run(fmt.Sprintf("items_%d", itemsCount), func(b *testing.B) {
|
||||
benchmarkIntersect(b, sa, sb)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func createRandomSet(itemsCount int, lastBits uint64) *Set {
|
||||
mask := (uint64(1) << lastBits) - 1
|
||||
start := uint64(time.Now().UnixNano())
|
||||
func BenchmarkIntersectPartialOverlap(b *testing.B) {
|
||||
for _, itemsCount := range []int{1e3, 1e4, 1e5, 1e6, 1e7} {
|
||||
start := uint64(time.Now().UnixNano())
|
||||
sa := createRangeSet(start, itemsCount)
|
||||
sb := createRangeSet(start+uint64(itemsCount/2), itemsCount)
|
||||
b.Run(fmt.Sprintf("items_%d", itemsCount), func(b *testing.B) {
|
||||
benchmarkIntersect(b, sa, sb)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkIntersectFullOverlap(b *testing.B) {
|
||||
for _, itemsCount := range []int{1e3, 1e4, 1e5, 1e6, 1e7} {
|
||||
start := uint64(time.Now().UnixNano())
|
||||
sa := createRangeSet(start, itemsCount)
|
||||
sb := createRangeSet(start, itemsCount)
|
||||
b.Run(fmt.Sprintf("items_%d", itemsCount), func(b *testing.B) {
|
||||
benchmarkIntersect(b, sa, sb)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func benchmarkIntersect(b *testing.B, sa, sb *Set) {
|
||||
b.ReportAllocs()
|
||||
b.SetBytes(int64(sa.Len() + sb.Len()))
|
||||
b.RunParallel(func(pb *testing.PB) {
|
||||
for pb.Next() {
|
||||
saCopy := sa.Clone()
|
||||
sbCopy := sb.Clone()
|
||||
saCopy.Intersect(sb)
|
||||
sbCopy.Intersect(sa)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func createRangeSet(start uint64, itemsCount int) *Set {
|
||||
var s Set
|
||||
var rng fastrand.RNG
|
||||
for i := 0; i < itemsCount; i++ {
|
||||
n := start | uint64(rng.Uint32())&mask
|
||||
n := start + uint64(i)
|
||||
s.Add(n)
|
||||
}
|
||||
return &s
|
||||
|
@ -172,8 +197,15 @@ func BenchmarkMapAddReuse(b *testing.B) {
|
|||
func BenchmarkSetHasHitRandomLastBits(b *testing.B) {
|
||||
const itemsCount = 1e5
|
||||
for _, lastBits := range []uint64{20, 24, 28, 32} {
|
||||
mask := (uint64(1) << lastBits) - 1
|
||||
b.Run(fmt.Sprintf("lastBits_%d", lastBits), func(b *testing.B) {
|
||||
s := createRandomSet(itemsCount, lastBits)
|
||||
start := uint64(time.Now().UnixNano())
|
||||
var s Set
|
||||
var rng fastrand.RNG
|
||||
for i := 0; i < itemsCount; i++ {
|
||||
n := start | (uint64(rng.Uint32()) & mask)
|
||||
s.Add(n)
|
||||
}
|
||||
a := s.AppendTo(nil)
|
||||
|
||||
b.ResetTimer()
|
||||
|
|
Loading…
Reference in a new issue