Bucketed NSet

This commit is contained in:
bloeys
2022-06-10 11:00:26 +04:00
parent c1de522f10
commit 52e80d82e4
6 changed files with 193 additions and 104 deletions

View File

@ -1,6 +1,8 @@
package nset_test
import (
"fmt"
"math"
"math/rand"
"testing"
@ -13,27 +15,61 @@ const (
)
var (
dump int
dump int
fullRangeNSet *nset.NSet[uint32]
)
func TestNSet(t *testing.T) {
n := nset.NewNSet[uint32]()
IsEq(t, 1, cap(n.Data))
n.Add(0)
n.Add(1)
n.Add(63)
n.Add(math.MaxUint32)
AllTrue(t, n.Contains(0), n.Contains(1), n.Contains(63), !n.Contains(10), !n.Contains(599))
AllTrue(t, n.Contains(0), n.Contains(1), n.Contains(63), n.Contains(math.MaxUint32), !n.Contains(10), !n.Contains(599))
AllTrue(t, n.ContainsAll(0, 1, 63), !n.ContainsAll(9, 0, 1), !n.ContainsAll(0, 1, 63, 99))
AllTrue(t, n.ContainsAny(0, 1, 63), n.ContainsAny(9, 99, 999, 1), !n.ContainsAny(9, 99, 999))
IsEq(t, nset.BucketCount-1, n.GetBucketIndex(math.MaxUint32))
IsEq(t, math.MaxUint32/64/nset.BucketCount, n.GetStorageUnitIndex(math.MaxUint32))
n.Remove(1)
AllTrue(t, n.Contains(0), n.Contains(63), !n.Contains(1))
}
func TestNSetFullRange(t *testing.T) {
if fullRangeNSet == nil {
fullRangeNSet = nset.NewNSet[uint32]()
println("Adding all uint32 to NSet...")
for i := uint32(0); i < math.MaxUint32; i++ {
fullRangeNSet.Add(i)
if i%1_000_000_000 == 0 {
fmt.Printf("i=%d billion\n", i)
}
}
fullRangeNSet.Add(math.MaxUint32)
}
n := fullRangeNSet
IsEq(t, 67_108_864, n.StorageUnitCount)
for i := 0; i < len(n.Buckets); i++ {
b := &n.Buckets[i]
IsEq(t, 524288, b.StorageUnitCount)
for j := 0; j < len(b.Data); j++ {
if b.Data[j] != math.MaxUint64 {
t.Errorf("Error: storage unit is NOT equal to MaxUint64 (i=%d,j=%d)! Expected math.MaxUint64 but got '%08b'\n",
i,
j,
b.Data[j])
}
}
}
n = nset.NewNSetWithMax[uint32](100)
IsEq(t, 2, cap(n.Data))
}
func AllTrue(t *testing.T, values ...bool) bool {
@ -85,6 +121,16 @@ func BenchmarkNSetAddRand(b *testing.B) {
}
}
func BenchmarkNSetAddRandNoSizeLimit(b *testing.B) {
n := nset.NewNSet[uint32]()
rand.Seed(RandSeed)
for i := 0; i < b.N; i++ {
n.Add(rand.Uint32())
}
}
func BenchmarkMapAddRand(b *testing.B) {
hMap := map[uint32]struct{}{}
@ -95,44 +141,6 @@ func BenchmarkMapAddRand(b *testing.B) {
}
}
func BenchmarkNSetAddPresized(b *testing.B) {
n := nset.NewNSetWithMax[uint32](maxBenchSize - 1)
for i := uint32(0); i < uint32(b.N); i++ {
n.Add(i % maxBenchSize)
}
}
func BenchmarkMapAddPresized(b *testing.B) {
hMap := make(map[uint32]struct{}, maxBenchSize-1)
for i := uint32(0); i < uint32(b.N); i++ {
hMap[i%maxBenchSize] = struct{}{}
}
}
func BenchmarkNSetAddPresizedRand(b *testing.B) {
n := nset.NewNSetWithMax[uint32](maxBenchSize - 1)
rand.Seed(RandSeed)
for i := 0; i < b.N; i++ {
n.Add(rand.Uint32() % maxBenchSize)
}
}
func BenchmarkMapAddPresizedRand(b *testing.B) {
hMap := make(map[uint32]struct{}, maxBenchSize-1)
rand.Seed(RandSeed)
for i := 0; i < b.N; i++ {
hMap[rand.Uint32()%maxBenchSize] = struct{}{}
}
}
func BenchmarkNSetContains(b *testing.B) {
//Init
@ -202,6 +210,39 @@ func BenchmarkNSetContainsRand(b *testing.B) {
dump = found
}
func BenchmarkNSetContainsRandFullRange(b *testing.B) {
//Init
if fullRangeNSet == nil {
b.StopTimer()
fullRangeNSet = nset.NewNSet[uint32]()
println("Preparing full range NSet...")
for i := uint32(0); i < math.MaxUint32; i++ {
fullRangeNSet.Add(i)
}
fullRangeNSet.Add(math.MaxUint32)
b.StartTimer()
}
n := fullRangeNSet
//Work
found := 0
rand.Seed(RandSeed)
for i := 0; i < b.N; i++ {
randVal := rand.Uint32()
if n.Contains(randVal) {
found++
}
}
dump = found
}
func BenchmarkMapContainsRand(b *testing.B) {
//Init