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  }