github.com/zuoyebang/bitalosdb@v1.1.1-0.20240516111551-79a8c4d8ce20/internal/batchskl/skl_test.go (about)

     1  // Copyright 2021 The Bitalosdb author(hustxrb@163.com) and other contributors.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //	http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package batchskl
    16  
    17  import (
    18  	"bytes"
    19  	"encoding/binary"
    20  	"fmt"
    21  	"testing"
    22  	"time"
    23  
    24  	"github.com/zuoyebang/bitalosdb/internal/base"
    25  
    26  	"github.com/stretchr/testify/require"
    27  	"golang.org/x/exp/rand"
    28  )
    29  
    30  type iterAdapter struct {
    31  	Iterator
    32  }
    33  
    34  func (i *iterAdapter) verify(key *base.InternalKey) bool {
    35  	valid := key != nil
    36  	if valid != i.Valid() {
    37  		panic(fmt.Sprintf("inconsistent valid: %t != %t", valid, i.Valid()))
    38  	}
    39  	if valid {
    40  		if base.InternalCompare(bytes.Compare, *key, i.Key()) != 0 {
    41  			panic(fmt.Sprintf("inconsistent key: %s != %s", *key, i.Key()))
    42  		}
    43  	}
    44  	return valid
    45  }
    46  
    47  func (i *iterAdapter) SeekGE(key []byte) bool {
    48  	return i.verify(i.Iterator.SeekGE(key))
    49  }
    50  
    51  func (i *iterAdapter) SeekLT(key []byte) bool {
    52  	return i.verify(i.Iterator.SeekLT(key))
    53  }
    54  
    55  func (i *iterAdapter) First() bool {
    56  	return i.verify(i.Iterator.First())
    57  }
    58  
    59  func (i *iterAdapter) Last() bool {
    60  	return i.verify(i.Iterator.Last())
    61  }
    62  
    63  func (i *iterAdapter) Next() bool {
    64  	return i.verify(i.Iterator.Next())
    65  }
    66  
    67  func (i *iterAdapter) Prev() bool {
    68  	return i.verify(i.Iterator.Prev())
    69  }
    70  
    71  func (i *iterAdapter) Key() base.InternalKey {
    72  	return *i.Iterator.Key()
    73  }
    74  
    75  func length(s *Skiplist) int {
    76  	count := 0
    77  
    78  	it := iterAdapter{s.NewIter(nil, nil)}
    79  	for valid := it.First(); valid; valid = it.Next() {
    80  		count++
    81  	}
    82  
    83  	return count
    84  }
    85  
    86  func lengthRev(s *Skiplist) int {
    87  	count := 0
    88  
    89  	it := iterAdapter{s.NewIter(nil, nil)}
    90  	for valid := it.Last(); valid; valid = it.Prev() {
    91  		count++
    92  	}
    93  
    94  	return count
    95  }
    96  
    97  func makeKey(s string) []byte {
    98  	return []byte(s)
    99  }
   100  
   101  type testStorage struct {
   102  	data []byte
   103  }
   104  
   105  func (d *testStorage) add(key string) uint32 {
   106  	offset := uint32(len(d.data))
   107  	d.data = append(d.data, uint8(base.InternalKeyKindSet))
   108  	var buf [binary.MaxVarintLen64]byte
   109  	n := binary.PutUvarint(buf[:], uint64(len(key)))
   110  	d.data = append(d.data, buf[:n]...)
   111  	d.data = append(d.data, key...)
   112  	return offset
   113  }
   114  
   115  func (d *testStorage) addBytes(key []byte) uint32 {
   116  	offset := uint32(len(d.data))
   117  	d.data = append(d.data, uint8(base.InternalKeyKindSet))
   118  	var buf [binary.MaxVarintLen64]byte
   119  	n := binary.PutUvarint(buf[:], uint64(len(key)))
   120  	d.data = append(d.data, buf[:n]...)
   121  	d.data = append(d.data, key...)
   122  	return offset
   123  }
   124  
   125  func newTestSkiplist(storage *testStorage) *Skiplist {
   126  	return NewSkiplist(&storage.data, base.DefaultComparer.Compare,
   127  		base.DefaultComparer.AbbreviatedKey)
   128  }
   129  
   130  func TestEmpty(t *testing.T) {
   131  	key := makeKey("aaa")
   132  	l := newTestSkiplist(&testStorage{})
   133  	it := iterAdapter{l.NewIter(nil, nil)}
   134  
   135  	require.False(t, it.Valid())
   136  
   137  	it.First()
   138  	require.False(t, it.Valid())
   139  
   140  	it.Last()
   141  	require.False(t, it.Valid())
   142  
   143  	require.False(t, it.SeekGE(key))
   144  	require.False(t, it.Valid())
   145  }
   146  
   147  func TestBasic(t *testing.T) {
   148  	d := &testStorage{}
   149  	l := newTestSkiplist(d)
   150  	it := iterAdapter{l.NewIter(nil, nil)}
   151  
   152  	require.Nil(t, l.Add(d.add("key1")))
   153  	require.Nil(t, l.Add(d.add("key2")))
   154  	require.Nil(t, l.Add(d.add("key3")))
   155  
   156  	require.True(t, it.SeekGE(makeKey("key")))
   157  	require.EqualValues(t, "key1", it.Key().UserKey)
   158  
   159  	require.True(t, it.SeekGE(makeKey("key1")))
   160  	require.EqualValues(t, "key1", it.Key().UserKey)
   161  
   162  	require.True(t, it.SeekGE(makeKey("key2")))
   163  	require.EqualValues(t, "key2", it.Key().UserKey)
   164  
   165  	require.True(t, it.SeekGE(makeKey("key3")))
   166  	require.EqualValues(t, "key3", it.Key().UserKey)
   167  
   168  	require.True(t, it.SeekGE(makeKey("key2")))
   169  	require.True(t, it.SeekGE(makeKey("key3")))
   170  }
   171  
   172  func TestSkiplistAdd(t *testing.T) {
   173  	d := &testStorage{}
   174  	l := newTestSkiplist(d)
   175  	it := iterAdapter{l.NewIter(nil, nil)}
   176  
   177  	require.Nil(t, l.Add(d.add("")))
   178  	require.EqualValues(t, []byte(nil), it.Key().UserKey)
   179  	require.True(t, it.First())
   180  	require.EqualValues(t, []byte{}, it.Key().UserKey)
   181  
   182  	require.Nil(t, l.Add(d.add("00002")))
   183  	require.True(t, it.SeekGE(makeKey("00002")))
   184  	require.EqualValues(t, "00002", it.Key().UserKey)
   185  
   186  	require.Nil(t, l.Add(d.add("00001")))
   187  	require.True(t, it.SeekGE(makeKey("00001")))
   188  	require.EqualValues(t, "00001", it.Key().UserKey)
   189  
   190  	require.Nil(t, l.Add(d.add("00004")))
   191  	require.True(t, it.SeekGE(makeKey("00004")))
   192  	require.EqualValues(t, "00004", it.Key().UserKey)
   193  
   194  	require.Nil(t, l.Add(d.add("00003")))
   195  	require.True(t, it.SeekGE(makeKey("00003")))
   196  	require.EqualValues(t, "00003", it.Key().UserKey)
   197  
   198  	require.Nil(t, l.Add(d.add("00002")))
   199  	require.Equal(t, 6, length(l))
   200  	require.Equal(t, 6, lengthRev(l))
   201  }
   202  
   203  func TestIteratorNext(t *testing.T) {
   204  	const n = 100
   205  	d := &testStorage{}
   206  	l := newTestSkiplist(d)
   207  	it := iterAdapter{l.NewIter(nil, nil)}
   208  
   209  	require.False(t, it.Valid())
   210  
   211  	it.First()
   212  	require.False(t, it.Valid())
   213  
   214  	for i := n - 1; i >= 0; i-- {
   215  		require.Nil(t, l.Add(d.add(fmt.Sprintf("%05d", i))))
   216  	}
   217  
   218  	it.First()
   219  	for i := 0; i < n; i++ {
   220  		require.True(t, it.Valid())
   221  		require.EqualValues(t, fmt.Sprintf("%05d", i), it.Key().UserKey)
   222  		it.Next()
   223  	}
   224  	require.False(t, it.Valid())
   225  }
   226  
   227  func TestIteratorPrev(t *testing.T) {
   228  	const n = 100
   229  	d := &testStorage{}
   230  	l := newTestSkiplist(d)
   231  	it := iterAdapter{l.NewIter(nil, nil)}
   232  
   233  	require.False(t, it.Valid())
   234  
   235  	it.Last()
   236  	require.False(t, it.Valid())
   237  
   238  	for i := 0; i < n; i++ {
   239  		l.Add(d.add(fmt.Sprintf("%05d", i)))
   240  	}
   241  
   242  	it.Last()
   243  	for i := n - 1; i >= 0; i-- {
   244  		require.True(t, it.Valid())
   245  		require.EqualValues(t, fmt.Sprintf("%05d", i), string(it.Key().UserKey))
   246  		it.Prev()
   247  	}
   248  	require.False(t, it.Valid())
   249  }
   250  
   251  func TestIteratorSeekGE(t *testing.T) {
   252  	const n = 1000
   253  	d := &testStorage{}
   254  	l := newTestSkiplist(d)
   255  	it := iterAdapter{l.NewIter(nil, nil)}
   256  
   257  	require.False(t, it.Valid())
   258  	it.First()
   259  	require.False(t, it.Valid())
   260  
   261  	for i := n - 1; i >= 0; i-- {
   262  		require.Nil(t, l.Add(d.add(fmt.Sprintf("%05d", i*10+1000))))
   263  	}
   264  
   265  	require.True(t, it.SeekGE(makeKey("")))
   266  	require.True(t, it.Valid())
   267  	require.EqualValues(t, "01000", it.Key().UserKey)
   268  
   269  	require.True(t, it.SeekGE(makeKey("01000")))
   270  	require.True(t, it.Valid())
   271  	require.EqualValues(t, "01000", it.Key().UserKey)
   272  
   273  	require.True(t, it.SeekGE(makeKey("01005")))
   274  	require.True(t, it.Valid())
   275  	require.EqualValues(t, "01010", it.Key().UserKey)
   276  
   277  	require.True(t, it.SeekGE(makeKey("01010")))
   278  	require.True(t, it.Valid())
   279  	require.EqualValues(t, "01010", it.Key().UserKey)
   280  
   281  	require.False(t, it.SeekGE(makeKey("99999")))
   282  	require.False(t, it.Valid())
   283  
   284  	require.Nil(t, l.Add(d.add("")))
   285  	require.True(t, it.SeekGE([]byte{}))
   286  	require.True(t, it.Valid())
   287  
   288  	require.True(t, it.SeekGE(makeKey("")))
   289  	require.True(t, it.Valid())
   290  }
   291  
   292  func TestIteratorSeekLT(t *testing.T) {
   293  	const n = 100
   294  	d := &testStorage{}
   295  	l := newTestSkiplist(d)
   296  	it := iterAdapter{l.NewIter(nil, nil)}
   297  
   298  	require.False(t, it.Valid())
   299  	it.First()
   300  	require.False(t, it.Valid())
   301  
   302  	for i := n - 1; i >= 0; i-- {
   303  		require.Nil(t, l.Add(d.add(fmt.Sprintf("%05d", i*10+1000))))
   304  	}
   305  
   306  	require.False(t, it.SeekLT(makeKey("")))
   307  	require.False(t, it.Valid())
   308  
   309  	require.False(t, it.SeekLT(makeKey("01000")))
   310  	require.False(t, it.Valid())
   311  
   312  	require.True(t, it.SeekLT(makeKey("01001")))
   313  	require.EqualValues(t, "01000", it.Key().UserKey)
   314  	require.True(t, it.Valid())
   315  
   316  	require.True(t, it.SeekLT(makeKey("01005")))
   317  	require.EqualValues(t, "01000", it.Key().UserKey)
   318  	require.True(t, it.Valid())
   319  
   320  	require.True(t, it.SeekLT(makeKey("01991")))
   321  	require.EqualValues(t, "01990", it.Key().UserKey)
   322  	require.True(t, it.Valid())
   323  
   324  	require.True(t, it.SeekLT(makeKey("99999")))
   325  	require.True(t, it.Valid())
   326  	require.EqualValues(t, "01990", it.Key().UserKey)
   327  
   328  	require.Nil(t, l.Add(d.add("")))
   329  	require.False(t, it.SeekLT([]byte{}))
   330  	require.False(t, it.Valid())
   331  	require.True(t, it.SeekLT(makeKey("\x01")))
   332  	require.True(t, it.Valid())
   333  	require.EqualValues(t, "", it.Key().UserKey)
   334  }
   335  
   336  func TestIteratorBounds(t *testing.T) {
   337  	d := &testStorage{}
   338  	l := newTestSkiplist(d)
   339  	for i := 1; i < 10; i++ {
   340  		require.NoError(t, l.Add(d.add(fmt.Sprintf("%05d", i))))
   341  	}
   342  
   343  	it := iterAdapter{l.NewIter(makeKey("00003"), makeKey("00007"))}
   344  
   345  	for i := 3; i <= 6; i++ {
   346  		key := makeKey(fmt.Sprintf("%05d", i))
   347  		require.True(t, it.SeekGE(key))
   348  		require.EqualValues(t, string(key), string(it.Key().UserKey))
   349  	}
   350  
   351  	for i := 1; i < 3; i++ {
   352  		key := makeKey(fmt.Sprintf("%05d", i))
   353  		require.True(t, it.SeekGE(key))
   354  		require.EqualValues(t, string(key), string(it.Key().UserKey))
   355  	}
   356  
   357  	for i := 7; i < 10; i++ {
   358  		key := makeKey(fmt.Sprintf("%05d", i))
   359  		require.False(t, it.SeekGE(key))
   360  	}
   361  
   362  	require.True(t, it.SeekGE(makeKey("00006")))
   363  	require.EqualValues(t, "00006", it.Key().UserKey)
   364  
   365  	require.False(t, it.Next())
   366  
   367  	for i := 4; i <= 7; i++ {
   368  		key := makeKey(fmt.Sprintf("%05d", i))
   369  		require.True(t, it.SeekLT(key))
   370  		require.EqualValues(t, fmt.Sprintf("%05d", i-1), string(it.Key().UserKey))
   371  	}
   372  
   373  	for i := 8; i < 9; i++ {
   374  		key := makeKey(fmt.Sprintf("%05d", i))
   375  		require.True(t, it.SeekLT(key))
   376  		require.EqualValues(t, fmt.Sprintf("%05d", i-1), string(it.Key().UserKey))
   377  	}
   378  
   379  	for i := 1; i < 4; i++ {
   380  		key := makeKey(fmt.Sprintf("%05d", i))
   381  		require.False(t, it.SeekLT(key))
   382  	}
   383  
   384  	require.True(t, it.SeekLT(makeKey("00004")))
   385  	require.EqualValues(t, "00003", it.Key().UserKey)
   386  
   387  	require.False(t, it.Prev())
   388  }
   389  
   390  func randomKey(rng *rand.Rand, b []byte) []byte {
   391  	key := rng.Uint32()
   392  	key2 := rng.Uint32()
   393  	binary.LittleEndian.PutUint32(b, key)
   394  	binary.LittleEndian.PutUint32(b[4:], key2)
   395  	return b
   396  }
   397  
   398  func BenchmarkReadWrite(b *testing.B) {
   399  	for i := 0; i <= 10; i++ {
   400  		readFrac := float32(i) / 10.0
   401  		b.Run(fmt.Sprintf("frac_%d", i*10), func(b *testing.B) {
   402  			var buf [8]byte
   403  			d := &testStorage{
   404  				data: make([]byte, 0, b.N*10),
   405  			}
   406  			l := newTestSkiplist(d)
   407  			it := l.NewIter(nil, nil)
   408  			rng := rand.New(rand.NewSource(uint64(time.Now().UnixNano())))
   409  
   410  			b.ResetTimer()
   411  			for i := 0; i < b.N; i++ {
   412  				key := randomKey(rng, buf[:])
   413  				if rng.Float32() < readFrac {
   414  					_ = it.SeekGE(key)
   415  				} else {
   416  					offset := d.addBytes(buf[:])
   417  					_ = l.Add(offset)
   418  				}
   419  			}
   420  			b.StopTimer()
   421  		})
   422  	}
   423  }
   424  
   425  func BenchmarkOrderedWrite(b *testing.B) {
   426  	var buf [8]byte
   427  	d := &testStorage{
   428  		data: make([]byte, 0, b.N*10),
   429  	}
   430  	l := newTestSkiplist(d)
   431  
   432  	b.ResetTimer()
   433  	for i := 0; i < b.N; i++ {
   434  		binary.BigEndian.PutUint64(buf[:], uint64(i))
   435  		offset := d.addBytes(buf[:])
   436  		_ = l.Add(offset)
   437  	}
   438  }
   439  
   440  func BenchmarkIterNext(b *testing.B) {
   441  	var buf [8]byte
   442  	d := &testStorage{
   443  		data: make([]byte, 0, 64<<10),
   444  	}
   445  	l := newTestSkiplist(d)
   446  
   447  	rng := rand.New(rand.NewSource(uint64(time.Now().UnixNano())))
   448  	for len(d.data)+20 < cap(d.data) {
   449  		key := randomKey(rng, buf[:])
   450  		offset := d.addBytes(key)
   451  		_ = l.Add(offset)
   452  	}
   453  
   454  	it := l.NewIter(nil, nil)
   455  	b.ResetTimer()
   456  	for i := 0; i < b.N; i++ {
   457  		if !it.Valid() {
   458  			it.First()
   459  		}
   460  		it.Next()
   461  	}
   462  }
   463  
   464  func BenchmarkIterPrev(b *testing.B) {
   465  	var buf [8]byte
   466  	d := &testStorage{
   467  		data: make([]byte, 0, 64<<10),
   468  	}
   469  	l := newTestSkiplist(d)
   470  
   471  	rng := rand.New(rand.NewSource(uint64(time.Now().UnixNano())))
   472  	for len(d.data)+20 < cap(d.data) {
   473  		key := randomKey(rng, buf[:])
   474  		offset := d.addBytes(key)
   475  		_ = l.Add(offset)
   476  	}
   477  
   478  	it := l.NewIter(nil, nil)
   479  	b.ResetTimer()
   480  	for i := 0; i < b.N; i++ {
   481  		if !it.Valid() {
   482  			it.Last()
   483  		}
   484  		it.Prev()
   485  	}
   486  }