github.com/jxskiss/gopkg@v0.17.3/lru/sharded_test.go (about) 1 package lru 2 3 import ( 4 "math/rand" 5 "runtime" 6 "testing" 7 "time" 8 ) 9 10 func createFilledShardedCache(ttl time.Duration) *ShardedCache { 11 c := NewShardedCache(8, 500) 12 for i := 0; i < 1000; i++ { 13 key := int64(rand.Intn(5000)) 14 c.Set(key, key, ttl) 15 } 16 return c 17 } 18 19 func TestShardedBasicEviction(t *testing.T) { 20 t.Parallel() 21 c := NewShardedCache(4, 3) 22 if _, ok, _ := c.Get("a"); ok { 23 t.Error("") 24 } 25 26 c.Set("b", "vb", 2*time.Second) 27 c.Set("a", "va", time.Second) 28 c.Set("c", "vc", 3*time.Second) 29 30 if v, _, _ := c.Get("a"); v != "va" { 31 t.Error("va") 32 } 33 if v, _, _ := c.Get("b"); v != "vb" { 34 t.Error("vb") 35 } 36 if v, _, _ := c.Get("c"); v != "vc" { 37 t.Error("vc") 38 } 39 40 c.MSet(map[string]string{"h": "vh", "i": "vi"}, time.Second) 41 if v, _, _ := c.Get("h"); v != "vh" { 42 t.Error("vh") 43 } 44 if v, _, _ := c.Get("i"); v != "vi" { 45 t.Error("vi") 46 } 47 48 m := c.MGetString("h", "i") 49 if m["h"] != "vh" { 50 t.Error("expecting MSetString and MGetString to work") 51 } 52 if m["i"] != "vi" { 53 t.Error("expecting MSetString and MGetString to work") 54 } 55 } 56 57 func TestShardedConcurrentGet(t *testing.T) { 58 t.Parallel() 59 c := createFilledShardedCache(time.Second) 60 s := createRandInts(50000) 61 62 done := make(chan bool) 63 worker := func() { 64 for i := 0; i < 5000; i++ { 65 key := s[i] 66 v, exists, _ := c.Get(key) 67 if exists && v.(int64) != key { 68 t.Errorf("value not match: want= %v, got= %v", key, v) 69 } 70 } 71 done <- true 72 } 73 workers := 4 74 for i := 0; i < workers; i++ { 75 go worker() 76 } 77 for i := 0; i < workers; i++ { 78 _ = <-done 79 } 80 } 81 82 func TestShardedConcurrentSet(t *testing.T) { 83 t.Parallel() 84 c := createFilledShardedCache(time.Second) 85 s := createRandInts(5000) 86 87 done := make(chan bool) 88 worker := func() { 89 ttl := 4 * time.Second 90 for i := 0; i < 5000; i++ { 91 key := s[i] 92 c.Set(key, key, ttl) 93 } 94 done <- true 95 } 96 workers := 4 97 for i := 0; i < workers; i++ { 98 go worker() 99 } 100 for i := 0; i < workers; i++ { 101 _ = <-done 102 } 103 } 104 105 func TestShardedConcurrentGetSet(t *testing.T) { 106 t.Parallel() 107 c := createFilledShardedCache(time.Second) 108 s := createRandInts(5000) 109 110 done := make(chan bool) 111 getWorker := func() { 112 for i := 0; i < 5000; i++ { 113 key := s[i] 114 v, exists, _ := c.Get(key) 115 if exists && v.(int64) != key { 116 t.Errorf("value not match: want= %v, got= %v", key, v) 117 } 118 } 119 done <- true 120 } 121 setWorker := func() { 122 ttl := 4 * time.Second 123 for i := 0; i < 5000; i++ { 124 key := s[i] 125 c.Set(key, key, ttl) 126 } 127 done <- true 128 } 129 workers := 4 130 for i := 0; i < workers; i++ { 131 go getWorker() 132 go setWorker() 133 } 134 for i := 0; i < workers*2; i++ { 135 _ = <-done 136 } 137 } 138 139 func BenchmarkShardedConcurrentGetLRUCache(bb *testing.B) { 140 c := createFilledShardedCache(time.Second) 141 s := createRandInts(5000) 142 143 bb.ReportAllocs() 144 bb.ResetTimer() 145 cpu := runtime.GOMAXPROCS(0) 146 ch := make(chan bool) 147 worker := func() { 148 for i := 0; i < bb.N/cpu; i++ { 149 c.Get(s[i%5000]) 150 } 151 ch <- true 152 } 153 for i := 0; i < cpu; i++ { 154 go worker() 155 } 156 for i := 0; i < cpu; i++ { 157 _ = <-ch 158 } 159 } 160 161 func BenchmarkShardedConcurrentSetLRUCache(bb *testing.B) { 162 c := createFilledShardedCache(time.Second) 163 s := createRandInts(5000) 164 165 bb.ReportAllocs() 166 bb.ResetTimer() 167 cpu := runtime.GOMAXPROCS(0) 168 ch := make(chan bool) 169 worker := func() { 170 ttl := 4 * time.Second 171 for i := 0; i < bb.N/cpu; i++ { 172 key := s[i%5000] 173 c.Set(key, key, ttl) 174 } 175 ch <- true 176 } 177 for i := 0; i < cpu; i++ { 178 go worker() 179 } 180 for i := 0; i < cpu; i++ { 181 _ = <-ch 182 } 183 } 184 185 // No expiry 186 func BenchmarkShardedConcurrentSetNXLRUCache(bb *testing.B) { 187 c := createFilledShardedCache(time.Second) 188 s := createRandInts(5000) 189 190 bb.ReportAllocs() 191 bb.ResetTimer() 192 cpu := runtime.GOMAXPROCS(0) 193 ch := make(chan bool) 194 worker := func() { 195 for i := 0; i < bb.N/cpu; i++ { 196 key := s[i%5000] 197 c.Set(key, key, 0) 198 } 199 ch <- true 200 } 201 for i := 0; i < cpu; i++ { 202 go worker() 203 } 204 for i := 0; i < cpu; i++ { 205 _ = <-ch 206 } 207 }