github.com/zuoyebang/bitalosdb@v1.1.1-0.20240516111551-79a8c4d8ce20/internal/cache/lfucache/lfucache_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  	"fmt"
    20  	"runtime"
    21  	"testing"
    22  	"time"
    23  
    24  	"github.com/zuoyebang/bitalosdb/internal/base"
    25  	"github.com/zuoyebang/bitalosdb/internal/cache/lrucache"
    26  	"github.com/zuoyebang/bitalosdb/internal/hash"
    27  	"github.com/zuoyebang/bitalosdb/internal/options"
    28  )
    29  
    30  func testNewCache() *LfuCache {
    31  	opts := &options.CacheOptions{
    32  		Size:   1 << 20,
    33  		Shards: 64,
    34  	}
    35  	mc := NewLfuCache(opts)
    36  	return mc
    37  }
    38  
    39  func TestFreq(t *testing.T) {
    40  	opts := &options.CacheOptions{
    41  		Size:   1 << 20,
    42  		Shards: 2,
    43  	}
    44  	mc := NewLfuCache(opts)
    45  
    46  	value := []byte("mcache_valuemcache_valuemcache_valuemcache_valuemcache_valuemcache_valuemcache_valuemcache_valuemcache_valuemcache_valuemcache_valuemcache_valuemcache_valuemcache_valuemcache_valuemcache_valuemcache_valuemcache_valuemcache_valuemcache_value")
    47  
    48  	key := []byte("mcache")
    49  	khash := mc.GetKeyHash(key)
    50  	for i := 0; i < 500; i++ {
    51  		mc.Set(key, value, khash)
    52  		mc.Get(key, khash)
    53  	}
    54  
    55  	time.Sleep(5 * time.Second)
    56  
    57  	fmt.Printf("----------------------------------------compact----------------------------------------\n")
    58  
    59  	for i := 0; i < 500; i++ {
    60  		k := []byte(fmt.Sprintf("xxx_%d", i))
    61  		mc.Set(k, value, mc.GetKeyHash(k))
    62  	}
    63  
    64  	time.Sleep(10 * time.Second)
    65  
    66  	mc.Get(key, khash)
    67  }
    68  
    69  func TestLfucache_Shards(t *testing.T) {
    70  	for i := -1; i < 12; i++ {
    71  		opts := &options.CacheOptions{
    72  			Size:   10 << 20,
    73  			Shards: 2,
    74  			Logger: base.DefaultLogger,
    75  		}
    76  		mc := NewLfuCache(opts)
    77  		fmt.Println(i, mc.shardNum)
    78  		mc.Close()
    79  	}
    80  }
    81  
    82  func Test_GetIter_VS_GET(t *testing.T) {
    83  	opts := &options.CacheOptions{
    84  		Size:   512 << 20,
    85  		Shards: 2,
    86  		Logger: base.DefaultLogger,
    87  	}
    88  	lc := NewLfuCache(opts)
    89  
    90  	startNum := 0
    91  	totalNum := 1 << 20
    92  	totalNum_total := totalNum
    93  
    94  	khashs := make([]uint32, totalNum_total+1, totalNum_total+1)
    95  	value := []byte("v")
    96  
    97  	bt := time.Now()
    98  	for i := startNum; i <= totalNum_total; i++ {
    99  		key := []byte(fmt.Sprintf("lfucache_key_%d", i))
   100  		khash := hash.Crc32(key)
   101  		khashs[i] = khash
   102  		if i <= totalNum {
   103  			lc.bucketByHash(khash).set(key, value)
   104  		}
   105  	}
   106  	et := time.Since(bt)
   107  	fmt.Printf("build lfucache time cost = %v\n", et)
   108  
   109  	printMemStats()
   110  
   111  	bt = time.Now()
   112  	for i := startNum; i <= totalNum_total; i++ {
   113  		key := []byte(fmt.Sprintf("lfucache_key_%d", i))
   114  		khash := khashs[i]
   115  		val, closer, found := lc.bucketByHash(khash).getIter(key)
   116  		if found && bytes.Equal(val, value) {
   117  			closer()
   118  		} else if i <= totalNum {
   119  			fmt.Printf("lfucache get by iter fail, key=%s, val=%s\n", key, val)
   120  		}
   121  	}
   122  	et = time.Since(bt)
   123  	fmt.Printf("get by iter lfucache time cost = %v\n", et)
   124  
   125  	bt = time.Now()
   126  	for i := startNum; i <= totalNum_total; i++ {
   127  		key := []byte(fmt.Sprintf("lfucache_key_%d", i))
   128  		khash := khashs[i]
   129  		val, closer, found := lc.bucketByHash(khash).get(key)
   130  		if found && bytes.Equal(val, value) {
   131  			closer()
   132  		} else if i <= totalNum {
   133  			fmt.Printf("lfucache get fail, key=%s, val=%s\n", key, val)
   134  		}
   135  	}
   136  	et = time.Since(bt)
   137  	fmt.Printf("get lfucache time cost = %v\n", et)
   138  
   139  	bt = time.Now()
   140  	for i := startNum; i <= totalNum_total; i++ {
   141  		key := []byte(fmt.Sprintf("lfucache_key_%d", i))
   142  		khash := khashs[i]
   143  		found := lc.bucketByHash(khash).exist(key)
   144  		if !found && i <= totalNum {
   145  			fmt.Printf("lfucache exist fail, key=%s\n", key)
   146  		}
   147  	}
   148  	et = time.Since(bt)
   149  	fmt.Printf("exist lfucache time cost = %v\n", et)
   150  }
   151  
   152  func Test_LFU_VS_LRU(t *testing.T) {
   153  	startNum := 0
   154  	totalNum := 1 << 20
   155  	totalNum_total := totalNum
   156  
   157  	opts := &options.CacheOptions{
   158  		Size:     512 << 20,
   159  		Shards:   64,
   160  		HashSize: totalNum,
   161  		Logger:   base.DefaultLogger,
   162  	}
   163  	lfu := NewLfuCache(opts)
   164  	lru := lrucache.New(opts)
   165  
   166  	value := []byte("v")
   167  
   168  	bt := time.Now()
   169  	for i := startNum; i <= totalNum_total; i++ {
   170  		key := []byte(fmt.Sprintf("lfucache_key_%d", i))
   171  		khash := hash.Crc32(key)
   172  		if i <= totalNum {
   173  			lfu.bucketByHash(khash).set(key, value)
   174  		}
   175  	}
   176  	et := time.Since(bt)
   177  	fmt.Printf("build lfucache time cost = %v\n", et)
   178  
   179  	printMemStats()
   180  
   181  	bt = time.Now()
   182  	for i := startNum; i <= totalNum_total; i++ {
   183  		key := []byte(fmt.Sprintf("lfucache_key_%d", i))
   184  		if i <= totalNum {
   185  			lru.Set(key, value, lru.GetKeyHash(key))
   186  		}
   187  	}
   188  	et = time.Since(bt)
   189  	fmt.Printf("build lrucache time cost = %v\n", et)
   190  
   191  	printMemStats()
   192  
   193  	bt = time.Now()
   194  	for i := startNum; i <= totalNum_total; i++ {
   195  		key := []byte(fmt.Sprintf("lfucache_key_%d", i))
   196  		khash := hash.Crc32(key)
   197  		val, closer, found := lfu.bucketByHash(khash).get(key)
   198  		if found && bytes.Equal(val, value) {
   199  			closer()
   200  		} else if i <= totalNum {
   201  			fmt.Printf("lfucache get fail, key=%s, val=%s\n", key, val)
   202  		}
   203  	}
   204  	et = time.Since(bt)
   205  	fmt.Printf("get lfucache time cost = %v\n", et)
   206  
   207  	bt = time.Now()
   208  	for i := startNum; i <= totalNum_total; i++ {
   209  		key := []byte(fmt.Sprintf("lfucache_key_%d", i))
   210  		val, vcloser, vexist := lru.Get(key, lru.GetKeyHash(key))
   211  		if vexist && bytes.Equal(val, value) {
   212  			vcloser()
   213  		} else if i <= totalNum {
   214  			fmt.Printf("lrucache get fail, key=%s\n", key)
   215  		}
   216  	}
   217  	et = time.Since(bt)
   218  	fmt.Printf("get lrucache time cost = %v\n", et)
   219  }
   220  
   221  const MB = 1024 * 1024
   222  
   223  func printMemStats() {
   224  	var m runtime.MemStats
   225  	runtime.ReadMemStats(&m)
   226  	fmt.Printf("Map MEM: Alloc=%vMB; TotalAlloc=%vMB; SYS=%vMB; Mallocs=%v; Frees=%v; HeapAlloc=%vMB; HeapSys=%vMB; HeapIdle=%vMB; HeapReleased=%vMB; GCSys=%vMB; NextGC=%vMB; NumGC=%v; NumForcedGC=%v\n",
   227  		m.Alloc/MB, m.TotalAlloc/MB, m.Sys/MB, m.Mallocs, m.Frees, m.HeapAlloc/MB, m.HeapSys/MB, m.HeapIdle/MB, m.HeapReleased/MB,
   228  		m.GCSys/MB, m.NextGC/MB, m.NumGC, m.NumForcedGC)
   229  }