package pmap import ( "fmt" "testing" ) func hash(k Key) uint32 { //u := uint(k.(int))*6364136223846793005 + 1 //return uint32(u >> 32) u := uint(k) //u := uint(k.(int)) return uint32(u + u>>32) } // FIXME: collisions can cause allocations during Get func TestPmap(t *testing.T) { p := New(hash) const numElems = 100 for i := range iter(numElems) { p = p.Set(i, i) } if p.Len() != numElems { t.Fatalf("Len() = %v, want %v", p.Len(), numElems) } for i := range iter(numElems) { v, ok := p.Get(i) if v != i || !ok { t.Errorf("Get(%d) = %v %v, want %v %v", i, v, ok, i, true) } } fmt.Print(p.(pmap).stats()) } func BenchmarkGet(b *testing.B) { b.Run("size=10", func(b *testing.B) { benchmarkGet(b, 10) }) b.Run("size=100", func(b *testing.B) { benchmarkGet(b, 100) }) b.Run("size=1000", func(b *testing.B) { benchmarkGet(b, 1000) }) b.Run("size=10000", func(b *testing.B) { benchmarkGet(b, 10000) }) //b.Run("size=100000", func(b *testing.B) { benchmarkGet(b, 100000) }) //b.Run("size=1000000", func(b *testing.B) { benchmarkGet(b, 1000000) }) } func BenchmarkGetAbsent(b *testing.B) { b.Run("size=10", func(b *testing.B) { benchmarkGetAbsent(b, 10) }) b.Run("size=100", func(b *testing.B) { benchmarkGetAbsent(b, 100) }) b.Run("size=1000", func(b *testing.B) { benchmarkGetAbsent(b, 1000) }) b.Run("size=10000", func(b *testing.B) { benchmarkGetAbsent(b, 10000) }) } func benchmarkGet(b *testing.B, numElems int) { p := New(hash) for i := range iter(numElems) { p = p.Set(i, i) } if p.Len() != numElems { b.Fatalf("Len() = %v, want %v", p.Len(), numElems) } b.ResetTimer() i := 0 for range iter(b.N) { v, ok := p.Get(i) if v != i || !ok { b.Errorf("Get(%d) = %v %v, want %v %v", i, v, ok, i, true) } i++ if i >= numElems { i = 0 } } } func benchmarkGetAbsent(b *testing.B, numElems int) { p := New(hash) for i := range iter(numElems) { p = p.Set(i-numElems, i) } if p.Len() != numElems { b.Fatalf("Len() = %v, want %v", p.Len(), numElems) } b.ResetTimer() i := 0 for range iter(b.N) { v, ok := p.Get(i) if ok { b.Errorf("Get(%d) = %v %v, want %v %v", i, v, ok, 0, false) } i++ } } func iter(n int) []struct{} { return make([]struct{}, n) } func BenchmarkHmapGet_baseline(b *testing.B) { b.Run("size=10", func(b *testing.B) { benchmarkHmapGet(b, 10) }) b.Run("size=100", func(b *testing.B) { benchmarkHmapGet(b, 100) }) b.Run("size=1000", func(b *testing.B) { benchmarkHmapGet(b, 1000) }) b.Run("size=10000", func(b *testing.B) { benchmarkHmapGet(b, 10000) }) b.Run("size=100000", func(b *testing.B) { benchmarkHmapGet(b, 100000) }) b.Run("size=1000000", func(b *testing.B) { benchmarkHmapGet(b, 1000000) }) } func benchmarkHmapGet(b *testing.B, numElems int) { h := make(map[int]Value) for i := range iter(numElems) { h[i] = i } if len(h) != numElems { b.Fatalf("Len() = %v, want %v", len(h), numElems) } b.ResetTimer() i := 0 for range iter(b.N) { v, ok := h[i] if v != i || !ok { b.Errorf("h[%d] = %v %v, want %v %v", i, v, ok, i, true) } i++ if i >= numElems { i = 0 } } } func BenchmarkSet(b *testing.B) { b.Run("size=10", func(b *testing.B) { benchmarkSet(b, 10) }) b.Run("size=100", func(b *testing.B) { benchmarkSet(b, 100) }) b.Run("size=1000", func(b *testing.B) { benchmarkSet(b, 1000) }) b.Run("size=10000", func(b *testing.B) { benchmarkSet(b, 10000) }) if !testing.Short() { b.Run("size=100000", func(b *testing.B) { benchmarkSet(b, 100000) }) } } func benchmarkSet(b *testing.B, numElems int) { p := New(hash) for i := range iter(numElems) { p = p.Set(i, i) } if p.Len() != numElems { b.Fatalf("Len() = %v, want %v", p.Len(), numElems) } b.ResetTimer() for i := range iter(b.N) { k := i + numElems _ = p.Set(k, k) } } func BenchmarkHmapSet_baseline(b *testing.B) { b.Run("size=10", func(b *testing.B) { benchmarkHmapSet(b, 10) }) b.Run("size=100", func(b *testing.B) { benchmarkHmapSet(b, 100) }) b.Run("size=1000", func(b *testing.B) { benchmarkHmapSet(b, 1000) }) b.Run("size=10000", func(b *testing.B) { benchmarkHmapSet(b, 10000) }) if !testing.Short() { b.Run("size=100000", func(b *testing.B) { benchmarkHmapSet(b, 100000) }) } } func benchmarkHmapSet(b *testing.B, numElems int) { h := make(map[int]Value) for i := range iter(numElems) { h[i] = i } if len(h) != numElems { b.Fatalf("Len() = %v, want %v", len(h), numElems) } b.ResetTimer() for i := range iter(b.N) { k := i + numElems h[k] = k delete(h, k) } } func TestBitmap(t *testing.T) { n := node{bitmap: 0xff0a} const x = -1 want := []int{x, 0, x, 1, x, x, x, x, 2, 3, 4, 5, 6, 7, 8, 9} for i, j := range want { if j == x { continue } m := bitmask(uint32(i)) if got := n.index(m); got != j { t.Errorf("got %v, want %v", got, j) } } }