mirror of
https://github.com/VictoriaMetrics/VictoriaMetrics.git
synced 2025-03-21 15:45:01 +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 {
|
if n := s3.Len(); n != expectedLen {
|
||||||
t.Fatalf("unexpected s3.Len() after union with empty set; got %d; want %d", 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
|
// Verify intersect
|
||||||
{
|
{
|
||||||
const intersectOffset = 12345
|
// Verify s1.Intersect(s2) and s2.Intersect(s1)
|
||||||
var s1, s2 Set
|
var s1, s2 Set
|
||||||
for i := 0; i < itemsCount; i++ {
|
for _, intersectOffset := range []uint64{123, 12345, 1<<32 + 4343} {
|
||||||
s1.Add(uint64(i) + offset)
|
s1 = Set{}
|
||||||
s2.Add(uint64(i) + offset + intersectOffset)
|
s2 = Set{}
|
||||||
}
|
for i := 0; i < itemsCount; i++ {
|
||||||
s1.Intersect(&s2)
|
s1.Add(uint64(i) + offset)
|
||||||
expectedLen := 0
|
s2.Add(uint64(i) + offset + intersectOffset)
|
||||||
if itemsCount > intersectOffset {
|
}
|
||||||
expectedLen = itemsCount - intersectOffset
|
expectedLen := 0
|
||||||
}
|
if uint64(itemsCount) > intersectOffset {
|
||||||
if n := s1.Len(); n != expectedLen {
|
expectedLen = int(uint64(itemsCount) - intersectOffset)
|
||||||
t.Fatalf("unexpected s1.Len() after intersect; got %d; want %d", n, expectedLen)
|
}
|
||||||
|
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.
|
// Verify intersect on empty set.
|
||||||
var s3 Set
|
var s3 Set
|
||||||
s2.Intersect(&s3)
|
s2.Intersect(&s3)
|
||||||
expectedLen = 0
|
expectedLen := 0
|
||||||
if n := s2.Len(); n != 0 {
|
if n := s2.Len(); n != expectedLen {
|
||||||
t.Fatalf("unexpected s3.Len() after intersect with empty set; got %d; want %d", 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
|
// Verify subtract
|
||||||
|
|
|
@ -8,31 +8,56 @@ import (
|
||||||
"github.com/valyala/fastrand"
|
"github.com/valyala/fastrand"
|
||||||
)
|
)
|
||||||
|
|
||||||
func BenchmarkIntersect(b *testing.B) {
|
func BenchmarkIntersectNoOverlap(b *testing.B) {
|
||||||
const itemsCount = 3e6
|
for _, itemsCount := range []int{1e3, 1e4, 1e5, 1e6, 1e7} {
|
||||||
for _, lastBits := range []uint64{20, 24, 28, 32} {
|
start := uint64(time.Now().UnixNano())
|
||||||
sa := createRandomSet(itemsCount, lastBits)
|
sa := createRangeSet(start, itemsCount)
|
||||||
sb := createRandomSet(itemsCount, lastBits)
|
sb := createRangeSet(start+uint64(itemsCount), itemsCount)
|
||||||
b.Run(fmt.Sprintf("lastBits_%d", lastBits), func(b *testing.B) {
|
b.Run(fmt.Sprintf("items_%d", itemsCount), func(b *testing.B) {
|
||||||
b.ReportAllocs()
|
benchmarkIntersect(b, sa, sb)
|
||||||
b.SetBytes(int64(sa.Len()+sb.Len()))
|
|
||||||
b.RunParallel(func(pb *testing.PB) {
|
|
||||||
for pb.Next() {
|
|
||||||
saCopy := sa.Clone()
|
|
||||||
saCopy.Intersect(sb)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func createRandomSet(itemsCount int, lastBits uint64) *Set {
|
func BenchmarkIntersectPartialOverlap(b *testing.B) {
|
||||||
mask := (uint64(1) << lastBits) - 1
|
for _, itemsCount := range []int{1e3, 1e4, 1e5, 1e6, 1e7} {
|
||||||
start := uint64(time.Now().UnixNano())
|
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 s Set
|
||||||
var rng fastrand.RNG
|
|
||||||
for i := 0; i < itemsCount; i++ {
|
for i := 0; i < itemsCount; i++ {
|
||||||
n := start | uint64(rng.Uint32())&mask
|
n := start + uint64(i)
|
||||||
s.Add(n)
|
s.Add(n)
|
||||||
}
|
}
|
||||||
return &s
|
return &s
|
||||||
|
@ -172,8 +197,15 @@ func BenchmarkMapAddReuse(b *testing.B) {
|
||||||
func BenchmarkSetHasHitRandomLastBits(b *testing.B) {
|
func BenchmarkSetHasHitRandomLastBits(b *testing.B) {
|
||||||
const itemsCount = 1e5
|
const itemsCount = 1e5
|
||||||
for _, lastBits := range []uint64{20, 24, 28, 32} {
|
for _, lastBits := range []uint64{20, 24, 28, 32} {
|
||||||
|
mask := (uint64(1) << lastBits) - 1
|
||||||
b.Run(fmt.Sprintf("lastBits_%d", lastBits), func(b *testing.B) {
|
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)
|
a := s.AppendTo(nil)
|
||||||
|
|
||||||
b.ResetTimer()
|
b.ResetTimer()
|
||||||
|
|
Loading…
Reference in a new issue