github.com/pingcap/badger@v1.5.1-0.20230103063557-828f39b09b6d/surf/bits_vec_test.go (about) 1 package surf 2 3 import ( 4 "testing" 5 6 "github.com/stretchr/testify/require" 7 "github.com/stretchr/testify/suite" 8 ) 9 10 type BitsVecTestSuite struct { 11 suite.Suite 12 } 13 14 func TestBitsVecTestSuite(t *testing.T) { 15 suite.Run(t, new(BitsVecTestSuite)) 16 } 17 18 func TestSelect64(t *testing.T) { 19 cases := [][]uint64{ 20 {0, 3, 1}, 21 {33, 3 << 32, 2}, 22 {63, 1 << 63, 1}, 23 {9, 0b11101011001010101, 5}, 24 } 25 t.Run("broadword", func(t *testing.T) { 26 for _, c := range cases { 27 require.EqualValues(t, c[0], select64Broadword(c[1], int64(c[2]))) 28 } 29 }) 30 t.Run("bmi2", func(t *testing.T) { 31 for _, c := range cases { 32 require.EqualValues(t, c[0], select64(c[1], int64(c[2]))) 33 } 34 }) 35 t.Run("fallback", func(t *testing.T) { 36 hasBMI2 = false 37 for _, c := range cases { 38 require.EqualValues(t, c[0], select64(c[1], int64(c[2]))) 39 } 40 hasBMI2 = true 41 }) 42 } 43 44 func TestBitSetAndRead(t *testing.T) { 45 for i := 0; i < 128; i++ { 46 var bits [2]uint64 47 setBit(bits[:], uint32(i)) 48 require.True(t, readBit(bits[:], uint32(i))) 49 } 50 } 51 52 func TestPopCount(t *testing.T) { 53 cases := [][]int{ 54 {0, 1, 2, 3, 4}, 55 {0, 2, 16, 17, 33, 62}, 56 {63, 64, 65, 66}, 57 {63, 127}, 58 {64}, 59 } 60 61 for _, c := range cases { 62 bits, nbits := constructBits(c) 63 require.EqualValues(t, len(c), popcountBlock(bits, 0, nbits)) 64 require.EqualValues(t, len(c)-1, popcountBlock(bits, 0, nbits-1)) 65 } 66 } 67 68 func TestBitVector(t *testing.T) { 69 cases := [][][]int{ 70 { 71 {0, 1, 24, 60}, 72 {0, 31, 127}, 73 {4}, 74 }, 75 { 76 {23, 44}, 77 {0, 122, 123, 456}, 78 {0, 1, 2, 3, 4, 5, 62, 63}, 79 {127, 128, 129, 255, 257}, 80 }, 81 } 82 83 for _, c := range cases { 84 var vec bitVector 85 numBitsPerLevel := make([]uint32, len(c)) 86 bitsPerLevel := make([][]uint64, len(c)) 87 for l, p := range c { 88 bitsPerLevel[l], numBitsPerLevel[l] = constructBits(p) 89 } 90 vec.Init(bitsPerLevel, numBitsPerLevel) 91 92 off := uint32(0) 93 for l, p := range c { 94 for i, pos := range p { 95 idx := off + uint32(pos) 96 97 require.True(t, vec.IsSet(idx)) 98 99 dist := vec.DistanceToNextSetBit(idx) 100 var expected int 101 if i == len(p)-1 { 102 if l < len(c)-1 { 103 expected = c[l+1][0] + 1 104 } else { 105 expected = 1 106 } 107 } else { 108 expected = p[i+1] - pos 109 } 110 require.EqualValues(t, expected, dist) 111 112 dist = vec.DistanceToPrevSetBit(idx) 113 if i == 0 { 114 expected = pos + 1 115 } else { 116 expected = pos - p[i-1] 117 } 118 require.EqualValuesf(t, expected, dist, "level %d, pos %d", l, pos) 119 } 120 off += numBitsPerLevel[l] 121 } 122 } 123 } 124 125 func TestSelectVector(t *testing.T) { 126 cases := [][][]int{ 127 { 128 {0, 1, 24, 60}, 129 {0, 31, 127}, 130 {4}, 131 }, 132 { 133 {0, 23, 44}, 134 {0, 122, 123, 456}, 135 {0, 1, 2, 3, 4, 5, 62, 63}, 136 {127, 128, 129, 255, 257}, 137 }, 138 } 139 140 for _, c := range cases { 141 var vec selectVector 142 numBitsPerLevel := make([]uint32, len(c)) 143 bitsPerLevel := make([][]uint64, len(c)) 144 for l, p := range c { 145 bitsPerLevel[l], numBitsPerLevel[l] = constructBits(p) 146 } 147 vec.Init(bitsPerLevel, numBitsPerLevel) 148 149 off, rank := uint32(0), uint32(1) 150 for l, p := range c { 151 for _, pos := range p { 152 idx := off + uint32(pos) 153 sr := vec.Select(rank) 154 155 require.EqualValuesf(t, idx, sr, "level: %d, pos: %d, rank: %d", l, pos, rank) 156 rank++ 157 } 158 off += numBitsPerLevel[l] 159 } 160 } 161 } 162 163 func constructBits(sets []int) ([]uint64, uint32) { 164 nbits := sets[len(sets)-1] + 1 165 words := nbits / wordSize 166 if nbits%wordSize != 0 { 167 words++ 168 } 169 bits := make([]uint64, words) 170 for _, i := range sets { 171 setBit(bits, uint32(i)) 172 } 173 return bits, uint32(nbits) 174 } 175 176 func BenchmarkSelect64(b *testing.B) { 177 b.Run("BMI2", func(b *testing.B) { 178 for n := 0; n < b.N; n++ { 179 select64(0b01101010101011110111101011001010101, 10) 180 } 181 }) 182 183 b.Run("fallback", func(b *testing.B) { 184 for n := 0; n < b.N; n++ { 185 select64Broadword(0b01101010101011110111101011001010101, 10) 186 } 187 }) 188 } 189 190 func TestLabelVecSearch(t *testing.T) { 191 labels := [][]byte{ 192 {1}, 193 {2, 3}, 194 {4, 5, 6}, 195 {labelTerminator, 7, 8, 9}, 196 } 197 v := new(labelVector) 198 v.Init(labels, 0, uint32(len(labels))) 199 labelShouldExist := func(k byte, start, size, pos uint32) { 200 r, ok := v.Search(k, start, size) 201 require.True(t, ok) 202 require.Equal(t, pos, r) 203 } 204 labelShouldExist(1, 0, 1, 0) 205 labelShouldExist(3, 0, 5, 2) 206 labelShouldExist(5, 3, 7, 4) 207 labelShouldExist(7, 6, 8, 7) 208 }