github.com/TeaOSLab/EdgeNode@v1.3.8/internal/caches/list_memory_test.go (about) 1 package caches_test 2 3 import ( 4 "fmt" 5 "github.com/TeaOSLab/EdgeNode/internal/caches" 6 "github.com/TeaOSLab/EdgeNode/internal/utils/testutils" 7 "github.com/cespare/xxhash/v2" 8 "github.com/iwind/TeaGo/logs" 9 "github.com/iwind/TeaGo/rands" 10 "github.com/iwind/TeaGo/types" 11 stringutil "github.com/iwind/TeaGo/utils/string" 12 "math/rand" 13 "sort" 14 "strconv" 15 "testing" 16 "time" 17 ) 18 19 func TestMemoryList_Add(t *testing.T) { 20 list := caches.NewMemoryList().(*caches.MemoryList) 21 _ = list.Init() 22 _ = list.Add("a", &caches.Item{ 23 Key: "a1", 24 ExpiresAt: time.Now().Unix() + 3600, 25 HeaderSize: 1024, 26 }) 27 _ = list.Add("b", &caches.Item{ 28 Key: "b1", 29 ExpiresAt: time.Now().Unix() + 3600, 30 HeaderSize: 1024, 31 }) 32 _ = list.Add("123456", &caches.Item{ 33 Key: "c1", 34 ExpiresAt: time.Now().Unix() + 3600, 35 HeaderSize: 1024, 36 }) 37 t.Log(list.Prefixes()) 38 logs.PrintAsJSON(list.ItemMaps(), t) 39 t.Log(list.Count()) 40 } 41 42 func TestMemoryList_Remove(t *testing.T) { 43 list := caches.NewMemoryList().(*caches.MemoryList) 44 _ = list.Init() 45 _ = list.Add("a", &caches.Item{ 46 Key: "a1", 47 ExpiresAt: time.Now().Unix() + 3600, 48 HeaderSize: 1024, 49 }) 50 _ = list.Add("b", &caches.Item{ 51 Key: "b1", 52 ExpiresAt: time.Now().Unix() + 3600, 53 HeaderSize: 1024, 54 }) 55 _ = list.Remove("b") 56 list.Print(t) 57 t.Log(list.Count()) 58 } 59 60 func TestMemoryList_Purge(t *testing.T) { 61 list := caches.NewMemoryList().(*caches.MemoryList) 62 _ = list.Init() 63 _ = list.Add("a", &caches.Item{ 64 Key: "a1", 65 ExpiresAt: time.Now().Unix() + 3600, 66 HeaderSize: 1024, 67 }) 68 _ = list.Add("b", &caches.Item{ 69 Key: "b1", 70 ExpiresAt: time.Now().Unix() + 3600, 71 HeaderSize: 1024, 72 }) 73 _ = list.Add("c", &caches.Item{ 74 Key: "c1", 75 ExpiresAt: time.Now().Unix() - 3600, 76 HeaderSize: 1024, 77 }) 78 _ = list.Add("d", &caches.Item{ 79 Key: "d1", 80 ExpiresAt: time.Now().Unix() - 2, 81 HeaderSize: 1024, 82 }) 83 _, _ = list.Purge(100, func(hash string) error { 84 t.Log("delete:", hash) 85 return nil 86 }) 87 list.Print(t) 88 89 for i := 0; i < 1000; i++ { 90 _, _ = list.Purge(100, func(hash string) error { 91 t.Log("delete:", hash) 92 return nil 93 }) 94 t.Log(list.PurgeIndex()) 95 } 96 97 t.Log(list.Count()) 98 } 99 100 func TestMemoryList_Purge_Large_List(t *testing.T) { 101 var list = caches.NewMemoryList().(*caches.MemoryList) 102 _ = list.Init() 103 104 var count = 100 105 if testutils.IsSingleTesting() { 106 count = 1_000_000 107 } 108 109 for i := 0; i < count; i++ { 110 _ = list.Add("a"+strconv.Itoa(i), &caches.Item{ 111 Key: "a" + strconv.Itoa(i), 112 ExpiresAt: time.Now().Unix() + int64(rands.Int(0, 24*3600)), 113 HeaderSize: 1024, 114 }) 115 } 116 117 if testutils.IsSingleTesting() { 118 time.Sleep(1 * time.Hour) 119 } 120 } 121 122 func TestMemoryList_Stat(t *testing.T) { 123 list := caches.NewMemoryList() 124 _ = list.Init() 125 _ = list.Add("a", &caches.Item{ 126 Key: "a1", 127 ExpiresAt: time.Now().Unix() + 3600, 128 HeaderSize: 1024, 129 }) 130 _ = list.Add("b", &caches.Item{ 131 Key: "b1", 132 ExpiresAt: time.Now().Unix() + 3600, 133 HeaderSize: 1024, 134 }) 135 _ = list.Add("c", &caches.Item{ 136 Key: "c1", 137 ExpiresAt: time.Now().Unix(), 138 HeaderSize: 1024, 139 }) 140 _ = list.Add("d", &caches.Item{ 141 Key: "d1", 142 ExpiresAt: time.Now().Unix() - 2, 143 HeaderSize: 1024, 144 }) 145 result, _ := list.Stat(func(hash string) bool { 146 // 随机测试 147 return rand.Int()%2 == 0 148 }) 149 t.Log(result) 150 } 151 152 func TestMemoryList_CleanPrefix(t *testing.T) { 153 list := caches.NewMemoryList() 154 _ = list.Init() 155 before := time.Now() 156 var count = 100 157 if testutils.IsSingleTesting() { 158 count = 1_000_000 159 } 160 for i := 0; i < count; i++ { 161 key := "https://www.teaos.cn/hello/" + strconv.Itoa(i/10000) + "/" + strconv.Itoa(i) + ".html" 162 _ = list.Add(fmt.Sprintf("%d", xxhash.Sum64String(key)), &caches.Item{ 163 Key: key, 164 ExpiresAt: time.Now().Unix() + 3600, 165 BodySize: 0, 166 HeaderSize: 0, 167 }) 168 } 169 t.Log(time.Since(before).Seconds()*1000, "ms") 170 171 before = time.Now() 172 err := list.CleanPrefix("https://www.teaos.cn/hello/10") 173 if err != nil { 174 t.Fatal(err) 175 } 176 177 logs.Println(list.Stat(func(hash string) bool { 178 return true 179 })) 180 181 t.Log(time.Since(before).Seconds()*1000, "ms") 182 } 183 184 func TestMapRandomDelete(t *testing.T) { 185 var countMap = map[int]int{} // k => count 186 187 var count = 1000 188 if testutils.IsSingleTesting() { 189 count = 1_000_000 190 } 191 192 for j := 0; j < count; j++ { 193 var m = map[int]bool{} 194 for i := 0; i < 100; i++ { 195 m[i] = true 196 } 197 198 var count = 0 199 for k := range m { 200 delete(m, k) 201 count++ 202 if count >= 10 { 203 break 204 } 205 } 206 207 for k := range m { 208 countMap[k]++ 209 } 210 } 211 212 var counts = []int{} 213 for _, count := range countMap { 214 counts = append(counts, count) 215 } 216 sort.Ints(counts) 217 t.Log("["+types.String(len(counts))+"]", counts) 218 } 219 220 func TestMemoryList_PurgeLFU(t *testing.T) { 221 var list = caches.NewMemoryList().(*caches.MemoryList) 222 223 var before = time.Now() 224 defer func() { 225 t.Log(time.Since(before).Seconds()*1000, "ms") 226 }() 227 228 _ = list.Add("1", &caches.Item{}) 229 _ = list.Add("2", &caches.Item{}) 230 _ = list.Add("3", &caches.Item{}) 231 _ = list.Add("4", &caches.Item{}) 232 _ = list.Add("5", &caches.Item{}) 233 234 //_ = list.IncreaseHit("1") 235 //_ = list.IncreaseHit("2") 236 //_ = list.IncreaseHit("3") 237 //_ = list.IncreaseHit("4") 238 //_ = list.IncreaseHit("5") 239 240 count, err := list.Count() 241 if err != nil { 242 t.Fatal(err) 243 } 244 t.Log("count items before purge:", count) 245 246 err = list.PurgeLFU(5, func(hash string) error { 247 t.Log("purge lfu:", hash) 248 return nil 249 }) 250 if err != nil { 251 t.Fatal(err) 252 } 253 t.Log("ok") 254 255 count, err = list.Count() 256 if err != nil { 257 t.Fatal(err) 258 } 259 t.Log("count items left:", count) 260 } 261 262 func TestMemoryList_CleanAll(t *testing.T) { 263 var list = caches.NewMemoryList().(*caches.MemoryList) 264 _ = list.Add("a", &caches.Item{}) 265 _ = list.CleanAll() 266 logs.PrintAsJSON(list.ItemMaps(), t) 267 t.Log(list.Count()) 268 } 269 270 func TestMemoryList_GC(t *testing.T) { 271 if !testutils.IsSingleTesting() { 272 return 273 } 274 275 list := caches.NewMemoryList().(*caches.MemoryList) 276 _ = list.Init() 277 for i := 0; i < 1_000_000; i++ { 278 key := "https://www.teaos.cn/hello" + strconv.Itoa(i/100000) + "/" + strconv.Itoa(i) + ".html" 279 _ = list.Add(fmt.Sprintf("%d", xxhash.Sum64String(key)), &caches.Item{ 280 Key: key, 281 ExpiresAt: 0, 282 BodySize: 0, 283 HeaderSize: 0, 284 }) 285 } 286 t.Log("clean...", len(list.ItemMaps())) 287 _ = list.CleanAll() 288 t.Log("cleanAll...", len(list.ItemMaps())) 289 before := time.Now() 290 //runtime.GC() 291 t.Log("gc cost:", time.Since(before).Seconds()*1000, "ms") 292 293 if testutils.IsSingleTesting() { 294 timeout := time.NewTimer(2 * time.Minute) 295 <-timeout.C 296 t.Log("2 minutes passed") 297 298 time.Sleep(30 * time.Minute) 299 } 300 } 301 302 func BenchmarkMemoryList(b *testing.B) { 303 var list = caches.NewMemoryList() 304 err := list.Init() 305 if err != nil { 306 b.Fatal(err) 307 } 308 for i := 0; i < 1_000_000; i++ { 309 _ = list.Add(stringutil.Md5(types.String(i)), &caches.Item{ 310 Key: "a1", 311 ExpiresAt: time.Now().Unix() + 3600, 312 HeaderSize: 1024, 313 }) 314 } 315 316 b.ResetTimer() 317 318 b.RunParallel(func(pb *testing.PB) { 319 for pb.Next() { 320 _, _, _ = list.Exist(types.String("a" + types.String(rands.Int(1, 10000)))) 321 _ = list.Add("a"+types.String(rands.Int(1, 100000)), &caches.Item{}) 322 _, _ = list.Purge(1000, func(hash string) error { 323 return nil 324 }) 325 } 326 }) 327 }