github.com/zuoyebang/bitalosdb@v1.1.1-0.20240516111551-79a8c4d8ce20/internal/cache/lfucache/array_table_test.go (about)

     1  // Copyright 2021 The Bitalosdb author(hustxrb@163.com) and other contributors.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package lfucache
    16  
    17  import (
    18  	"bytes"
    19  	"encoding/binary"
    20  	"fmt"
    21  	"sort"
    22  	"testing"
    23  	"time"
    24  
    25  	"github.com/stretchr/testify/require"
    26  )
    27  
    28  func TestArrayTable_Set(t *testing.T) {
    29  	num := 100
    30  	size := 52 * num
    31  	at := newArrayTable(1, size)
    32  	for i := 0; i < num; i++ {
    33  		key := []byte(fmt.Sprintf("cacheTestAtKey_%d", i))
    34  		value := []byte(fmt.Sprintf("cacheTestAtValue_%d", i))
    35  		if err := at.add(key, value); err != nil {
    36  			t.Fatalf("add err key:%s err:%v", string(key), err)
    37  		}
    38  	}
    39  
    40  	require.Equal(t, num, at.count())
    41  
    42  	for i := 0; i < num; i++ {
    43  		expKey := []byte(fmt.Sprintf("cacheTestAtKey_%d", i))
    44  		expValue := []byte(fmt.Sprintf("cacheTestAtValue_%d", i))
    45  		key, vaule := at.getKV(i)
    46  		require.Equal(t, expKey, key)
    47  		require.Equal(t, expValue, vaule)
    48  	}
    49  }
    50  
    51  func TestArrayTable_VS_MAP(t *testing.T) {
    52  	var buf [4]byte
    53  	num := uint32(1 << 20)
    54  	size := arrayTableEntrySize(4, 4) * int(num)
    55  	at := newArrayTable(1, size)
    56  
    57  	bt := time.Now()
    58  	i := uint32(0)
    59  	for ; i < num; i++ {
    60  		binary.BigEndian.PutUint32(buf[:], i)
    61  		if err := at.add(buf[:], buf[:]); err != nil {
    62  			t.Fatalf("add err key:%s err:%v", buf, err)
    63  		}
    64  	}
    65  	et := time.Since(bt)
    66  	fmt.Printf("arrtable add(include crc32, if annotate crc32, more faster then hashmap) time cost = %v\n", et)
    67  
    68  	bt = time.Now()
    69  	i = uint32(0)
    70  	for ; i < num; i++ {
    71  		binary.BigEndian.PutUint32(buf[:], i)
    72  		val, _, _ := at.get(buf[:])
    73  		if !bytes.Equal(buf[:], val[:]) {
    74  			t.Fatalf("arrtable get err key:%s\n", buf)
    75  		}
    76  	}
    77  	et = time.Since(bt)
    78  	fmt.Printf("arrtable get time cost = %v\n", et)
    79  
    80  	bt = time.Now()
    81  	i = uint32(0)
    82  	for ; i < num; i++ {
    83  		binary.BigEndian.PutUint32(buf[:], i)
    84  		iter := at.newIter(nil)
    85  		_, iterValue := iter.SeekGE(buf[:])
    86  		if !bytes.Equal(buf[:], iterValue[:]) {
    87  			t.Fatalf("arrtable use-iter-ßget err key:%s\n", buf)
    88  		}
    89  		iter.Close()
    90  	}
    91  	et = time.Since(bt)
    92  	fmt.Printf("arrtable use-iter-get time cost = %v\n", et)
    93  
    94  	hashmap := make(map[uint32]uint32, 1<<10)
    95  	bt = time.Now()
    96  	i = uint32(0)
    97  	for ; i < num; i++ {
    98  		binary.BigEndian.PutUint32(buf[:], i)
    99  		hashmap[i] = i
   100  	}
   101  	et = time.Since(bt)
   102  	fmt.Printf("hashmap add time cost = %v\n", et)
   103  
   104  	bt = time.Now()
   105  	i = uint32(0)
   106  	for ; i < num; i++ {
   107  		binary.BigEndian.PutUint32(buf[:], i)
   108  		if _, ok := hashmap[i]; !ok {
   109  			t.Fatalf("hashmap get err key:%s\n", buf)
   110  		}
   111  	}
   112  	et = time.Since(bt)
   113  	fmt.Printf("hashmap get time cost = %v\n", et)
   114  }
   115  
   116  type keySlice [][]byte
   117  
   118  func (x keySlice) Len() int           { return len(x) }
   119  func (x keySlice) Less(i, j int) bool { return bytes.Compare(x[i], x[j]) == -1 }
   120  func (x keySlice) Swap(i, j int)      { x[i], x[j] = x[j], x[i] }
   121  
   122  func TestArrayTable_Iter(t *testing.T) {
   123  	num := 100000
   124  	size := 52 * num
   125  	at := newArrayTable(1, size)
   126  	keys := make(keySlice, num, num)
   127  	for i := 0; i < num; i++ {
   128  		keys[i] = []byte(fmt.Sprintf("cacheTestAtKey_%d", i))
   129  	}
   130  
   131  	sort.Sort(keys)
   132  	for i := 0; i < num; i++ {
   133  		key := keys[i]
   134  		if err := at.add(key, key); err != nil {
   135  			t.Fatalf("add err key:%s err:%v", string(key), err)
   136  		}
   137  	}
   138  
   139  	var bytesFlushed *uint64
   140  	iter := at.newFlushIter(nil, bytesFlushed)
   141  	key, vaule := iter.First()
   142  	for i := 0; i < num; i++ {
   143  		expKey := keys[i]
   144  		require.Equal(t, expKey, key.UserKey)
   145  		require.Equal(t, expKey, vaule)
   146  		key, vaule = iter.Next()
   147  	}
   148  	require.NoError(t, iter.Close())
   149  
   150  	seekExist := func(skey []byte) {
   151  		ik, v := at.seek(skey)
   152  		require.Equal(t, skey, ik.UserKey)
   153  		require.Equal(t, skey, v)
   154  	}
   155  	seekNotExist := func(skey []byte) {
   156  		ik, _ := at.seek(skey)
   157  		require.Equal(t, (*internalKey)(nil), ik)
   158  	}
   159  
   160  	for _, v := range []int{7, 71, 711} {
   161  		seekExist([]byte(fmt.Sprintf("cacheTestAtKey_%d", v)))
   162  	}
   163  	for _, v := range []int{100007, 100071, 100711} {
   164  		seekNotExist([]byte(fmt.Sprintf("cacheTestAtKey_%d", v)))
   165  	}
   166  }