github.com/nyan233/littlerpc@v0.4.6-0.20230316182519-0c8d5c48abaf/core/container/map_test.go (about)

     1  package container
     2  
     3  import (
     4  	"github.com/nyan233/littlerpc/core/utils/random"
     5  	"strconv"
     6  	"testing"
     7  	"time"
     8  )
     9  
    10  type MapOnTest[Key any, Value any] interface {
    11  	LoadOk(Key) (Value, bool)
    12  	Store(Key, Value)
    13  	Delete(Key)
    14  	Len() int
    15  }
    16  
    17  func TestAllMap(t *testing.T) {
    18  	type RCUMapStore[Key comparable, Val any] interface {
    19  		StoreMulti(kvs []RCUMapElement[Key, Val])
    20  	}
    21  	printTestMap := func(printFn func(args ...any), iMap MapOnTest[string, int], errStr string) {
    22  		switch iMap.(type) {
    23  		case *MutexMap[string, int]:
    24  			printFn("MutexMap    : ", errStr)
    25  		case *RWMutexMap[string, int]:
    26  			printFn("RWMutexMap  : ", errStr)
    27  		case *SliceMap[string, int]:
    28  			printFn("SliceMap    : ", errStr)
    29  		case *SyncMap118[string, int]:
    30  			printFn("SyncMap118  : ", errStr)
    31  		case *RCUMap[string, int]:
    32  			printFn("RCUMap      : ", errStr)
    33  		}
    34  	}
    35  	type gen struct {
    36  		Key   string
    37  		Value int
    38  	}
    39  	const KeyNum int = 16384
    40  	for i := 0; i < 5; i++ {
    41  		var iMap MapOnTest[string, int]
    42  		switch i {
    43  		case 0:
    44  			iMap = &MutexMap[string, int]{}
    45  		case 1:
    46  			iMap = &RWMutexMap[string, int]{}
    47  		case 2:
    48  			iMap = NewSliceMap[string, int](8)
    49  		case 3:
    50  			iMap = &SyncMap118[string, int]{}
    51  		case 4:
    52  			iMap = NewRCUMap[string, int](128)
    53  		}
    54  		genData := make([]gen, KeyNum)
    55  		now := time.Now()
    56  		for j := 0; j < KeyNum; j++ {
    57  			genData[j] = gen{
    58  				Key:   strconv.FormatInt(int64((1<<16)+j), 16),
    59  				Value: j + 1,
    60  			}
    61  			if _, ok := iMap.(RCUMapStore[string, int]); !ok {
    62  				iMap.Store(genData[j].Key, genData[j].Value)
    63  			}
    64  		}
    65  		if inter, ok := iMap.(RCUMapStore[string, int]); ok {
    66  			kvs := make([]RCUMapElement[string, int], len(genData))
    67  			for k, v := range genData {
    68  				kvs[k] = RCUMapElement[string, int]{
    69  					Key:   v.Key,
    70  					Value: v.Value,
    71  				}
    72  			}
    73  			inter.StoreMulti(kvs)
    74  		}
    75  		// 插入一个已经存在的键, 检查长度是否计算正确
    76  		oldLen := iMap.Len()
    77  		iMap.Store(genData[KeyNum/2].Key, genData[KeyNum/2].Value)
    78  		if oldLen != iMap.Len() {
    79  			printTestMap(t.Fatal, iMap, "store after length not equal")
    80  		}
    81  		// 删除一个不存在的键, 检查长度计算是否正确
    82  		oldLen = iMap.Len()
    83  		iMap.Delete(random.GenStringOnAscii(100))
    84  		if oldLen != iMap.Len() {
    85  			printTestMap(t.Fatal, iMap, "delete after length not equal")
    86  		}
    87  		// 插入一个使用初始化数据的键, 检查长度
    88  		oldLen = iMap.Len()
    89  		iMap.Store("", 0)
    90  		if iMap.Len() != oldLen+1 {
    91  			printTestMap(t.Fatal, iMap, "store init key after length not equal")
    92  		}
    93  		iMap.Delete("")
    94  		if iMap.Len() != oldLen {
    95  			printTestMap(t.Fatal, iMap, "delete init key after length not equal")
    96  		}
    97  		for k, v := range genData {
    98  			genV, ok := iMap.LoadOk(v.Key)
    99  			if genV != k+1 {
   100  				printTestMap(t.Fatal, iMap, "genData.Value not equal")
   101  			}
   102  			if !ok {
   103  				printTestMap(t.Fatal, iMap, "genData.Key not found")
   104  			}
   105  			iMap.Delete(v.Key)
   106  		}
   107  		if iMap.Len() != 0 {
   108  			printTestMap(t.Fatal, iMap, "MaperOnTest length a not equal zero")
   109  		}
   110  		printTestMap(t.Log, iMap, "ExecTime :"+time.Since(now).String())
   111  	}
   112  }
   113  
   114  func BenchmarkGenericsMap(b *testing.B) {
   115  	mu := MutexMap[string, int]{}
   116  	rwMu := RWMutexMap[string, int]{}
   117  	writeTime := 100 * time.Nanosecond
   118  	sMap := NewSliceMap[string, int](100)
   119  	b.Run("SliceMap", func(b *testing.B) {
   120  		b.ReportAllocs()
   121  		for i := 0; i < b.N; i++ {
   122  			sMap.Store(strconv.Itoa(i%100), i)
   123  		}
   124  	})
   125  	b.Run("MutexBackgroundWrite", func(b *testing.B) {
   126  		go func() {
   127  			for {
   128  				time.Sleep(writeTime)
   129  				mu.Store("hash", 1)
   130  			}
   131  		}()
   132  		b.ReportAllocs()
   133  		for i := 0; i < b.N; i++ {
   134  			mu.Load("hash")
   135  		}
   136  	})
   137  	b.Run("RWMutexBackgroundWrite", func(b *testing.B) {
   138  		go func() {
   139  			for {
   140  				time.Sleep(writeTime)
   141  				rwMu.Store("hash", 1)
   142  			}
   143  		}()
   144  		b.ReportAllocs()
   145  		for i := 0; i < b.N; i++ {
   146  			rwMu.Load("hash")
   147  		}
   148  	})
   149  }