github.com/petermattis/pebble@v0.0.0-20190905164901-ab51a2166067/internal/arenaskl/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 arenaskl
    19  
    20  import (
    21  	"bytes"
    22  	"encoding/binary"
    23  	"fmt"
    24  	"strconv"
    25  	"sync"
    26  	"sync/atomic"
    27  	"testing"
    28  	"time"
    29  
    30  	"github.com/petermattis/pebble/internal/base"
    31  	"github.com/stretchr/testify/require"
    32  	"golang.org/x/exp/rand"
    33  )
    34  
    35  const arenaSize = 1 << 20
    36  
    37  // iterAdapter adapts the new Iterator API which returns the key and value from
    38  // positioning methods (Seek*, First, Last, Next, Prev) to the old API which
    39  // returned a boolean corresponding to Valid. Only used by test code.
    40  type iterAdapter struct {
    41  	*Iterator
    42  }
    43  
    44  func (i *iterAdapter) verify(key *base.InternalKey, val []byte) bool {
    45  	valid := key != nil
    46  	if valid != i.Valid() {
    47  		panic(fmt.Sprintf("inconsistent valid: %t != %t", valid, i.Valid()))
    48  	}
    49  	if valid {
    50  		if base.InternalCompare(bytes.Compare, *key, i.Key()) != 0 {
    51  			panic(fmt.Sprintf("inconsistent key: %s != %s", *key, i.Key()))
    52  		}
    53  		if !bytes.Equal(val, i.Value()) {
    54  			panic(fmt.Sprintf("inconsistent value: [% x] != [% x]", val, i.Value()))
    55  		}
    56  	}
    57  	return valid
    58  }
    59  
    60  func (i *iterAdapter) SeekGE(key []byte) bool {
    61  	return i.verify(i.Iterator.SeekGE(key))
    62  }
    63  
    64  func (i *iterAdapter) SeekPrefixGE(prefix, key []byte) bool {
    65  	return i.verify(i.Iterator.SeekPrefixGE(prefix, key))
    66  }
    67  
    68  func (i *iterAdapter) SeekLT(key []byte) bool {
    69  	return i.verify(i.Iterator.SeekLT(key))
    70  }
    71  
    72  func (i *iterAdapter) First() bool {
    73  	return i.verify(i.Iterator.First())
    74  }
    75  
    76  func (i *iterAdapter) Last() bool {
    77  	return i.verify(i.Iterator.Last())
    78  }
    79  
    80  func (i *iterAdapter) Next() bool {
    81  	return i.verify(i.Iterator.Next())
    82  }
    83  
    84  func (i *iterAdapter) Prev() bool {
    85  	return i.verify(i.Iterator.Prev())
    86  }
    87  
    88  func (i *iterAdapter) Key() base.InternalKey {
    89  	return *i.Iterator.Key()
    90  }
    91  
    92  func makeIntKey(i int) base.InternalKey {
    93  	return base.InternalKey{UserKey: []byte(fmt.Sprintf("%05d", i))}
    94  }
    95  
    96  func makeKey(s string) []byte {
    97  	return []byte(s)
    98  }
    99  
   100  func makeIkey(s string) base.InternalKey {
   101  	return base.InternalKey{UserKey: []byte(s)}
   102  }
   103  
   104  func makeValue(i int) []byte {
   105  	return []byte(fmt.Sprintf("v%05d", i))
   106  }
   107  
   108  func makeInserterAdd(s *Skiplist) func(key base.InternalKey, value []byte) error {
   109  	ins := &Inserter{}
   110  	return func(key base.InternalKey, value []byte) error {
   111  		return ins.Add(s, key, value)
   112  	}
   113  }
   114  
   115  // length iterates over skiplist to give exact size.
   116  func length(s *Skiplist) int {
   117  	count := 0
   118  
   119  	it := iterAdapter{s.NewIter(nil, nil)}
   120  	for valid := it.First(); valid; valid = it.Next() {
   121  		count++
   122  	}
   123  
   124  	return count
   125  }
   126  
   127  // length iterates over skiplist in reverse order to give exact size.
   128  func lengthRev(s *Skiplist) int {
   129  	count := 0
   130  
   131  	it := iterAdapter{s.NewIter(nil, nil)}
   132  	for valid := it.Last(); valid; valid = it.Prev() {
   133  		count++
   134  	}
   135  
   136  	return count
   137  }
   138  
   139  func TestEmpty(t *testing.T) {
   140  	key := makeKey("aaa")
   141  	l := NewSkiplist(NewArena(arenaSize, 0), bytes.Compare)
   142  	it := iterAdapter{l.NewIter(nil, nil)}
   143  
   144  	require.False(t, it.Valid())
   145  
   146  	it.First()
   147  	require.False(t, it.Valid())
   148  
   149  	it.Last()
   150  	require.False(t, it.Valid())
   151  
   152  	require.False(t, it.SeekGE(key))
   153  	require.False(t, it.Valid())
   154  }
   155  
   156  func TestFull(t *testing.T) {
   157  	l := NewSkiplist(NewArena(1000, 0), bytes.Compare)
   158  
   159  	foundArenaFull := false
   160  	for i := 0; i < 100; i++ {
   161  		err := l.Add(makeIntKey(i), makeValue(i))
   162  		if err == ErrArenaFull {
   163  			foundArenaFull = true
   164  			break
   165  		}
   166  	}
   167  
   168  	require.True(t, foundArenaFull)
   169  
   170  	err := l.Add(makeIkey("someval"), nil)
   171  	require.Equal(t, ErrArenaFull, err)
   172  }
   173  
   174  // TestBasic tests single-threaded seeks and adds.
   175  func TestBasic(t *testing.T) {
   176  	for _, inserter := range []bool{false, true} {
   177  		t.Run(fmt.Sprintf("inserter=%t", inserter), func(t *testing.T) {
   178  			l := NewSkiplist(NewArena(arenaSize, 0), bytes.Compare)
   179  			it := iterAdapter{l.NewIter(nil, nil)}
   180  
   181  			add := l.Add
   182  			if inserter {
   183  				add = makeInserterAdd(l)
   184  			}
   185  
   186  			// Try adding values.
   187  			add(makeIkey("key1"), makeValue(1))
   188  			add(makeIkey("key3"), makeValue(3))
   189  			add(makeIkey("key2"), makeValue(2))
   190  
   191  			require.True(t, it.SeekGE(makeKey("key")))
   192  			require.True(t, it.Valid())
   193  			require.NotEqual(t, "key", it.Key().UserKey)
   194  
   195  			require.True(t, it.SeekGE(makeKey("key1")))
   196  			require.EqualValues(t, "key1", it.Key().UserKey)
   197  			require.EqualValues(t, makeValue(1), it.Value())
   198  
   199  			require.True(t, it.SeekGE(makeKey("key2")))
   200  			require.EqualValues(t, "key2", it.Key().UserKey)
   201  			require.EqualValues(t, makeValue(2), it.Value())
   202  
   203  			require.True(t, it.SeekGE(makeKey("key3")))
   204  			require.EqualValues(t, "key3", it.Key().UserKey)
   205  			require.EqualValues(t, makeValue(3), it.Value())
   206  
   207  			key := makeIkey("a")
   208  			key.SetSeqNum(1)
   209  			add(key, nil)
   210  			key.SetSeqNum(2)
   211  			add(key, nil)
   212  
   213  			require.True(t, it.SeekGE(makeKey("a")))
   214  			require.True(t, it.Valid())
   215  			require.EqualValues(t, "a", it.Key().UserKey)
   216  			require.EqualValues(t, 2, it.Key().SeqNum())
   217  
   218  			require.True(t, it.Next())
   219  			require.True(t, it.Valid())
   220  			require.EqualValues(t, "a", it.Key().UserKey)
   221  			require.EqualValues(t, 1, it.Key().SeqNum())
   222  
   223  			key = makeIkey("b")
   224  			key.SetSeqNum(2)
   225  			add(key, nil)
   226  			key.SetSeqNum(1)
   227  			add(key, nil)
   228  
   229  			require.True(t, it.SeekGE(makeKey("b")))
   230  			require.True(t, it.Valid())
   231  			require.EqualValues(t, "b", it.Key().UserKey)
   232  			require.EqualValues(t, 2, it.Key().SeqNum())
   233  
   234  			require.True(t, it.Next())
   235  			require.True(t, it.Valid())
   236  			require.EqualValues(t, "b", it.Key().UserKey)
   237  			require.EqualValues(t, 1, it.Key().SeqNum())
   238  		})
   239  	}
   240  }
   241  
   242  // TestConcurrentBasic tests concurrent writes followed by concurrent reads.
   243  func TestConcurrentBasic(t *testing.T) {
   244  	const n = 1000
   245  
   246  	for _, inserter := range []bool{false, true} {
   247  		t.Run(fmt.Sprintf("inserter=%t", inserter), func(t *testing.T) {
   248  			// Set testing flag to make it easier to trigger unusual race conditions.
   249  			l := NewSkiplist(NewArena(arenaSize, 0), bytes.Compare)
   250  			l.testing = true
   251  
   252  			var wg sync.WaitGroup
   253  			for i := 0; i < n; i++ {
   254  				wg.Add(1)
   255  				go func(i int) {
   256  					defer wg.Done()
   257  
   258  					if inserter {
   259  						var ins Inserter
   260  						ins.Add(l, makeIntKey(i), makeValue(i))
   261  					} else {
   262  						l.Add(makeIntKey(i), makeValue(i))
   263  					}
   264  				}(i)
   265  			}
   266  			wg.Wait()
   267  
   268  			// Check values. Concurrent reads.
   269  			for i := 0; i < n; i++ {
   270  				wg.Add(1)
   271  				go func(i int) {
   272  					defer wg.Done()
   273  
   274  					it := iterAdapter{l.NewIter(nil, nil)}
   275  					require.True(t, it.SeekGE(makeKey(fmt.Sprintf("%05d", i))))
   276  					require.EqualValues(t, fmt.Sprintf("%05d", i), it.Key().UserKey)
   277  				}(i)
   278  			}
   279  			wg.Wait()
   280  			require.Equal(t, n, length(l))
   281  			require.Equal(t, n, lengthRev(l))
   282  		})
   283  	}
   284  }
   285  
   286  // TestConcurrentOneKey will read while writing to one single key.
   287  func TestConcurrentOneKey(t *testing.T) {
   288  	const n = 100
   289  	key := makeKey("thekey")
   290  	ikey := makeIkey("thekey")
   291  
   292  	for _, inserter := range []bool{false, true} {
   293  		t.Run(fmt.Sprintf("inserter=%t", inserter), func(t *testing.T) {
   294  			// Set testing flag to make it easier to trigger unusual race conditions.
   295  			l := NewSkiplist(NewArena(arenaSize, 0), bytes.Compare)
   296  			l.testing = true
   297  
   298  			var wg sync.WaitGroup
   299  			writeDone := make(chan struct{}, 1)
   300  			for i := 0; i < n; i++ {
   301  				wg.Add(1)
   302  				go func(i int) {
   303  					defer func() {
   304  						wg.Done()
   305  						select {
   306  						case writeDone <- struct{}{}:
   307  						default:
   308  						}
   309  					}()
   310  
   311  					if inserter {
   312  						var ins Inserter
   313  						ins.Add(l, ikey, makeValue(i))
   314  					} else {
   315  						l.Add(ikey, makeValue(i))
   316  					}
   317  				}(i)
   318  			}
   319  			// Wait until at least some write made it such that reads return a value.
   320  			<-writeDone
   321  			var sawValue int32
   322  			for i := 0; i < n; i++ {
   323  				wg.Add(1)
   324  				go func() {
   325  					defer wg.Done()
   326  
   327  					it := iterAdapter{l.NewIter(nil, nil)}
   328  					it.SeekGE(key)
   329  					require.True(t, it.Valid())
   330  					require.True(t, bytes.Equal(key, it.Key().UserKey))
   331  
   332  					atomic.AddInt32(&sawValue, 1)
   333  					v, err := strconv.Atoi(string(it.Value()[1:]))
   334  					require.NoError(t, err)
   335  					require.True(t, 0 <= v && v < n)
   336  				}()
   337  			}
   338  			wg.Wait()
   339  			require.Equal(t, int32(n), sawValue)
   340  			require.Equal(t, 1, length(l))
   341  			require.Equal(t, 1, lengthRev(l))
   342  		})
   343  	}
   344  }
   345  
   346  func TestSkiplistAdd(t *testing.T) {
   347  	for _, inserter := range []bool{false, true} {
   348  		t.Run(fmt.Sprintf("inserter=%t", inserter), func(t *testing.T) {
   349  			l := NewSkiplist(NewArena(arenaSize, 0), bytes.Compare)
   350  			it := iterAdapter{l.NewIter(nil, nil)}
   351  
   352  			add := l.Add
   353  			if inserter {
   354  				add = makeInserterAdd(l)
   355  			}
   356  
   357  			// Add nil key and value (treated same as empty).
   358  			err := add(base.InternalKey{}, nil)
   359  			require.Nil(t, err)
   360  			require.True(t, it.SeekGE([]byte{}))
   361  			require.EqualValues(t, []byte{}, it.Key().UserKey)
   362  			require.EqualValues(t, []byte{}, it.Value())
   363  
   364  			l = NewSkiplist(NewArena(arenaSize, 0), bytes.Compare)
   365  			it = iterAdapter{l.NewIter(nil, nil)}
   366  
   367  			add = l.Add
   368  			if inserter {
   369  				add = makeInserterAdd(l)
   370  			}
   371  
   372  			// Add empty key and value (treated same as nil).
   373  			err = add(makeIkey(""), []byte{})
   374  			require.Nil(t, err)
   375  			require.True(t, it.SeekGE([]byte{}))
   376  			require.EqualValues(t, []byte{}, it.Key().UserKey)
   377  			require.EqualValues(t, []byte{}, it.Value())
   378  
   379  			// Add to empty list.
   380  			err = add(makeIntKey(2), makeValue(2))
   381  			require.Nil(t, err)
   382  			require.True(t, it.SeekGE(makeKey("00002")))
   383  			require.EqualValues(t, "00002", it.Key().UserKey)
   384  			require.EqualValues(t, makeValue(2), it.Value())
   385  
   386  			// Add first element in non-empty list.
   387  			err = add(makeIntKey(1), makeValue(1))
   388  			require.Nil(t, err)
   389  			require.True(t, it.SeekGE(makeKey("00001")))
   390  			require.EqualValues(t, "00001", it.Key().UserKey)
   391  			require.EqualValues(t, makeValue(1), it.Value())
   392  
   393  			// Add last element in non-empty list.
   394  			err = add(makeIntKey(4), makeValue(4))
   395  			require.Nil(t, err)
   396  			require.True(t, it.SeekGE(makeKey("00004")))
   397  			require.EqualValues(t, "00004", it.Key().UserKey)
   398  			require.EqualValues(t, makeValue(4), it.Value())
   399  
   400  			// Add element in middle of list.
   401  			err = add(makeIntKey(3), makeValue(3))
   402  			require.Nil(t, err)
   403  			require.True(t, it.SeekGE(makeKey("00003")))
   404  			require.EqualValues(t, "00003", it.Key().UserKey)
   405  			require.EqualValues(t, makeValue(3), it.Value())
   406  
   407  			// Try to add element that already exists.
   408  			err = add(makeIntKey(2), nil)
   409  			require.Equal(t, ErrRecordExists, err)
   410  			require.EqualValues(t, "00003", it.Key().UserKey)
   411  			require.EqualValues(t, makeValue(3), it.Value())
   412  
   413  			require.Equal(t, 5, length(l))
   414  			require.Equal(t, 5, lengthRev(l))
   415  		})
   416  	}
   417  }
   418  
   419  // TestConcurrentAdd races between adding same nodes.
   420  func TestConcurrentAdd(t *testing.T) {
   421  	for _, inserter := range []bool{false, true} {
   422  		t.Run(fmt.Sprintf("inserter=%t", inserter), func(t *testing.T) {
   423  			const n = 100
   424  
   425  			// Set testing flag to make it easier to trigger unusual race conditions.
   426  			l := NewSkiplist(NewArena(arenaSize, 0), bytes.Compare)
   427  			l.testing = true
   428  
   429  			start := make([]sync.WaitGroup, n)
   430  			end := make([]sync.WaitGroup, n)
   431  
   432  			for i := 0; i < n; i++ {
   433  				start[i].Add(1)
   434  				end[i].Add(2)
   435  			}
   436  
   437  			for f := 0; f < 2; f++ {
   438  				go func() {
   439  					it := iterAdapter{l.NewIter(nil, nil)}
   440  					add := l.Add
   441  					if inserter {
   442  						add = makeInserterAdd(l)
   443  					}
   444  
   445  					for i := 0; i < n; i++ {
   446  						start[i].Wait()
   447  
   448  						key := makeIntKey(i)
   449  						if add(key, nil) == nil {
   450  							require.True(t, it.SeekGE(key.UserKey))
   451  							require.EqualValues(t, key, it.Key())
   452  						}
   453  
   454  						end[i].Done()
   455  					}
   456  				}()
   457  			}
   458  
   459  			for i := 0; i < n; i++ {
   460  				start[i].Done()
   461  				end[i].Wait()
   462  			}
   463  
   464  			require.Equal(t, n, length(l))
   465  			require.Equal(t, n, lengthRev(l))
   466  		})
   467  	}
   468  }
   469  
   470  // TestIteratorNext tests a basic iteration over all nodes from the beginning.
   471  func TestIteratorNext(t *testing.T) {
   472  	const n = 100
   473  	l := NewSkiplist(NewArena(arenaSize, 0), bytes.Compare)
   474  	it := iterAdapter{l.NewIter(nil, nil)}
   475  
   476  	require.False(t, it.Valid())
   477  
   478  	it.First()
   479  	require.False(t, it.Valid())
   480  
   481  	for i := n - 1; i >= 0; i-- {
   482  		l.Add(makeIntKey(i), makeValue(i))
   483  	}
   484  
   485  	it.First()
   486  	for i := 0; i < n; i++ {
   487  		require.True(t, it.Valid())
   488  		require.EqualValues(t, makeIntKey(i), it.Key())
   489  		require.EqualValues(t, makeValue(i), it.Value())
   490  		it.Next()
   491  	}
   492  	require.False(t, it.Valid())
   493  }
   494  
   495  // TestIteratorPrev tests a basic iteration over all nodes from the end.
   496  func TestIteratorPrev(t *testing.T) {
   497  	const n = 100
   498  	l := NewSkiplist(NewArena(arenaSize, 0), bytes.Compare)
   499  	it := iterAdapter{l.NewIter(nil, nil)}
   500  
   501  	require.False(t, it.Valid())
   502  
   503  	it.Last()
   504  	require.False(t, it.Valid())
   505  
   506  	var ins Inserter
   507  	for i := 0; i < n; i++ {
   508  		ins.Add(l, makeIntKey(i), makeValue(i))
   509  	}
   510  
   511  	it.Last()
   512  	for i := n - 1; i >= 0; i-- {
   513  		require.True(t, it.Valid())
   514  		require.EqualValues(t, makeIntKey(i), it.Key())
   515  		require.EqualValues(t, makeValue(i), it.Value())
   516  		it.Prev()
   517  	}
   518  	require.False(t, it.Valid())
   519  }
   520  
   521  func TestIteratorSeekGE(t *testing.T) {
   522  	const n = 100
   523  	l := NewSkiplist(NewArena(arenaSize, 0), bytes.Compare)
   524  	it := iterAdapter{l.NewIter(nil, nil)}
   525  
   526  	require.False(t, it.Valid())
   527  	it.First()
   528  	require.False(t, it.Valid())
   529  	// 1000, 1010, 1020, ..., 1990.
   530  
   531  	var ins Inserter
   532  	for i := n - 1; i >= 0; i-- {
   533  		v := i*10 + 1000
   534  		ins.Add(l, makeIntKey(v), makeValue(v))
   535  	}
   536  
   537  	require.True(t, it.SeekGE(makeKey("")))
   538  	require.True(t, it.Valid())
   539  	require.EqualValues(t, "01000", it.Key().UserKey)
   540  	require.EqualValues(t, "v01000", it.Value())
   541  
   542  	require.True(t, it.SeekGE(makeKey("01000")))
   543  	require.True(t, it.Valid())
   544  	require.EqualValues(t, "01000", it.Key().UserKey)
   545  	require.EqualValues(t, "v01000", it.Value())
   546  
   547  	require.True(t, it.SeekGE(makeKey("01005")))
   548  	require.True(t, it.Valid())
   549  	require.EqualValues(t, "01010", it.Key().UserKey)
   550  	require.EqualValues(t, "v01010", it.Value())
   551  
   552  	require.True(t, it.SeekGE(makeKey("01010")))
   553  	require.True(t, it.Valid())
   554  	require.EqualValues(t, "01010", it.Key().UserKey)
   555  	require.EqualValues(t, "v01010", it.Value())
   556  
   557  	require.False(t, it.SeekGE(makeKey("99999")))
   558  	require.False(t, it.Valid())
   559  
   560  	// Test seek for empty key.
   561  	ins.Add(l, base.InternalKey{}, nil)
   562  	require.True(t, it.SeekGE([]byte{}))
   563  	require.True(t, it.Valid())
   564  	require.EqualValues(t, "", it.Key().UserKey)
   565  
   566  	require.True(t, it.SeekGE(makeKey("")))
   567  	require.True(t, it.Valid())
   568  	require.EqualValues(t, "", it.Key().UserKey)
   569  }
   570  
   571  func TestIteratorSeekLT(t *testing.T) {
   572  	const n = 100
   573  	l := NewSkiplist(NewArena(arenaSize, 0), bytes.Compare)
   574  	it := iterAdapter{l.NewIter(nil, nil)}
   575  
   576  	require.False(t, it.Valid())
   577  	it.First()
   578  	require.False(t, it.Valid())
   579  	// 1000, 1010, 1020, ..., 1990.
   580  	var ins Inserter
   581  	for i := n - 1; i >= 0; i-- {
   582  		v := i*10 + 1000
   583  		ins.Add(l, makeIntKey(v), makeValue(v))
   584  	}
   585  
   586  	require.False(t, it.SeekLT(makeKey("")))
   587  	require.False(t, it.Valid())
   588  
   589  	require.False(t, it.SeekLT(makeKey("01000")))
   590  	require.False(t, it.Valid())
   591  
   592  	require.True(t, it.SeekLT(makeKey("01001")))
   593  	require.True(t, it.Valid())
   594  	require.EqualValues(t, "01000", it.Key().UserKey)
   595  	require.EqualValues(t, "v01000", it.Value())
   596  
   597  	require.True(t, it.SeekLT(makeKey("01005")))
   598  	require.True(t, it.Valid())
   599  	require.EqualValues(t, "01000", it.Key().UserKey)
   600  	require.EqualValues(t, "v01000", it.Value())
   601  
   602  	require.True(t, it.SeekLT(makeKey("01991")))
   603  	require.True(t, it.Valid())
   604  	require.EqualValues(t, "01990", it.Key().UserKey)
   605  	require.EqualValues(t, "v01990", it.Value())
   606  
   607  	require.True(t, it.SeekLT(makeKey("99999")))
   608  	require.True(t, it.Valid())
   609  	require.EqualValues(t, "01990", it.Key().UserKey)
   610  	require.EqualValues(t, "v01990", it.Value())
   611  
   612  	// Test seek for empty key.
   613  	ins.Add(l, base.InternalKey{}, nil)
   614  	require.False(t, it.SeekLT([]byte{}))
   615  	require.False(t, it.Valid())
   616  
   617  	require.True(t, it.SeekLT(makeKey("\x01")))
   618  	require.True(t, it.Valid())
   619  	require.EqualValues(t, "", it.Key().UserKey)
   620  }
   621  
   622  // TODO(peter): test First and Last.
   623  func TestIteratorBounds(t *testing.T) {
   624  	l := NewSkiplist(NewArena(arenaSize, 0), bytes.Compare)
   625  	for i := 1; i < 10; i++ {
   626  		err := l.Add(makeIntKey(i), makeValue(i))
   627  		if err != nil {
   628  			t.Fatal(err)
   629  		}
   630  	}
   631  
   632  	key := func(i int) []byte {
   633  		return makeIntKey(i).UserKey
   634  	}
   635  
   636  	it := iterAdapter{l.NewIter(key(3), key(7))}
   637  
   638  	// SeekGE within the lower and upper bound succeeds.
   639  	for i := 3; i <= 6; i++ {
   640  		k := key(i)
   641  		require.True(t, it.SeekGE(k))
   642  		require.EqualValues(t, string(k), string(it.Key().UserKey))
   643  	}
   644  
   645  	// SeekGE before the lower bound still succeeds (only the upper bound is
   646  	// checked).
   647  	for i := 1; i < 3; i++ {
   648  		k := key(i)
   649  		require.True(t, it.SeekGE(k))
   650  		require.EqualValues(t, string(k), string(it.Key().UserKey))
   651  	}
   652  
   653  	// SeekGE beyond the upper bound fails.
   654  	for i := 7; i < 10; i++ {
   655  		require.False(t, it.SeekGE(key(i)))
   656  	}
   657  
   658  	require.True(t, it.SeekGE(key(6)))
   659  	require.EqualValues(t, "00006", it.Key().UserKey)
   660  	require.EqualValues(t, "v00006", it.Value())
   661  
   662  	// Next into the upper bound fails.
   663  	require.False(t, it.Next())
   664  
   665  	// SeekLT within the lower and upper bound succeeds.
   666  	for i := 4; i <= 7; i++ {
   667  		require.True(t, it.SeekLT(key(i)))
   668  		require.EqualValues(t, string(key(i-1)), string(it.Key().UserKey))
   669  	}
   670  
   671  	// SeekLT beyond the upper bound still succeeds (only the lower bound is
   672  	// checked).
   673  	for i := 8; i < 9; i++ {
   674  		require.True(t, it.SeekLT(key(8)))
   675  		require.EqualValues(t, string(key(i-1)), string(it.Key().UserKey))
   676  	}
   677  
   678  	// SeekLT before the lower bound fails.
   679  	for i := 1; i < 4; i++ {
   680  		require.False(t, it.SeekLT(key(i)))
   681  	}
   682  
   683  	require.True(t, it.SeekLT(key(4)))
   684  	require.EqualValues(t, "00003", it.Key().UserKey)
   685  	require.EqualValues(t, "v00003", it.Value())
   686  
   687  	// Prev into the lower bound fails.
   688  	require.False(t, it.Prev())
   689  }
   690  
   691  func TestBytesIterated(t *testing.T) {
   692  	l := NewSkiplist(NewArena(arenaSize, 0), bytes.Compare)
   693  	emptySize := l.arena.Size()
   694  	for i := 0; i < 200; i++ {
   695  		bytesIterated := l.bytesIterated(t)
   696  		expected := uint64(l.arena.Size() - emptySize)
   697  		if bytesIterated != expected {
   698  			t.Fatalf("bytesIterated: got %d, want %d", bytesIterated, expected)
   699  		}
   700  		l.Add(base.InternalKey{UserKey: []byte{byte(i)}}, nil)
   701  	}
   702  }
   703  
   704  // bytesIterated returns the number of bytes iterated in the skiplist.
   705  func (s *Skiplist) bytesIterated(t *testing.T) (bytesIterated uint64) {
   706  	x := s.NewFlushIter(&bytesIterated)
   707  	var prevIterated uint64
   708  	for x.First(); x.Valid(); x.Next() {
   709  		if bytesIterated < prevIterated {
   710  			t.Fatalf("bytesIterated moved backward: %d < %d", bytesIterated, prevIterated)
   711  		}
   712  		prevIterated = bytesIterated
   713  	}
   714  	if x.Close() != nil {
   715  		return 0
   716  	}
   717  	return bytesIterated
   718  }
   719  
   720  func randomKey(rng *rand.Rand, b []byte) base.InternalKey {
   721  	key := rng.Uint32()
   722  	key2 := rng.Uint32()
   723  	binary.LittleEndian.PutUint32(b, key)
   724  	binary.LittleEndian.PutUint32(b[4:], key2)
   725  	return base.InternalKey{UserKey: b}
   726  }
   727  
   728  // Standard test. Some fraction is read. Some fraction is write. Writes have
   729  // to go through mutex lock.
   730  func BenchmarkReadWrite(b *testing.B) {
   731  	for i := 0; i <= 10; i++ {
   732  		readFrac := float32(i) / 10.0
   733  		b.Run(fmt.Sprintf("frac_%d", i*10), func(b *testing.B) {
   734  			l := NewSkiplist(NewArena(uint32((b.N+2)*maxNodeSize), 0), bytes.Compare)
   735  			b.ResetTimer()
   736  			var count int
   737  			b.RunParallel(func(pb *testing.PB) {
   738  				it := l.NewIter(nil, nil)
   739  				rng := rand.New(rand.NewSource(uint64(time.Now().UnixNano())))
   740  				buf := make([]byte, 8)
   741  
   742  				for pb.Next() {
   743  					if rng.Float32() < readFrac {
   744  						key, _ := it.SeekGE(randomKey(rng, buf).UserKey)
   745  						if key != nil {
   746  							_ = key
   747  							count++
   748  						}
   749  					} else {
   750  						_ = l.Add(randomKey(rng, buf), nil)
   751  					}
   752  				}
   753  			})
   754  		})
   755  	}
   756  }
   757  
   758  func BenchmarkOrderedWrite(b *testing.B) {
   759  	l := NewSkiplist(NewArena(8<<20, 0), bytes.Compare)
   760  	var ins Inserter
   761  	buf := make([]byte, 8)
   762  
   763  	b.ResetTimer()
   764  	for i := 0; i < b.N; i++ {
   765  		binary.BigEndian.PutUint64(buf, uint64(i))
   766  		if err := ins.Add(l, base.InternalKey{UserKey: buf}, nil); err == ErrArenaFull {
   767  			b.StopTimer()
   768  			l = NewSkiplist(NewArena(uint32((b.N+2)*maxNodeSize), 0), bytes.Compare)
   769  			ins = Inserter{}
   770  			b.StartTimer()
   771  		}
   772  	}
   773  }
   774  
   775  func BenchmarkIterNext(b *testing.B) {
   776  	l := NewSkiplist(NewArena(64<<10, 0), bytes.Compare)
   777  	rng := rand.New(rand.NewSource(uint64(time.Now().UnixNano())))
   778  	buf := make([]byte, 8)
   779  	for {
   780  		if err := l.Add(randomKey(rng, buf), nil); err == ErrArenaFull {
   781  			break
   782  		}
   783  	}
   784  
   785  	it := l.NewIter(nil, nil)
   786  	b.ResetTimer()
   787  	for i := 0; i < b.N; i++ {
   788  		if !it.Valid() {
   789  			it.First()
   790  		}
   791  		it.Next()
   792  	}
   793  }
   794  
   795  func BenchmarkIterPrev(b *testing.B) {
   796  	l := NewSkiplist(NewArena(64<<10, 0), bytes.Compare)
   797  	rng := rand.New(rand.NewSource(uint64(time.Now().UnixNano())))
   798  	buf := make([]byte, 8)
   799  	for {
   800  		if err := l.Add(randomKey(rng, buf), nil); err == ErrArenaFull {
   801  			break
   802  		}
   803  	}
   804  
   805  	it := l.NewIter(nil, nil)
   806  	b.ResetTimer()
   807  	for i := 0; i < b.N; i++ {
   808  		if !it.Valid() {
   809  			it.Last()
   810  		}
   811  		it.Prev()
   812  	}
   813  }
   814  
   815  // Standard test. Some fraction is read. Some fraction is write. Writes have
   816  // to go through mutex lock.
   817  // func BenchmarkReadWriteMap(b *testing.B) {
   818  // 	for i := 0; i <= 10; i++ {
   819  // 		readFrac := float32(i) / 10.0
   820  // 		b.Run(fmt.Sprintf("frac_%d", i*10), func(b *testing.B) {
   821  // 			m := make(map[string]struct{})
   822  // 			var mutex sync.RWMutex
   823  // 			b.ResetTimer()
   824  // 			var count int
   825  // 			b.RunParallel(func(pb *testing.PB) {
   826  // 				rng := rand.New(rand.NewSource(time.Now().UnixNano()))
   827  // 				for pb.Next() {
   828  // 					if rng.Float32() < readFrac {
   829  // 						mutex.RLock()
   830  // 						_, ok := m[string(randomKey(rng))]
   831  // 						mutex.RUnlock()
   832  // 						if ok {
   833  // 							count++
   834  // 						}
   835  // 					} else {
   836  // 						mutex.Lock()
   837  // 						m[string(randomKey(rng))] = struct{}{}
   838  // 						mutex.Unlock()
   839  // 					}
   840  // 				}
   841  // 			})
   842  // 		})
   843  // 	}
   844  // }