github.com/petermattis/pebble@v0.0.0-20190905164901-ab51a2166067/internal/batchskl/skl_test.go (about)

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