github.com/pingcap/badger@v1.5.1-0.20230103063557-828f39b09b6d/table/sstable/table_test.go (about)

     1  /*
     2   * Copyright 2017 Dgraph Labs, Inc. and Contributors
     3   *
     4   * Licensed under the Apache License, Version 2.0 (the "License");
     5   * you may not use this file except in compliance with the License.
     6   * You may obtain a copy of the License at
     7   *
     8   *     http://www.apache.org/licenses/LICENSE-2.0
     9   *
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS,
    12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   * See the License for the specific language governing permissions and
    14   * limitations under the License.
    15   */
    16  
    17  package sstable
    18  
    19  import (
    20  	"bytes"
    21  	"encoding/binary"
    22  	"fmt"
    23  	"io"
    24  	"io/ioutil"
    25  	"math"
    26  	"math/rand"
    27  	"os"
    28  	"sort"
    29  	"testing"
    30  	"time"
    31  
    32  	"github.com/dgryski/go-farm"
    33  	"github.com/pingcap/badger/cache"
    34  	"github.com/pingcap/badger/cache/z"
    35  	"github.com/pingcap/badger/options"
    36  	"github.com/pingcap/badger/table"
    37  	"github.com/pingcap/badger/y"
    38  	"github.com/stretchr/testify/require"
    39  	"golang.org/x/time/rate"
    40  )
    41  
    42  func key(prefix string, i int) string {
    43  	return prefix + fmt.Sprintf("%04d", i)
    44  }
    45  
    46  var defaultBuilderOpt = options.TableBuilderOptions{
    47  	SuRFStartLevel: 0,
    48  	SuRFOptions: options.SuRFOptions{
    49  		BitsPerKeyHint: 40,
    50  		RealSuffixLen:  10,
    51  	},
    52  	CompressionPerLevel: []options.CompressionType{options.ZSTD},
    53  	BlockSize:           4 * 1024,
    54  	HashUtilRatio:       0.75,
    55  	WriteBufferSize:     1024 * 1024,
    56  	MaxLevels:           1,
    57  	LevelSizeMultiplier: 10,
    58  	LogicalBloomFPR:     0.01,
    59  	MaxTableSize:        32 * 1024,
    60  }
    61  
    62  func testCache() *cache.Cache {
    63  	c, err := cache.NewCache(&cache.Config{
    64  		NumCounters: 1000000 * 10,
    65  		MaxCost:     1000000,
    66  		BufferItems: 64,
    67  		Metrics:     true,
    68  	})
    69  	y.Check(err)
    70  	return c
    71  }
    72  
    73  func generateKeyValues(prefix string, n int) [][]string {
    74  	y.Assert(n <= 10000)
    75  	keyValues := make([][]string, n)
    76  	for i := 0; i < n; i++ {
    77  		k := key(prefix, i)
    78  		v := fmt.Sprintf("%d", i)
    79  		keyValues[i] = []string{k, v}
    80  	}
    81  	return keyValues
    82  }
    83  
    84  var compressionType = options.ZSTD
    85  
    86  func buildTestTable(t *testing.T, prefix string, n int) *os.File {
    87  	return buildTable(t, generateKeyValues(prefix, n))
    88  }
    89  
    90  // keyValues is n by 2 where n is number of pairs.
    91  func buildTable(t *testing.T, keyValues [][]string) *os.File {
    92  	// TODO: Add test for file garbage collection here. No files should be left after the tests here.
    93  	b, f := newTableBuilderForTest(false)
    94  	sort.Slice(keyValues, func(i, j int) bool {
    95  		return keyValues[i][0] < keyValues[j][0]
    96  	})
    97  	for _, kv := range keyValues {
    98  		y.Assert(len(kv) == 2)
    99  		err := b.Add(y.KeyWithTs([]byte(kv[0]), 0), y.ValueStruct{Value: []byte(kv[1]), Meta: 'A', UserMeta: []byte{0}})
   100  		if t != nil {
   101  			require.NoError(t, err)
   102  		} else {
   103  			y.Check(err)
   104  		}
   105  	}
   106  	_, err := b.Finish()
   107  	y.Check(err)
   108  	y.Check(f.Close())
   109  	f, _ = y.OpenSyncedFile(f.Name(), true)
   110  	return f
   111  }
   112  
   113  func newTableBuilderForTest(surf bool) (*Builder, *os.File) {
   114  	filename := fmt.Sprintf("%s%s%x.sst", os.TempDir(), string(os.PathSeparator), z.FastRand())
   115  	f, err := y.OpenSyncedFile(filename, true)
   116  	y.Check(err)
   117  	opt := defaultBuilderOpt
   118  	if !surf {
   119  		opt.SuRFStartLevel = 8
   120  	}
   121  	y.Assert(filename == f.Name())
   122  	return NewTableBuilder(f, rate.NewLimiter(rate.Inf, math.MaxInt32), 0, opt), f
   123  }
   124  
   125  func buildMultiVersionTable(keyValues [][]string) (*os.File, int) {
   126  	b, f := newTableBuilderForTest(false)
   127  	sort.Slice(keyValues, func(i, j int) bool {
   128  		return keyValues[i][0] < keyValues[j][0]
   129  	})
   130  	allCnt := len(keyValues)
   131  	for _, kv := range keyValues {
   132  		y.Assert(len(kv) == 2)
   133  		val := fmt.Sprintf("%s_%d", kv[1], 9)
   134  		err := b.Add(y.KeyWithTs([]byte(kv[0]), 9), y.ValueStruct{Value: []byte(val), Meta: 'A', UserMeta: []byte{0}})
   135  		y.Check(err)
   136  		for i := uint64(8); i > 0; i-- {
   137  			if z.FastRand()%4 == 0 {
   138  				val = fmt.Sprintf("%s_%d", kv[1], i)
   139  				err = b.Add(y.KeyWithTs([]byte(kv[0]), i), y.ValueStruct{Value: []byte(val), Meta: 'A', UserMeta: []byte{0}})
   140  				y.Check(err)
   141  				allCnt++
   142  			}
   143  		}
   144  	}
   145  	_, err := b.Finish()
   146  	y.Check(err)
   147  	y.Check(f.Close())
   148  	f, _ = y.OpenSyncedFile(f.Name(), true)
   149  	return f, allCnt
   150  }
   151  
   152  func TestTableIterator(t *testing.T) {
   153  	for _, n := range []int{99, 100, 101} {
   154  		t.Run(fmt.Sprintf("n=%d", n), func(t *testing.T) {
   155  			f := buildTestTable(t, "key", n)
   156  			table, err := OpenTable(f.Name(), testCache(), testCache())
   157  			require.NoError(t, err)
   158  			defer table.Delete()
   159  			it := table.newIterator(false)
   160  			defer it.Close()
   161  			count := 0
   162  			for it.Rewind(); it.Valid(); it.Next() {
   163  				v := it.Value()
   164  				k := y.KeyWithTs([]byte(key("key", count)), 0)
   165  				require.EqualValues(t, k, it.Key())
   166  				require.EqualValues(t, fmt.Sprintf("%d", count), string(v.Value))
   167  				count++
   168  			}
   169  			require.Equal(t, count, n)
   170  		})
   171  	}
   172  }
   173  
   174  func TestHashIndexTS(t *testing.T) {
   175  	filename := fmt.Sprintf("%s%s%x.sst", os.TempDir(), string(os.PathSeparator), rand.Uint32())
   176  	f, err := y.OpenSyncedFile(filename, true)
   177  	if t != nil {
   178  		require.NoError(t, err)
   179  	} else {
   180  		y.Check(err)
   181  	}
   182  	b := NewTableBuilder(f, nil, 0, defaultBuilderOpt)
   183  	keys := []y.Key{
   184  		y.KeyWithTs([]byte("key"), 9),
   185  		y.KeyWithTs([]byte("key"), 7),
   186  		y.KeyWithTs([]byte("key"), 5),
   187  		y.KeyWithTs([]byte("key"), 3),
   188  		y.KeyWithTs([]byte("key"), 1),
   189  	}
   190  	for _, k := range keys {
   191  		b.Add(k, y.ValueStruct{Value: k.UserKey, Meta: 'A', UserMeta: []byte{0}})
   192  	}
   193  	_, err = b.Finish()
   194  	y.Check(err)
   195  	f.Close()
   196  	table, err := OpenTable(filename, testCache(), testCache())
   197  	keyHash := farm.Fingerprint64([]byte("key"))
   198  
   199  	rk, _, ok, err := table.pointGet(y.KeyWithTs([]byte("key"), 10), keyHash)
   200  	require.NoError(t, err)
   201  	require.True(t, ok)
   202  	require.True(t, rk.Equal(keys[0]), "%s", string(rk.UserKey))
   203  
   204  	rk, _, ok, err = table.pointGet(y.KeyWithTs([]byte("key"), 6), keyHash)
   205  	require.NoError(t, err)
   206  	require.True(t, ok)
   207  	require.True(t, rk.Equal(keys[2]))
   208  
   209  	rk, _, ok, err = table.pointGet(y.KeyWithTs([]byte("key"), 2), keyHash)
   210  	require.NoError(t, err)
   211  	require.True(t, ok)
   212  	require.True(t, rk.Equal(keys[4]))
   213  }
   214  
   215  func TestPointGet(t *testing.T) {
   216  	f := buildTestTable(t, "key", 8000)
   217  	table, err := OpenTable(f.Name(), testCache(), testCache())
   218  	require.NoError(t, err)
   219  	defer table.Delete()
   220  
   221  	for i := 0; i < 8000; i++ {
   222  		k := y.KeyWithTs([]byte(key("key", i)), math.MaxUint64)
   223  		keyHash := farm.Fingerprint64(k.UserKey)
   224  		k1, _, ok, err := table.pointGet(k, keyHash)
   225  		require.NoError(t, err)
   226  		if !ok {
   227  			// will fallback to seek
   228  			continue
   229  		}
   230  		require.True(t, k1.SameUserKey(k), "point get not point to correct key")
   231  	}
   232  
   233  	for i := 8000; i < 10000; i++ {
   234  		k := y.KeyWithTs([]byte(key("key", i)), math.MaxUint64)
   235  		keyHash := farm.Fingerprint64(k.UserKey)
   236  		rk, _, ok, err := table.pointGet(k, keyHash)
   237  		require.NoError(t, err)
   238  		if !ok {
   239  			// will fallback to seek
   240  			continue
   241  		}
   242  		if rk.IsEmpty() {
   243  			// hash table says no entry, fast return
   244  			continue
   245  		}
   246  		require.False(t, k.SameUserKey(rk), "point get not point to correct key")
   247  	}
   248  }
   249  
   250  func TestExternalTable(t *testing.T) {
   251  	filename := fmt.Sprintf("%s%s%x.sst", os.TempDir(), string(os.PathSeparator), rand.Uint32())
   252  	f, err := y.OpenSyncedFile(filename, true)
   253  	if t != nil {
   254  		require.NoError(t, err)
   255  	} else {
   256  		y.Check(err)
   257  	}
   258  
   259  	n := 200
   260  	b := NewExternalTableBuilder(f, rate.NewLimiter(rate.Inf, math.MaxInt32), defaultBuilderOpt, compressionType)
   261  	kvs := generateKeyValues("key", n)
   262  	for _, kv := range kvs {
   263  		y.Assert(len(kv) == 2)
   264  		err := b.Add(y.KeyWithTs([]byte(kv[0]), 0), y.ValueStruct{Value: []byte(kv[1]), Meta: 'A', UserMeta: []byte{0}})
   265  		if t != nil {
   266  			require.NoError(t, err)
   267  		} else {
   268  			y.Check(err)
   269  		}
   270  	}
   271  	_, err = b.Finish()
   272  	y.Check(err)
   273  	f.Close()
   274  	table, err := OpenTable(filename, testCache(), testCache())
   275  	require.NoError(t, err)
   276  	require.NoError(t, table.SetGlobalTs(10))
   277  
   278  	require.NoError(t, table.Close())
   279  	table, err = OpenTable(filename, testCache(), testCache())
   280  	require.NoError(t, err)
   281  	defer table.Delete()
   282  
   283  	it := table.newIterator(false)
   284  	defer it.Close()
   285  	count := 0
   286  	for it.Rewind(); it.Valid(); it.Next() {
   287  		v := it.Value()
   288  		k := y.KeyWithTs([]byte(key("key", count)), 10)
   289  		require.EqualValues(t, k, it.Key())
   290  		require.EqualValues(t, fmt.Sprintf("%d", count), string(v.Value))
   291  		count++
   292  	}
   293  	require.Equal(t, count, n)
   294  }
   295  
   296  func TestSeekToFirst(t *testing.T) {
   297  	for _, n := range []int{99, 100, 101, 199, 200, 250, 9999, 10000} {
   298  		t.Run(fmt.Sprintf("n=%d", n), func(t *testing.T) {
   299  			f := buildTestTable(t, "key", n)
   300  			table, err := OpenTable(f.Name(), testCache(), testCache())
   301  			require.NoError(t, err)
   302  			defer table.Delete()
   303  			it := table.newIterator(false)
   304  			defer it.Close()
   305  			it.seekToFirst()
   306  			require.True(t, it.Valid())
   307  			v := it.Value()
   308  			require.EqualValues(t, "0", string(v.Value))
   309  			require.EqualValues(t, 'A', v.Meta)
   310  		})
   311  	}
   312  }
   313  
   314  func TestSeekToLast(t *testing.T) {
   315  	for _, n := range []int{99, 100, 101, 199, 200, 250, 9999, 10000} {
   316  		t.Run(fmt.Sprintf("n=%d", n), func(t *testing.T) {
   317  			f := buildTestTable(t, "key", n)
   318  			table, err := OpenTable(f.Name(), testCache(), testCache())
   319  			require.NoError(t, err)
   320  			defer table.Delete()
   321  			it := table.newIterator(false)
   322  			defer it.Close()
   323  			it.seekToLast()
   324  			require.True(t, it.Valid())
   325  			v := it.Value()
   326  			require.EqualValues(t, fmt.Sprintf("%d", n-1), string(v.Value))
   327  			require.EqualValues(t, 'A', v.Meta)
   328  			it.prev()
   329  			require.True(t, it.Valid())
   330  			v = it.Value()
   331  			require.EqualValues(t, fmt.Sprintf("%d", n-2), string(v.Value))
   332  			require.EqualValues(t, 'A', v.Meta)
   333  		})
   334  	}
   335  }
   336  
   337  func TestSeekBasic(t *testing.T) {
   338  	f := buildTestTable(t, "k", 10000)
   339  	table, err := OpenTable(f.Name(), testCache(), testCache())
   340  	require.NoError(t, err)
   341  	defer table.Delete()
   342  
   343  	it := table.newIterator(false)
   344  	defer it.Close()
   345  
   346  	var data = []struct {
   347  		in    string
   348  		valid bool
   349  		out   string
   350  	}{
   351  		{"abc", true, "k0000"},
   352  		{"k0100", true, "k0100"},
   353  		{"k0100b", true, "k0101"}, // Test case where we jump to next block.
   354  		{"k1234", true, "k1234"},
   355  		{"k1234b", true, "k1235"},
   356  		{"k9999", true, "k9999"},
   357  		{"z", false, ""},
   358  	}
   359  
   360  	for _, tt := range data {
   361  		it.seek([]byte(tt.in))
   362  		if !tt.valid {
   363  			require.False(t, it.Valid())
   364  			continue
   365  		}
   366  		require.True(t, it.Valid())
   367  		k := it.Key()
   368  		require.EqualValues(t, tt.out, string(k.UserKey))
   369  	}
   370  }
   371  
   372  func TestSeekForPrev(t *testing.T) {
   373  	f := buildTestTable(t, "k", 10000)
   374  	table, err := OpenTable(f.Name(), testCache(), testCache())
   375  	require.NoError(t, err)
   376  	defer table.Delete()
   377  
   378  	it := table.newIterator(false)
   379  	defer it.Close()
   380  
   381  	var data = []struct {
   382  		in    string
   383  		valid bool
   384  		out   string
   385  	}{
   386  		{"abc", false, ""},
   387  		{"k0100", true, "k0100"},
   388  		{"k0100b", true, "k0100"}, // Test case where we jump to next block.
   389  		{"k1234", true, "k1234"},
   390  		{"k1234b", true, "k1234"},
   391  		{"k9999", true, "k9999"},
   392  		{"z", true, "k9999"},
   393  	}
   394  
   395  	for _, tt := range data {
   396  		it.seekForPrev([]byte(tt.in))
   397  		if !tt.valid {
   398  			require.False(t, it.Valid())
   399  			continue
   400  		}
   401  		require.True(t, it.Valid())
   402  		k := it.Key()
   403  		require.EqualValues(t, tt.out, string(k.UserKey))
   404  	}
   405  }
   406  
   407  func TestIterateFromStart(t *testing.T) {
   408  	// Vary the number of elements added.
   409  	for _, n := range []int{99, 100, 101, 199, 200, 250, 9999, 10000} {
   410  		t.Run(fmt.Sprintf("n=%d", n), func(t *testing.T) {
   411  			f := buildTestTable(t, "key", n)
   412  			table, err := OpenTable(f.Name(), testCache(), testCache())
   413  			require.NoError(t, err)
   414  			defer table.Delete()
   415  			ti := table.newIterator(false)
   416  			defer ti.Close()
   417  			ti.reset()
   418  			ti.seekToFirst()
   419  			require.True(t, ti.Valid())
   420  			// No need to do a Next.
   421  			// ti.Seek brings us to the first key >= "". Essentially a SeekToFirst.
   422  			var count int
   423  			for ; ti.Valid(); ti.next() {
   424  				v := ti.Value()
   425  				require.EqualValues(t, fmt.Sprintf("%d", count), string(v.Value))
   426  				require.EqualValues(t, 'A', v.Meta)
   427  				count++
   428  			}
   429  			require.EqualValues(t, n, count)
   430  		})
   431  	}
   432  }
   433  
   434  func TestIterateFromEnd(t *testing.T) {
   435  	// Vary the number of elements added.
   436  	for _, n := range []int{99, 100, 101, 199, 200, 250, 9999, 10000} {
   437  		t.Run(fmt.Sprintf("n=%d", n), func(t *testing.T) {
   438  			f := buildTestTable(t, "key", n)
   439  			table, err := OpenTable(f.Name(), testCache(), testCache())
   440  			require.NoError(t, err)
   441  			defer table.Delete()
   442  			ti := table.newIterator(false)
   443  			defer ti.Close()
   444  			ti.reset()
   445  			ti.seek([]byte("zzzzzz")) // Seek to end, an invalid element.
   446  			require.False(t, ti.Valid())
   447  			ti.seekToLast()
   448  			for i := n - 1; i >= 0; i-- {
   449  				require.True(t, ti.Valid())
   450  				v := ti.Value()
   451  				require.EqualValues(t, fmt.Sprintf("%d", i), string(v.Value))
   452  				require.EqualValues(t, 'A', v.Meta)
   453  				ti.prev()
   454  			}
   455  			ti.prev()
   456  			require.False(t, ti.Valid())
   457  		})
   458  	}
   459  }
   460  
   461  func TestTable(t *testing.T) {
   462  	f := buildTestTable(t, "key", 10000)
   463  	table, err := OpenTable(f.Name(), testCache(), testCache())
   464  	require.NoError(t, err)
   465  	defer table.Delete()
   466  	ti := table.newIterator(false)
   467  	defer ti.Close()
   468  	kid := 1010
   469  	seek := y.KeyWithTs([]byte(key("key", kid)), 0)
   470  	for ti.seek(seek.UserKey); ti.Valid(); ti.next() {
   471  		k := ti.Key()
   472  		require.EqualValues(t, string(k.UserKey), key("key", kid))
   473  		kid++
   474  	}
   475  	if kid != 10000 {
   476  		t.Errorf("Expected kid: 10000. Got: %v", kid)
   477  	}
   478  
   479  	ti.seek([]byte(key("key", 99999)))
   480  	require.False(t, ti.Valid())
   481  
   482  	ti.seek([]byte(key("key", -1)))
   483  	require.True(t, ti.Valid())
   484  	k := ti.Key()
   485  	require.EqualValues(t, string(k.UserKey), key("key", 0))
   486  }
   487  
   488  func TestIterateBackAndForth(t *testing.T) {
   489  	f := buildTestTable(t, "key", 10000)
   490  	table, err := OpenTable(f.Name(), testCache(), testCache())
   491  	require.NoError(t, err)
   492  	defer table.Delete()
   493  
   494  	seek := y.KeyWithTs([]byte(key("key", 1010)), 0)
   495  	it := table.newIterator(false)
   496  	defer it.Close()
   497  	it.seek(seek.UserKey)
   498  	require.True(t, it.Valid())
   499  	k := it.Key()
   500  	require.EqualValues(t, seek, k)
   501  
   502  	it.prev()
   503  	it.prev()
   504  	require.True(t, it.Valid())
   505  	k = it.Key()
   506  	require.EqualValues(t, key("key", 1008), string(k.UserKey))
   507  
   508  	it.next()
   509  	it.next()
   510  	require.True(t, it.Valid())
   511  	k = it.Key()
   512  	require.EqualValues(t, key("key", 1010), k.UserKey)
   513  
   514  	it.seek([]byte(key("key", 2000)))
   515  	require.True(t, it.Valid())
   516  	k = it.Key()
   517  	require.EqualValues(t, key("key", 2000), k.UserKey)
   518  
   519  	it.prev()
   520  	require.True(t, it.Valid())
   521  	k = it.Key()
   522  	require.EqualValues(t, key("key", 1999), k.UserKey)
   523  
   524  	it.seekToFirst()
   525  	k = it.Key()
   526  	require.EqualValues(t, key("key", 0), k.UserKey)
   527  }
   528  
   529  func TestIterateMultiVersion(t *testing.T) {
   530  	f, allCnt := buildMultiVersionTable(generateKeyValues("key", 4000))
   531  	table, err := OpenTable(f.Name(), testCache(), testCache())
   532  	require.NoError(t, err)
   533  	defer table.Delete()
   534  	it := table.newIterator(false)
   535  	defer it.Close()
   536  	itCnt := 0
   537  	var lastKey y.Key
   538  	for it.Rewind(); it.Valid(); it.Next() {
   539  		if !lastKey.IsEmpty() {
   540  			require.True(t, lastKey.Compare(it.Key()) < 0)
   541  		}
   542  		lastKey.Copy(it.Key())
   543  		itCnt++
   544  		for it.NextVersion() {
   545  			itCnt++
   546  		}
   547  	}
   548  	require.Equal(t, itCnt, allCnt)
   549  	for i := 0; i < 1000; i++ {
   550  		k := y.KeyWithTs([]byte(key("key", int(z.FastRand()%4000))), uint64(5+z.FastRand()%5))
   551  		kHash := farm.Fingerprint64(k.UserKey)
   552  		gotKey, _, ok, _ := table.pointGet(k, kHash)
   553  		if ok {
   554  			if !gotKey.IsEmpty() {
   555  				require.True(t, gotKey.SameUserKey(k))
   556  				require.True(t, gotKey.Compare(k) >= 0)
   557  			}
   558  		} else {
   559  			it.Seek(k.UserKey)
   560  			if it.Valid() {
   561  				require.True(t, it.Key().Version == 9)
   562  				require.True(t, bytes.Compare(it.Key().UserKey, k.UserKey) >= 0)
   563  				if y.SeekToVersion(it, k.Version) {
   564  					require.True(t, it.Key().Version <= k.Version)
   565  				}
   566  			}
   567  		}
   568  	}
   569  	revIt := table.newIterator(true)
   570  	defer revIt.Close()
   571  	lastKey.Reset()
   572  	for revIt.Rewind(); revIt.Valid(); revIt.Next() {
   573  		if !lastKey.IsEmpty() {
   574  			require.Truef(t, lastKey.Compare(revIt.Key()) > 0, "%v %v", lastKey.String(), revIt.Key().String())
   575  		}
   576  		lastKey.Copy(revIt.Key())
   577  	}
   578  	for i := 0; i < 1000; i++ {
   579  		k := y.KeyWithTs([]byte(key("key", int(z.FastRand()%4000))), uint64(5+z.FastRand()%5))
   580  		// reverse iterator never seek to the same key with smaller version.
   581  		revIt.Seek(k.UserKey)
   582  		if !revIt.Valid() {
   583  			continue
   584  		}
   585  		require.True(t, revIt.Key().Version == 9)
   586  		require.True(t, revIt.Key().Compare(k) <= 0, "%s %s", revIt.Key(), k)
   587  	}
   588  }
   589  
   590  func TestUniIterator(t *testing.T) {
   591  	f := buildTestTable(t, "key", 10000)
   592  	table, err := OpenTable(f.Name(), testCache(), testCache())
   593  	require.NoError(t, err)
   594  	defer table.Delete()
   595  	{
   596  		it := table.newIterator(false)
   597  		defer it.Close()
   598  		var count int
   599  		for it.Rewind(); it.Valid(); it.Next() {
   600  			v := it.Value()
   601  			require.EqualValues(t, fmt.Sprintf("%d", count), string(v.Value))
   602  			require.EqualValues(t, 'A', v.Meta)
   603  			count++
   604  		}
   605  		require.EqualValues(t, 10000, count)
   606  	}
   607  	{
   608  		it := table.newIterator(true)
   609  		defer it.Close()
   610  		var count int
   611  		for it.Rewind(); it.Valid(); it.Next() {
   612  			v := it.Value()
   613  			require.EqualValues(t, fmt.Sprintf("%d", 10000-1-count), string(v.Value))
   614  			require.EqualValues(t, 'A', v.Meta)
   615  			count++
   616  		}
   617  		require.EqualValues(t, 10000, count)
   618  	}
   619  }
   620  
   621  // Try having only one table.
   622  func TestConcatIteratorOneTable(t *testing.T) {
   623  	f := buildTable(t, [][]string{
   624  		{"k1", "a1"},
   625  		{"k2", "a2"},
   626  	})
   627  
   628  	tbl, err := OpenTable(f.Name(), testCache(), testCache())
   629  	require.NoError(t, err)
   630  	defer tbl.Delete()
   631  
   632  	it := table.NewConcatIterator([]table.Table{tbl}, false)
   633  	defer it.Close()
   634  
   635  	it.Rewind()
   636  	require.True(t, it.Valid())
   637  	k := it.Key()
   638  	require.EqualValues(t, "k1", string(k.UserKey))
   639  	vs := it.Value()
   640  	require.EqualValues(t, "a1", string(vs.Value))
   641  	require.EqualValues(t, 'A', vs.Meta)
   642  }
   643  
   644  func TestConcatIterator(t *testing.T) {
   645  	f := buildTestTable(t, "keya", 10000)
   646  	f2 := buildTestTable(t, "keyb", 10000)
   647  	f3 := buildTestTable(t, "keyc", 10000)
   648  	blkCache, idxCache := testCache(), testCache()
   649  	tbl, err := OpenTable(f.Name(), blkCache, idxCache)
   650  	require.NoError(t, err)
   651  	defer tbl.Delete()
   652  	tbl2, err := OpenTable(f2.Name(), blkCache, idxCache)
   653  	require.NoError(t, err)
   654  	defer tbl2.Delete()
   655  	tbl3, err := OpenTable(f3.Name(), blkCache, idxCache)
   656  	require.NoError(t, err)
   657  	defer tbl3.Delete()
   658  
   659  	{
   660  		it := table.NewConcatIterator([]table.Table{tbl, tbl2, tbl3}, false)
   661  		defer it.Close()
   662  		it.Rewind()
   663  		require.True(t, it.Valid())
   664  		var count int
   665  		for ; it.Valid(); it.Next() {
   666  			vs := it.Value()
   667  			require.EqualValues(t, fmt.Sprintf("%d", count%10000), string(vs.Value))
   668  			require.EqualValues(t, 'A', vs.Meta)
   669  			count++
   670  		}
   671  		require.EqualValues(t, 30000, count)
   672  
   673  		it.Seek([]byte("a"))
   674  		require.EqualValues(t, "keya0000", string(it.Key().UserKey))
   675  		vs := it.Value()
   676  		require.EqualValues(t, "0", string(vs.Value))
   677  
   678  		it.Seek([]byte("keyb"))
   679  		require.EqualValues(t, "keyb0000", string(it.Key().UserKey))
   680  		vs = it.Value()
   681  		require.EqualValues(t, "0", string(vs.Value))
   682  
   683  		it.Seek([]byte("keyb9999b"))
   684  		require.EqualValues(t, "keyc0000", string(it.Key().UserKey))
   685  		vs = it.Value()
   686  		require.EqualValues(t, "0", string(vs.Value))
   687  
   688  		it.Seek([]byte("keyd"))
   689  		require.False(t, it.Valid())
   690  	}
   691  	{
   692  		it := table.NewConcatIterator([]table.Table{tbl, tbl2, tbl3}, true)
   693  		defer it.Close()
   694  		it.Rewind()
   695  		require.True(t, it.Valid())
   696  		var count int
   697  		for ; it.Valid(); it.Next() {
   698  			vs := it.Value()
   699  			require.EqualValues(t, fmt.Sprintf("%d", 10000-(count%10000)-1), string(vs.Value))
   700  			require.EqualValues(t, 'A', vs.Meta)
   701  			count++
   702  		}
   703  		require.EqualValues(t, 30000, count)
   704  
   705  		it.Seek([]byte("a"))
   706  		require.False(t, it.Valid())
   707  
   708  		it.Seek([]byte("keyb"))
   709  		require.EqualValues(t, "keya9999", string(it.Key().UserKey))
   710  		vs := it.Value()
   711  		require.EqualValues(t, "9999", string(vs.Value))
   712  
   713  		it.Seek([]byte("keyb9999b"))
   714  		require.EqualValues(t, "keyb9999", string(it.Key().UserKey))
   715  		vs = it.Value()
   716  		require.EqualValues(t, "9999", string(vs.Value))
   717  
   718  		it.Seek([]byte("keyd"))
   719  		require.EqualValues(t, "keyc9999", string(it.Key().UserKey))
   720  		vs = it.Value()
   721  		require.EqualValues(t, "9999", string(vs.Value))
   722  	}
   723  }
   724  
   725  func TestMergingIterator(t *testing.T) {
   726  	f1 := buildTable(t, [][]string{
   727  		{"k1", "a1"},
   728  		{"k2", "a2"},
   729  	})
   730  	f2 := buildTable(t, [][]string{
   731  		{"k1", "b1"},
   732  		{"k2", "b2"},
   733  	})
   734  	blkCache, idxCache := testCache(), testCache()
   735  	tbl1, err := OpenTable(f1.Name(), blkCache, idxCache)
   736  	require.NoError(t, err)
   737  	defer tbl1.Delete()
   738  	tbl2, err := OpenTable(f2.Name(), blkCache, idxCache)
   739  	require.NoError(t, err)
   740  	defer tbl2.Delete()
   741  	it1 := tbl1.newIterator(false)
   742  	it2 := table.NewConcatIterator([]table.Table{tbl2}, false)
   743  	it := table.NewMergeIterator([]y.Iterator{it1, it2}, false)
   744  	defer it.Close()
   745  
   746  	it.Rewind()
   747  	require.True(t, it.Valid())
   748  	k := it.Key()
   749  	require.EqualValues(t, "k1", string(k.UserKey))
   750  	vs := it.Value()
   751  	require.EqualValues(t, "a1", string(vs.Value))
   752  	require.EqualValues(t, 'A', vs.Meta)
   753  	it.Next()
   754  
   755  	require.True(t, it.Valid())
   756  	k = it.Key()
   757  	require.EqualValues(t, "k2", string(k.UserKey))
   758  	vs = it.Value()
   759  	require.EqualValues(t, "a2", string(vs.Value))
   760  	require.EqualValues(t, 'A', vs.Meta)
   761  	it.Next()
   762  
   763  	require.False(t, it.Valid())
   764  }
   765  
   766  func TestMergingIteratorReversed(t *testing.T) {
   767  	f1 := buildTable(t, [][]string{
   768  		{"k1", "a1"},
   769  		{"k2", "a2"},
   770  	})
   771  	f2 := buildTable(t, [][]string{
   772  		{"k1", "b1"},
   773  		{"k2", "b2"},
   774  	})
   775  	blkCache, idxCache := testCache(), testCache()
   776  	tbl1, err := OpenTable(f1.Name(), blkCache, idxCache)
   777  	require.NoError(t, err)
   778  	defer tbl1.Delete()
   779  	tbl2, err := OpenTable(f2.Name(), blkCache, idxCache)
   780  	require.NoError(t, err)
   781  	defer tbl2.Delete()
   782  	it1 := tbl1.newIterator(true)
   783  	it2 := table.NewConcatIterator([]table.Table{tbl2}, true)
   784  	it := table.NewMergeIterator([]y.Iterator{it1, it2}, true)
   785  	defer it.Close()
   786  
   787  	it.Rewind()
   788  	require.True(t, it.Valid())
   789  	k := it.Key()
   790  	require.EqualValues(t, "k2", string(k.UserKey))
   791  	vs := it.Value()
   792  	require.EqualValues(t, "a2", string(vs.Value))
   793  	require.EqualValues(t, 'A', vs.Meta)
   794  	it.Next()
   795  
   796  	require.True(t, it.Valid())
   797  	k = it.Key()
   798  	require.EqualValues(t, "k1", string(k.UserKey))
   799  	vs = it.Value()
   800  	require.EqualValues(t, "a1", string(vs.Value))
   801  	require.EqualValues(t, 'A', vs.Meta)
   802  	it.Next()
   803  
   804  	require.False(t, it.Valid())
   805  }
   806  
   807  // Take only the first iterator.
   808  func TestMergingIteratorTakeOne(t *testing.T) {
   809  	f1 := buildTable(t, [][]string{
   810  		{"k1", "a1"},
   811  		{"k2", "a2"},
   812  	})
   813  	f2 := buildTable(t, [][]string{{"l1", "b1"}})
   814  
   815  	blkCache, idxCache := testCache(), testCache()
   816  	t1, err := OpenTable(f1.Name(), blkCache, idxCache)
   817  	require.NoError(t, err)
   818  	defer t1.Delete()
   819  	t2, err := OpenTable(f2.Name(), blkCache, idxCache)
   820  	require.NoError(t, err)
   821  	defer t2.Delete()
   822  
   823  	it1 := table.NewConcatIterator([]table.Table{t1}, false)
   824  	it2 := table.NewConcatIterator([]table.Table{t2}, false)
   825  	it := table.NewMergeIterator([]y.Iterator{it1, it2}, false)
   826  	defer it.Close()
   827  
   828  	it.Rewind()
   829  	require.True(t, it.Valid())
   830  	k := it.Key()
   831  	require.EqualValues(t, "k1", string(k.UserKey))
   832  	vs := it.Value()
   833  	require.EqualValues(t, "a1", string(vs.Value))
   834  	require.EqualValues(t, 'A', vs.Meta)
   835  	it.Next()
   836  
   837  	require.True(t, it.Valid())
   838  	k = it.Key()
   839  	require.EqualValues(t, "k2", string(k.UserKey))
   840  	vs = it.Value()
   841  	require.EqualValues(t, "a2", string(vs.Value))
   842  	require.EqualValues(t, 'A', vs.Meta)
   843  	it.Next()
   844  
   845  	k = it.Key()
   846  	require.EqualValues(t, "l1", string(k.UserKey))
   847  	vs = it.Value()
   848  	require.EqualValues(t, "b1", string(vs.Value))
   849  	require.EqualValues(t, 'A', vs.Meta)
   850  	it.Next()
   851  
   852  	require.False(t, it.Valid())
   853  }
   854  
   855  // Take only the second iterator.
   856  func TestMergingIteratorTakeTwo(t *testing.T) {
   857  	f1 := buildTable(t, [][]string{{"l1", "b1"}})
   858  	f2 := buildTable(t, [][]string{
   859  		{"k1", "a1"},
   860  		{"k2", "a2"},
   861  	})
   862  	blkCache, idxCache := testCache(), testCache()
   863  	t1, err := OpenTable(f1.Name(), blkCache, idxCache)
   864  	require.NoError(t, err)
   865  	defer t1.Delete()
   866  	t2, err := OpenTable(f2.Name(), blkCache, idxCache)
   867  	require.NoError(t, err)
   868  	defer t2.Delete()
   869  
   870  	it1 := table.NewConcatIterator([]table.Table{t1}, false)
   871  	it2 := table.NewConcatIterator([]table.Table{t2}, false)
   872  	it := table.NewMergeIterator([]y.Iterator{it1, it2}, false)
   873  	defer it.Close()
   874  
   875  	it.Rewind()
   876  	require.True(t, it.Valid())
   877  	k := it.Key()
   878  	require.EqualValues(t, "k1", string(k.UserKey))
   879  	vs := it.Value()
   880  	require.EqualValues(t, "a1", string(vs.Value))
   881  	require.EqualValues(t, 'A', vs.Meta)
   882  	it.Next()
   883  
   884  	require.True(t, it.Valid())
   885  	k = it.Key()
   886  	require.EqualValues(t, "k2", string(k.UserKey))
   887  	vs = it.Value()
   888  	require.EqualValues(t, "a2", string(vs.Value))
   889  	require.EqualValues(t, 'A', vs.Meta)
   890  	it.Next()
   891  	require.True(t, it.Valid())
   892  
   893  	k = it.Key()
   894  	require.EqualValues(t, "l1", string(k.UserKey))
   895  	vs = it.Value()
   896  	require.EqualValues(t, "b1", string(vs.Value))
   897  	require.EqualValues(t, 'A', vs.Meta)
   898  	it.Next()
   899  
   900  	require.False(t, it.Valid())
   901  }
   902  
   903  func TestSeekInvalidIssue(t *testing.T) {
   904  	keys := make([][]byte, 1024)
   905  	for i := 0; i < len(keys); i++ {
   906  		key := make([]byte, 8)
   907  		binary.BigEndian.PutUint64(key, uint64(i))
   908  		keys[i] = key
   909  	}
   910  	// TODO:
   911  	// FIXME: if set surf to true it always fail.
   912  	b, f := newTableBuilderForTest(false)
   913  	for _, key := range keys {
   914  		err := b.Add(y.KeyWithTs(key, 0), y.ValueStruct{Value: key, Meta: 'A', UserMeta: []byte{0}})
   915  		if t != nil {
   916  			require.NoError(t, err)
   917  		} else {
   918  			y.Check(err)
   919  		}
   920  	}
   921  	_, err := b.Finish()
   922  	y.Check(err)
   923  	y.Check(f.Close())
   924  	f, _ = y.OpenSyncedFile(f.Name(), true)
   925  	t1, err := OpenTable(f.Name(), nil, nil)
   926  
   927  	require.NoError(t, err)
   928  	defer t1.Delete()
   929  	it := t1.NewIterator(false).(*Iterator)
   930  	defer it.Close()
   931  	for i := 1; i < it.tIdx.baseKeys.length(); i++ {
   932  		baseKey := it.tIdx.baseKeys.getEntry(i)
   933  		idx := sort.Search(len(keys), func(i int) bool {
   934  			return bytes.Compare(keys[i], baseKey) >= 0
   935  		})
   936  		seekKey := y.SafeCopy(nil, keys[idx-1])
   937  		seekKey = append(seekKey, 0)
   938  		it.Seek(seekKey)
   939  		require.True(t, it.Valid(), "candidate key %v, baseKey %v %d", seekKey, baseKey, i)
   940  	}
   941  }
   942  
   943  func TestOpenImMemoryTable(t *testing.T) {
   944  	file := buildTestTable(t, "in-mem", 1000)
   945  	blockData, err := ioutil.ReadFile(file.Name())
   946  	require.Nil(t, err)
   947  	idxData, err := ioutil.ReadFile(IndexFilename(file.Name()))
   948  	require.Nil(t, err)
   949  	inMemTbl, err := OpenInMemoryTable(blockData, idxData)
   950  	require.Nil(t, err)
   951  	fileTable, err := OpenTable(file.Name(), nil, nil)
   952  	require.Nil(t, err)
   953  	inMemIt := inMemTbl.NewIterator(false)
   954  	defer inMemIt.Close()
   955  	inMemIt.Rewind()
   956  	fileIt := fileTable.NewIterator(false)
   957  	defer fileIt.Close()
   958  	fileIt.Rewind()
   959  	for ; fileIt.Valid(); fileIt.Next() {
   960  		if fileIt.Valid() {
   961  			require.True(t, inMemIt.Valid())
   962  			require.EqualValues(t, fileIt.Key(), inMemIt.Key())
   963  			require.EqualValues(t, fileIt.Value(), inMemIt.Value())
   964  		}
   965  		inMemIt.Next()
   966  	}
   967  }
   968  
   969  func TestBuildImMemoryTable(t *testing.T) {
   970  	b := NewTableBuilder(nil, nil, 0, defaultBuilderOpt)
   971  	keyValues := generateKeyValues("in-mem", 1000)
   972  	sort.Slice(keyValues, func(i, j int) bool {
   973  		return keyValues[i][0] < keyValues[j][0]
   974  	})
   975  	for _, kv := range keyValues {
   976  		y.Assert(len(kv) == 2)
   977  		err := b.Add(y.KeyWithTs([]byte(kv[0]), 0), y.ValueStruct{Value: []byte(kv[1]), Meta: 'A', UserMeta: []byte{0}})
   978  		if t != nil {
   979  			require.NoError(t, err)
   980  		} else {
   981  			y.Check(err)
   982  		}
   983  	}
   984  	result, err := b.Finish()
   985  	y.Check(err)
   986  	require.NotNil(t, result.FileData)
   987  	require.NotNil(t, result.IndexData)
   988  	tbl, err := OpenInMemoryTable(result.FileData, result.IndexData)
   989  	y.Check(err)
   990  	for _, kv := range keyValues {
   991  		key := y.KeyWithTs([]byte(kv[0]), 0)
   992  		keyHash := farm.Fingerprint64(key.UserKey)
   993  		v, err := tbl.Get(key, keyHash)
   994  		require.Nil(t, err)
   995  		require.EqualValues(t, v.Value, []byte(kv[1]))
   996  	}
   997  }
   998  
   999  func BenchmarkRead(b *testing.B) {
  1000  	n := 5 << 20
  1001  	filename := fmt.Sprintf("%s%s%d.sst", os.TempDir(), string(os.PathSeparator), rand.Uint32())
  1002  	f, err := y.OpenSyncedFile(filename, true)
  1003  	y.Check(err)
  1004  	builder := NewTableBuilder(f, nil, 0, defaultBuilderOpt)
  1005  	for i := 0; i < n; i++ {
  1006  		k := fmt.Sprintf("%016x", i)
  1007  		v := fmt.Sprintf("%d", i)
  1008  		y.Check(builder.Add(y.KeyWithTs([]byte(k), 0), y.ValueStruct{Value: []byte(v), Meta: 123, UserMeta: []byte{0}}))
  1009  	}
  1010  	_, err = builder.Finish()
  1011  	y.Check(err)
  1012  	tbl, err := OpenTable(f.Name(), testCache(), testCache())
  1013  	y.Check(err)
  1014  	defer tbl.Delete()
  1015  
  1016  	//	y.Printf("Size of table: %d\n", tbl.Size())
  1017  	b.ResetTimer()
  1018  	// Iterate b.N times over the entire table.
  1019  	for i := 0; i < b.N; i++ {
  1020  		func() {
  1021  			it := tbl.newIterator(false)
  1022  			defer it.Close()
  1023  			for it.seekToFirst(); it.Valid(); it.next() {
  1024  			}
  1025  		}()
  1026  	}
  1027  }
  1028  
  1029  func BenchmarkBuildTable(b *testing.B) {
  1030  	ns := []int{1000, 10000, 100000, 1000000, 5000000, 10000000, 15000000}
  1031  	for _, n := range ns {
  1032  		kvs := make([]struct {
  1033  			k y.Key
  1034  			v []byte
  1035  		}, n)
  1036  		for i := 0; i < n; i++ {
  1037  			kvs[i].k = y.KeyWithTs([]byte(fmt.Sprintf("%016x", i)), 0)
  1038  			kvs[i].v = []byte(fmt.Sprintf("%d", i))
  1039  		}
  1040  		b.ResetTimer()
  1041  
  1042  		b.Run(fmt.Sprintf("NoHash_%d", n), func(b *testing.B) {
  1043  			filename := fmt.Sprintf("%s%s%d.sst", os.TempDir(), string(os.PathSeparator), rand.Uint32())
  1044  			f, err := y.OpenSyncedFile(filename, false)
  1045  			y.Check(err)
  1046  			opt := defaultBuilderOpt
  1047  			for bn := 0; bn < b.N; bn++ {
  1048  				builder := NewTableBuilder(f, nil, 0, opt)
  1049  				for i := 0; i < n; i++ {
  1050  					y.Check(builder.Add(kvs[i].k, y.ValueStruct{Value: kvs[i].v, Meta: 123, UserMeta: []byte{0}}))
  1051  				}
  1052  				_, err = builder.Finish()
  1053  				y.Check(err)
  1054  				_, err := f.Seek(0, io.SeekStart)
  1055  				y.Check(err)
  1056  			}
  1057  		})
  1058  
  1059  		b.Run(fmt.Sprintf("Hash_%d", n), func(b *testing.B) {
  1060  			filename := fmt.Sprintf("%s%s%d.sst", os.TempDir(), string(os.PathSeparator), rand.Uint32())
  1061  			f, err := y.OpenSyncedFile(filename, false)
  1062  			y.Check(err)
  1063  			for bn := 0; bn < b.N; bn++ {
  1064  				builder := NewTableBuilder(f, nil, 0, defaultBuilderOpt)
  1065  				for i := 0; i < n; i++ {
  1066  					y.Check(builder.Add(kvs[i].k, y.ValueStruct{Value: kvs[i].v, Meta: 123, UserMeta: []byte{0}}))
  1067  				}
  1068  				_, err = builder.Finish()
  1069  				y.Check(err)
  1070  				_, err := f.Seek(0, io.SeekStart)
  1071  				y.Check(err)
  1072  			}
  1073  		})
  1074  	}
  1075  }
  1076  
  1077  var cacheConfig = cache.Config{
  1078  	NumCounters: 1000000 * 10,
  1079  	MaxCost:     1000000,
  1080  	BufferItems: 64,
  1081  	Metrics:     true,
  1082  }
  1083  
  1084  func BenchmarkPointGet(b *testing.B) {
  1085  	ns := []int{1000, 10000, 100000, 1000000, 5000000, 10000000, 15000000}
  1086  	for _, n := range ns {
  1087  		filename := fmt.Sprintf("%s%s%d.sst", os.TempDir(), string(os.PathSeparator), rand.Uint32())
  1088  		f, err := y.OpenSyncedFile(filename, true)
  1089  		builder := NewTableBuilder(f, nil, 0, defaultBuilderOpt)
  1090  		keys := make([]y.Key, n)
  1091  		y.Check(err)
  1092  		for i := 0; i < n; i++ {
  1093  			k := y.KeyWithTs([]byte(fmt.Sprintf("%016x", i)), 0)
  1094  			v := fmt.Sprintf("%d", i)
  1095  			keys[i] = k
  1096  			y.Check(builder.Add(k, y.ValueStruct{Value: []byte(v), Meta: 123, UserMeta: []byte{0}}))
  1097  		}
  1098  		_, err = builder.Finish()
  1099  		y.Check(err)
  1100  		tbl, err := OpenTable(filename, testCache(), testCache())
  1101  		y.Check(err)
  1102  		b.ResetTimer()
  1103  
  1104  		b.Run(fmt.Sprintf("Seek_%d", n), func(b *testing.B) {
  1105  			var vs y.ValueStruct
  1106  			rand := rand.New(rand.NewSource(0))
  1107  			for bn := 0; bn < b.N; bn++ {
  1108  				rand.Seed(0)
  1109  				for i := 0; i < n; i++ {
  1110  					k := keys[rand.Intn(n)]
  1111  					it := tbl.newIterator(false)
  1112  					defer it.Close()
  1113  					it.Seek(k.UserKey)
  1114  					if !it.Valid() {
  1115  						continue
  1116  					}
  1117  					if !k.SameUserKey(it.Key()) {
  1118  						continue
  1119  					}
  1120  					vs = it.Value()
  1121  				}
  1122  			}
  1123  			_ = vs
  1124  		})
  1125  
  1126  		b.Run(fmt.Sprintf("Hash_%d", n), func(b *testing.B) {
  1127  			var (
  1128  				resultKey y.Key
  1129  				resultVs  y.ValueStruct
  1130  				ok        bool
  1131  			)
  1132  			rand := rand.New(rand.NewSource(0))
  1133  			for bn := 0; bn < b.N; bn++ {
  1134  				rand.Seed(0)
  1135  				for i := 0; i < n; i++ {
  1136  					k := keys[rand.Intn(n)]
  1137  					keyHash := farm.Fingerprint64(k.UserKey)
  1138  					resultKey, resultVs, ok, _ = tbl.pointGet(k, keyHash)
  1139  					if !ok {
  1140  						it := tbl.newIterator(false)
  1141  						defer it.Close()
  1142  						it.Seek(k.UserKey)
  1143  						if !it.Valid() {
  1144  							continue
  1145  						}
  1146  						if !k.SameUserKey(it.Key()) {
  1147  							continue
  1148  						}
  1149  						resultKey, resultVs = it.Key(), it.Value()
  1150  					}
  1151  				}
  1152  			}
  1153  			_, _ = resultKey, resultVs
  1154  		})
  1155  
  1156  		tbl.Delete()
  1157  	}
  1158  }
  1159  
  1160  func BenchmarkReadAndBuild(b *testing.B) {
  1161  	n := 5 << 20
  1162  	filename := fmt.Sprintf("%s%s%d.sst", os.TempDir(), string(os.PathSeparator), rand.Uint32())
  1163  	f, err := y.OpenSyncedFile(filename, false)
  1164  	builder := NewTableBuilder(f, nil, 0, defaultBuilderOpt)
  1165  	y.Check(err)
  1166  	for i := 0; i < n; i++ {
  1167  		k := y.KeyWithTs([]byte(fmt.Sprintf("%016x", i)), 0)
  1168  		v := fmt.Sprintf("%d", i)
  1169  		y.Check(builder.Add(k, y.ValueStruct{Value: []byte(v), Meta: 123, UserMeta: []byte{0}}))
  1170  	}
  1171  	_, err = builder.Finish()
  1172  	y.Check(err)
  1173  	tbl, err := OpenTable(f.Name(), testCache(), testCache())
  1174  	y.Check(err)
  1175  	defer tbl.Delete()
  1176  
  1177  	//	y.Printf("Size of table: %d\n", tbl.Size())
  1178  	b.ResetTimer()
  1179  	// Iterate b.N times over the entire table.
  1180  	filename = fmt.Sprintf("%s%s%d.sst", os.TempDir(), string(os.PathSeparator), rand.Uint32())
  1181  	f, err = y.OpenSyncedFile(filename, false)
  1182  	y.Check(err)
  1183  	for i := 0; i < b.N; i++ {
  1184  		func() {
  1185  			newBuilder := NewTableBuilder(f, nil, 0, options.TableBuilderOptions{})
  1186  			it := tbl.newIterator(false)
  1187  			defer it.Close()
  1188  			for it.seekToFirst(); it.Valid(); it.next() {
  1189  				vs := it.Value()
  1190  				newBuilder.Add(it.Key(), vs)
  1191  			}
  1192  			_, err = newBuilder.Finish()
  1193  			y.Check(err)
  1194  			_, err := f.Seek(0, io.SeekStart)
  1195  			y.Check(err)
  1196  		}()
  1197  	}
  1198  }
  1199  
  1200  func BenchmarkReadMerged(b *testing.B) {
  1201  	n := 5 << 20
  1202  	m := 5 // Number of tables.
  1203  	y.Assert((n % m) == 0)
  1204  	tableSize := n / m
  1205  	var tables []*Table
  1206  
  1207  	for i := 0; i < m; i++ {
  1208  		filename := fmt.Sprintf("%s%s%d.sst", os.TempDir(), string(os.PathSeparator), rand.Uint32())
  1209  		f, err := y.OpenSyncedFile(filename, true)
  1210  		y.Check(err)
  1211  		builder := NewTableBuilder(f, nil, 0, defaultBuilderOpt)
  1212  		for j := 0; j < tableSize; j++ {
  1213  			id := j*m + i // Arrays are interleaved.
  1214  			// id := i*tableSize+j (not interleaved)
  1215  			k := y.KeyWithTs([]byte(fmt.Sprintf("%016x", id)), 0)
  1216  			v := fmt.Sprintf("%d", id)
  1217  			y.Check(builder.Add(k, y.ValueStruct{Value: []byte(v), Meta: 123, UserMeta: []byte{0}}))
  1218  		}
  1219  		_, err = builder.Finish()
  1220  		y.Check(err)
  1221  		tbl, err := OpenTable(f.Name(), testCache(), testCache())
  1222  		y.Check(err)
  1223  		tables = append(tables, tbl)
  1224  		defer tbl.Delete()
  1225  	}
  1226  
  1227  	b.ResetTimer()
  1228  	// Iterate b.N times over the entire table.
  1229  	for i := 0; i < b.N; i++ {
  1230  		func() {
  1231  			var iters []y.Iterator
  1232  			for _, tbl := range tables {
  1233  				iters = append(iters, tbl.newIterator(false))
  1234  			}
  1235  			it := table.NewMergeIterator(iters, false)
  1236  			defer it.Close()
  1237  			for it.Rewind(); it.Valid(); it.Next() {
  1238  			}
  1239  		}()
  1240  	}
  1241  }
  1242  
  1243  func BenchmarkRandomRead(b *testing.B) {
  1244  	n := int(5 * 1e6)
  1245  	tbl := getTableForBenchmarks(b, n, testCache(), testCache())
  1246  
  1247  	r := rand.New(rand.NewSource(time.Now().Unix()))
  1248  
  1249  	b.ResetTimer()
  1250  	for i := 0; i < b.N; i++ {
  1251  		itr := tbl.newIterator(false)
  1252  		defer itr.Close()
  1253  		no := r.Intn(n)
  1254  		k := []byte(fmt.Sprintf("%016x", no))
  1255  		v := []byte(fmt.Sprintf("%d", no))
  1256  		itr.Seek(k)
  1257  		if !itr.Valid() {
  1258  			b.Fatal("itr should be valid")
  1259  		}
  1260  		v1 := itr.Value().Value
  1261  
  1262  		if !bytes.Equal(v, v1) {
  1263  			fmt.Println("value does not match")
  1264  			b.Fatal()
  1265  		}
  1266  	}
  1267  }
  1268  
  1269  func getTableForBenchmarks(b *testing.B, count int, blkCache, idxCache *cache.Cache) *Table {
  1270  	rand.Seed(time.Now().Unix())
  1271  	filename := fmt.Sprintf("%s%s%d.sst", os.TempDir(), string(os.PathSeparator), rand.Uint32())
  1272  	f, err := y.OpenSyncedFile(filename, false)
  1273  	builder := NewTableBuilder(f, nil, 0, defaultBuilderOpt)
  1274  	require.NoError(b, err)
  1275  	for i := 0; i < count; i++ {
  1276  		k := y.KeyWithTs([]byte(fmt.Sprintf("%016x", i)), 0)
  1277  		v := fmt.Sprintf("%d", i)
  1278  		builder.Add(k, y.ValueStruct{Value: []byte(v)})
  1279  	}
  1280  
  1281  	_, err = builder.Finish()
  1282  	require.NoError(b, err, "unable to write to file")
  1283  	tbl, err := OpenTable(f.Name(), blkCache, idxCache)
  1284  	require.NoError(b, err, "unable to open table")
  1285  	return tbl
  1286  }
  1287  
  1288  func TestMain(m *testing.M) {
  1289  	rand.Seed(time.Now().UTC().UnixNano())
  1290  	os.Exit(m.Run())
  1291  }