lib/uint64set: improve benchmark for Set.Intersect

This commit is contained in:
Aliaksandr Valialkin 2020-01-17 16:07:49 +02:00
parent d0d258b314
commit cd53f7d177
2 changed files with 86 additions and 34 deletions

View file

@ -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

View file

@ -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()