github.com/cockroachdb/pebble@v0.0.0-20231214172447-ab4952c5f87b/mem_table_test.go (about)

     1  // Copyright 2011 The LevelDB-Go and Pebble Authors. All rights reserved. Use
     2  // of this source code is governed by a BSD-style license that can be found in
     3  // the LICENSE file.
     4  
     5  package pebble
     6  
     7  import (
     8  	"bytes"
     9  	"context"
    10  	"fmt"
    11  	"strconv"
    12  	"strings"
    13  	"sync/atomic"
    14  	"testing"
    15  	"time"
    16  
    17  	"github.com/cockroachdb/datadriven"
    18  	"github.com/cockroachdb/errors"
    19  	"github.com/cockroachdb/pebble/internal/arenaskl"
    20  	"github.com/cockroachdb/pebble/internal/base"
    21  	"github.com/cockroachdb/pebble/internal/itertest"
    22  	"github.com/cockroachdb/pebble/internal/rangekey"
    23  	"github.com/stretchr/testify/require"
    24  	"golang.org/x/exp/rand"
    25  	"golang.org/x/sync/errgroup"
    26  )
    27  
    28  // get gets the value for the given key. It returns ErrNotFound if the DB does
    29  // not contain the key.
    30  func (m *memTable) get(key []byte) (value []byte, err error) {
    31  	it := m.skl.NewIter(nil, nil)
    32  	ikey, val := it.SeekGE(key, base.SeekGEFlagsNone)
    33  	if ikey == nil {
    34  		return nil, ErrNotFound
    35  	}
    36  	if !m.equal(key, ikey.UserKey) {
    37  		return nil, ErrNotFound
    38  	}
    39  	switch ikey.Kind() {
    40  	case InternalKeyKindDelete, InternalKeyKindSingleDelete, InternalKeyKindDeleteSized:
    41  		return nil, ErrNotFound
    42  	default:
    43  		return val.InPlaceValue(), nil
    44  	}
    45  }
    46  
    47  // Set sets the value for the given key. It overwrites any previous value for
    48  // that key; a DB is not a multi-map. NB: this might have unexpected
    49  // interaction with prepare/apply. Caveat emptor!
    50  func (m *memTable) set(key InternalKey, value []byte) error {
    51  	if key.Kind() == InternalKeyKindRangeDelete {
    52  		if err := m.rangeDelSkl.Add(key, value); err != nil {
    53  			return err
    54  		}
    55  		m.tombstones.invalidate(1)
    56  		return nil
    57  	}
    58  	if rangekey.IsRangeKey(key.Kind()) {
    59  		if err := m.rangeKeySkl.Add(key, value); err != nil {
    60  			return err
    61  		}
    62  		m.rangeKeys.invalidate(1)
    63  		return nil
    64  	}
    65  	return m.skl.Add(key, value)
    66  }
    67  
    68  // count returns the number of entries in a DB.
    69  func (m *memTable) count() (n int) {
    70  	x := newInternalIterAdapter(m.newIter(nil))
    71  	for valid := x.First(); valid; valid = x.Next() {
    72  		n++
    73  	}
    74  	if x.Close() != nil {
    75  		return -1
    76  	}
    77  	return n
    78  }
    79  
    80  // bytesIterated returns the number of bytes iterated in a DB.
    81  func (m *memTable) bytesIterated(t *testing.T) (bytesIterated uint64) {
    82  	x := newInternalIterAdapter(m.newFlushIter(nil, &bytesIterated))
    83  	var prevIterated uint64
    84  	for valid := x.First(); valid; valid = x.Next() {
    85  		if bytesIterated < prevIterated {
    86  			t.Fatalf("bytesIterated moved backward: %d < %d", bytesIterated, prevIterated)
    87  		}
    88  		prevIterated = bytesIterated
    89  	}
    90  	if x.Close() != nil {
    91  		return 0
    92  	}
    93  	return bytesIterated
    94  }
    95  
    96  func ikey(s string) InternalKey {
    97  	return base.MakeInternalKey([]byte(s), 0, InternalKeyKindSet)
    98  }
    99  
   100  func TestMemTableBasic(t *testing.T) {
   101  	// Check the empty DB.
   102  	m := newMemTable(memTableOptions{})
   103  	if got, want := m.count(), 0; got != want {
   104  		t.Fatalf("0.count: got %v, want %v", got, want)
   105  	}
   106  	v, err := m.get([]byte("cherry"))
   107  	if string(v) != "" || err != ErrNotFound {
   108  		t.Fatalf("1.get: got (%q, %v), want (%q, %v)", v, err, "", ErrNotFound)
   109  	}
   110  	// Add some key/value pairs.
   111  	m.set(ikey("cherry"), []byte("red"))
   112  	m.set(ikey("peach"), []byte("yellow"))
   113  	m.set(ikey("grape"), []byte("red"))
   114  	m.set(ikey("grape"), []byte("green"))
   115  	m.set(ikey("plum"), []byte("purple"))
   116  	if got, want := m.count(), 4; got != want {
   117  		t.Fatalf("2.count: got %v, want %v", got, want)
   118  	}
   119  	// Get keys that are and aren't in the DB.
   120  	v, err = m.get([]byte("plum"))
   121  	if string(v) != "purple" || err != nil {
   122  		t.Fatalf("6.get: got (%q, %v), want (%q, %v)", v, err, "purple", error(nil))
   123  	}
   124  	v, err = m.get([]byte("lychee"))
   125  	if string(v) != "" || err != ErrNotFound {
   126  		t.Fatalf("7.get: got (%q, %v), want (%q, %v)", v, err, "", ErrNotFound)
   127  	}
   128  	// Check an iterator.
   129  	s, x := "", newInternalIterAdapter(m.newIter(nil))
   130  	for valid := x.SeekGE([]byte("mango"), base.SeekGEFlagsNone); valid; valid = x.Next() {
   131  		s += fmt.Sprintf("%s/%s.", x.Key().UserKey, x.Value())
   132  	}
   133  	if want := "peach/yellow.plum/purple."; s != want {
   134  		t.Fatalf("8.iter: got %q, want %q", s, want)
   135  	}
   136  	if err = x.Close(); err != nil {
   137  		t.Fatalf("9.close: %v", err)
   138  	}
   139  	// Check some more sets and deletes.
   140  	if err := m.set(ikey("apricot"), []byte("orange")); err != nil {
   141  		t.Fatalf("12.set: %v", err)
   142  	}
   143  	if got, want := m.count(), 5; got != want {
   144  		t.Fatalf("13.count: got %v, want %v", got, want)
   145  	}
   146  }
   147  
   148  func TestMemTableCount(t *testing.T) {
   149  	m := newMemTable(memTableOptions{})
   150  	for i := 0; i < 200; i++ {
   151  		if j := m.count(); j != i {
   152  			t.Fatalf("count: got %d, want %d", j, i)
   153  		}
   154  		m.set(InternalKey{UserKey: []byte{byte(i)}}, nil)
   155  	}
   156  }
   157  
   158  func TestMemTableBytesIterated(t *testing.T) {
   159  	m := newMemTable(memTableOptions{})
   160  	for i := 0; i < 200; i++ {
   161  		bytesIterated := m.bytesIterated(t)
   162  		expected := m.inuseBytes()
   163  		if bytesIterated != expected {
   164  			t.Fatalf("bytesIterated: got %d, want %d", bytesIterated, expected)
   165  		}
   166  		m.set(InternalKey{UserKey: []byte{byte(i)}}, nil)
   167  	}
   168  }
   169  
   170  func TestMemTableEmpty(t *testing.T) {
   171  	m := newMemTable(memTableOptions{})
   172  	if !m.empty() {
   173  		t.Errorf("got !empty, want empty")
   174  	}
   175  	// Add one key/value pair with an empty key and empty value.
   176  	m.set(InternalKey{}, nil)
   177  	if m.empty() {
   178  		t.Errorf("got empty, want !empty")
   179  	}
   180  }
   181  
   182  func TestMemTable1000Entries(t *testing.T) {
   183  	// Initialize the DB.
   184  	const N = 1000
   185  	m0 := newMemTable(memTableOptions{})
   186  	for i := 0; i < N; i++ {
   187  		k := ikey(strconv.Itoa(i))
   188  		v := []byte(strings.Repeat("x", i))
   189  		m0.set(k, v)
   190  	}
   191  	// Check the DB count.
   192  	if got, want := m0.count(), 1000; got != want {
   193  		t.Fatalf("count: got %v, want %v", got, want)
   194  	}
   195  	// Check random-access lookup.
   196  	r := rand.New(rand.NewSource(0))
   197  	for i := 0; i < 3*N; i++ {
   198  		j := r.Intn(N)
   199  		k := []byte(strconv.Itoa(j))
   200  		v, err := m0.get(k)
   201  		require.NoError(t, err)
   202  		if len(v) != cap(v) {
   203  			t.Fatalf("get: j=%d, got len(v)=%d, cap(v)=%d", j, len(v), cap(v))
   204  		}
   205  		var c uint8
   206  		if len(v) != 0 {
   207  			c = v[0]
   208  		} else {
   209  			c = 'x'
   210  		}
   211  		if len(v) != j || c != 'x' {
   212  			t.Fatalf("get: j=%d, got len(v)=%d,c=%c, want %d,%c", j, len(v), c, j, 'x')
   213  		}
   214  	}
   215  	// Check that iterating through the middle of the DB looks OK.
   216  	// Keys are in lexicographic order, not numerical order.
   217  	// Multiples of 3 are not present.
   218  	wants := []string{
   219  		"499",
   220  		"5",
   221  		"50",
   222  		"500",
   223  		"501",
   224  		"502",
   225  		"503",
   226  		"504",
   227  		"505",
   228  		"506",
   229  		"507",
   230  	}
   231  	x := newInternalIterAdapter(m0.newIter(nil))
   232  	x.SeekGE([]byte(wants[0]), base.SeekGEFlagsNone)
   233  	for _, want := range wants {
   234  		if !x.Valid() {
   235  			t.Fatalf("iter: next failed, want=%q", want)
   236  		}
   237  		if got := string(x.Key().UserKey); got != want {
   238  			t.Fatalf("iter: got %q, want %q", got, want)
   239  		}
   240  		if k := x.Key().UserKey; len(k) != cap(k) {
   241  			t.Fatalf("iter: len(k)=%d, cap(k)=%d", len(k), cap(k))
   242  		}
   243  		if v := x.Value(); len(v) != cap(v) {
   244  			t.Fatalf("iter: len(v)=%d, cap(v)=%d", len(v), cap(v))
   245  		}
   246  		x.Next()
   247  	}
   248  	if err := x.Close(); err != nil {
   249  		t.Fatalf("close: %v", err)
   250  	}
   251  }
   252  
   253  func TestMemTableIter(t *testing.T) {
   254  	var mem *memTable
   255  	for _, testdata := range []string{
   256  		"testdata/internal_iter_next", "testdata/internal_iter_bounds"} {
   257  		datadriven.RunTest(t, testdata, func(t *testing.T, d *datadriven.TestData) string {
   258  			switch d.Cmd {
   259  			case "define":
   260  				mem = newMemTable(memTableOptions{})
   261  				for _, key := range strings.Split(d.Input, "\n") {
   262  					j := strings.Index(key, ":")
   263  					if err := mem.set(base.ParseInternalKey(key[:j]), []byte(key[j+1:])); err != nil {
   264  						return err.Error()
   265  					}
   266  				}
   267  				return ""
   268  
   269  			case "iter":
   270  				var options IterOptions
   271  				for _, arg := range d.CmdArgs {
   272  					switch arg.Key {
   273  					case "lower":
   274  						if len(arg.Vals) != 1 {
   275  							return fmt.Sprintf(
   276  								"%s expects at most 1 value for lower", d.Cmd)
   277  						}
   278  						options.LowerBound = []byte(arg.Vals[0])
   279  					case "upper":
   280  						if len(arg.Vals) != 1 {
   281  							return fmt.Sprintf(
   282  								"%s expects at most 1 value for upper", d.Cmd)
   283  						}
   284  						options.UpperBound = []byte(arg.Vals[0])
   285  					default:
   286  						return fmt.Sprintf("unknown arg: %s", arg.Key)
   287  					}
   288  				}
   289  				iter := mem.newIter(&options)
   290  				defer iter.Close()
   291  				return itertest.RunInternalIterCmd(t, d, iter)
   292  
   293  			default:
   294  				return fmt.Sprintf("unknown command: %s", d.Cmd)
   295  			}
   296  		})
   297  	}
   298  }
   299  
   300  func TestMemTableDeleteRange(t *testing.T) {
   301  	var mem *memTable
   302  	var seqNum uint64
   303  
   304  	datadriven.RunTest(t, "testdata/delete_range", func(t *testing.T, td *datadriven.TestData) string {
   305  		switch td.Cmd {
   306  		case "clear":
   307  			mem = nil
   308  			seqNum = 0
   309  			return ""
   310  
   311  		case "define":
   312  			b := newBatch(nil)
   313  			if err := runBatchDefineCmd(td, b); err != nil {
   314  				return err.Error()
   315  			}
   316  			if mem == nil {
   317  				mem = newMemTable(memTableOptions{})
   318  			}
   319  			if err := mem.apply(b, seqNum); err != nil {
   320  				return err.Error()
   321  			}
   322  			seqNum += uint64(b.Count())
   323  			return ""
   324  
   325  		case "scan":
   326  			var buf bytes.Buffer
   327  			if td.HasArg("range-del") {
   328  				iter := mem.newRangeDelIter(nil)
   329  				defer iter.Close()
   330  				scanKeyspanIterator(&buf, iter)
   331  			} else {
   332  				iter := mem.newIter(nil)
   333  				defer iter.Close()
   334  				scanInternalIter(&buf, iter)
   335  			}
   336  			return buf.String()
   337  
   338  		default:
   339  			return fmt.Sprintf("unknown command: %s", td.Cmd)
   340  		}
   341  	})
   342  }
   343  
   344  func TestMemTableConcurrentDeleteRange(t *testing.T) {
   345  	// Concurrently write and read range tombstones. Workers add range
   346  	// tombstones, and then immediately retrieve them verifying that the
   347  	// tombstones they've added are all present.
   348  
   349  	m := newMemTable(memTableOptions{Options: &Options{MemTableSize: 64 << 20}})
   350  
   351  	const workers = 10
   352  	eg, _ := errgroup.WithContext(context.Background())
   353  	var seqNum atomic.Uint64
   354  	seqNum.Store(1)
   355  	for i := 0; i < workers; i++ {
   356  		i := i
   357  		eg.Go(func() error {
   358  			start := ([]byte)(fmt.Sprintf("%03d", i))
   359  			end := ([]byte)(fmt.Sprintf("%03d", i+1))
   360  			for j := 0; j < 100; j++ {
   361  				b := newBatch(nil)
   362  				b.DeleteRange(start, end, nil)
   363  				n := seqNum.Add(1) - 1
   364  				require.NoError(t, m.apply(b, n))
   365  				b.release()
   366  
   367  				var count int
   368  				it := m.newRangeDelIter(nil)
   369  				for s := it.SeekGE(start); s != nil; s = it.Next() {
   370  					if m.cmp(s.Start, end) >= 0 {
   371  						break
   372  					}
   373  					count += len(s.Keys)
   374  				}
   375  				if j+1 != count {
   376  					return errors.Errorf("%d: expected %d tombstones, but found %d", i, j+1, count)
   377  				}
   378  			}
   379  			return nil
   380  		})
   381  	}
   382  	err := eg.Wait()
   383  	if err != nil {
   384  		t.Error(err)
   385  	}
   386  }
   387  
   388  func TestMemTableReserved(t *testing.T) {
   389  	m := newMemTable(memTableOptions{size: 5000})
   390  	// Increase to 2 references.
   391  	m.writerRef()
   392  	// The initial reservation accounts for the already allocated bytes from the
   393  	// arena.
   394  	require.Equal(t, m.reserved, m.skl.Arena().Size())
   395  	b := newBatch(nil)
   396  	b.Set([]byte("blueberry"), []byte("pie"), nil)
   397  	require.NotEqual(t, 0, int(b.memTableSize))
   398  	prevReserved := m.reserved
   399  	m.prepare(b)
   400  	require.Equal(t, int(m.reserved), int(b.memTableSize)+int(prevReserved))
   401  }
   402  
   403  func buildMemTable(b *testing.B) (*memTable, [][]byte) {
   404  	m := newMemTable(memTableOptions{})
   405  	var keys [][]byte
   406  	var ikey InternalKey
   407  	for i := 0; ; i++ {
   408  		key := []byte(fmt.Sprintf("%08d", i))
   409  		keys = append(keys, key)
   410  		ikey = base.MakeInternalKey(key, 0, InternalKeyKindSet)
   411  		if m.set(ikey, nil) == arenaskl.ErrArenaFull {
   412  			break
   413  		}
   414  	}
   415  	return m, keys
   416  }
   417  
   418  func BenchmarkMemTableIterSeekGE(b *testing.B) {
   419  	m, keys := buildMemTable(b)
   420  	iter := m.newIter(nil)
   421  	rng := rand.New(rand.NewSource(uint64(time.Now().UnixNano())))
   422  
   423  	b.ResetTimer()
   424  	for i := 0; i < b.N; i++ {
   425  		iter.SeekGE(keys[rng.Intn(len(keys))], base.SeekGEFlagsNone)
   426  	}
   427  }
   428  
   429  func BenchmarkMemTableIterNext(b *testing.B) {
   430  	m, _ := buildMemTable(b)
   431  	iter := m.newIter(nil)
   432  	_, _ = iter.First()
   433  	b.ResetTimer()
   434  	for i := 0; i < b.N; i++ {
   435  		key, _ := iter.Next()
   436  		if key == nil {
   437  			key, _ = iter.First()
   438  		}
   439  		_ = key
   440  	}
   441  }
   442  
   443  func BenchmarkMemTableIterPrev(b *testing.B) {
   444  	m, _ := buildMemTable(b)
   445  	iter := m.newIter(nil)
   446  	_, _ = iter.Last()
   447  	b.ResetTimer()
   448  	for i := 0; i < b.N; i++ {
   449  		key, _ := iter.Prev()
   450  		if key == nil {
   451  			key, _ = iter.Last()
   452  		}
   453  		_ = key
   454  	}
   455  }