github.com/TeaOSLab/EdgeNode@v1.3.8/internal/caches/list_file_kv_test.go (about) 1 // Copyright 2024 GoEdge CDN goedge.cdn@gmail.com. All rights reserved. Official site: https://goedge.cn . 2 3 package caches_test 4 5 import ( 6 "fmt" 7 "github.com/TeaOSLab/EdgeNode/internal/caches" 8 "github.com/TeaOSLab/EdgeNode/internal/utils/testutils" 9 "github.com/iwind/TeaGo/Tea" 10 _ "github.com/iwind/TeaGo/bootstrap" 11 stringutil "github.com/iwind/TeaGo/utils/string" 12 "math/rand" 13 "strconv" 14 "sync" 15 "testing" 16 "time" 17 ) 18 19 var testingKVList *caches.KVFileList 20 21 func testOpenKVFileList(t *testing.T) *caches.KVFileList { 22 var list = caches.NewKVFileList(Tea.Root + "/data/stores/cache-stores") 23 err := list.Init() 24 if err != nil { 25 t.Fatal(err) 26 } 27 28 testingKVList = list 29 return list 30 } 31 32 func TestNewKVFileList(t *testing.T) { 33 var list = testOpenKVFileList(t) 34 err := list.Close() 35 if err != nil { 36 t.Fatal(err) 37 } 38 } 39 40 func TestKVFileList_Add(t *testing.T) { 41 var list = testOpenKVFileList(t) 42 defer func() { 43 _ = list.Close() 44 }() 45 46 err := list.Add(stringutil.Md5("123456"), &caches.Item{ 47 Type: caches.ItemTypeFile, 48 Key: "https://example.com/index.html", 49 ExpiresAt: time.Now().Unix() + 60, 50 StaleAt: 0, 51 HeaderSize: 0, 52 BodySize: 4096, 53 MetaSize: 0, 54 Host: "", 55 ServerId: 1, 56 Week: 0, 57 }) 58 if err != nil { 59 t.Fatal(err) 60 } 61 } 62 63 func TestKVFileList_Add_Many(t *testing.T) { 64 if !testutils.IsSingleTesting() { 65 return 66 } 67 68 var list = testOpenKVFileList(t) 69 defer func() { 70 _ = list.Close() 71 }() 72 73 const start = 0 74 const count = 1_000_000 75 const concurrent = 100 76 77 var before = time.Now() 78 defer func() { 79 var costSeconds = time.Since(before).Seconds() 80 t.Log("cost:", fmt.Sprintf("%.2fs", costSeconds), "qps:", fmt.Sprintf("%.2fK/s", float64(count)/1000/costSeconds)) 81 }() 82 83 var wg = &sync.WaitGroup{} 84 wg.Add(concurrent) 85 for c := 0; c < concurrent; c++ { 86 go func(c int) { 87 defer wg.Done() 88 89 var segmentStart = start + count/concurrent*c 90 for i := segmentStart; i < segmentStart+count/concurrent; i++ { 91 err := list.Add(stringutil.Md5(strconv.Itoa(i)), &caches.Item{ 92 Type: caches.ItemTypeFile, 93 Key: "https://www.example.com/index.html" + strconv.Itoa(i), 94 ExpiresAt: time.Now().Unix() + 3600, 95 StaleAt: 0, 96 HeaderSize: 0, 97 BodySize: int64(rand.Int() % 1_000_000), 98 MetaSize: 0, 99 Host: "", 100 ServerId: 1, 101 Week: 0, 102 }) 103 if err != nil { 104 t.Log(err) 105 } 106 } 107 }(c) 108 } 109 wg.Wait() 110 } 111 112 func TestKVFileList_Add_Many_Suffix(t *testing.T) { 113 if !testutils.IsSingleTesting() { 114 return 115 } 116 117 var list = testOpenKVFileList(t) 118 defer func() { 119 _ = list.Close() 120 }() 121 122 const start = 0 123 const count = 1000 124 const concurrent = 100 125 126 var before = time.Now() 127 defer func() { 128 var costSeconds = time.Since(before).Seconds() 129 t.Log("cost:", fmt.Sprintf("%.2fs", costSeconds), "qps:", fmt.Sprintf("%.2fK/s", float64(count)/1000/costSeconds)) 130 }() 131 132 var wg = &sync.WaitGroup{} 133 wg.Add(concurrent) 134 for c := 0; c < concurrent; c++ { 135 go func(c int) { 136 defer wg.Done() 137 138 var segmentStart = start + count/concurrent*c 139 for i := segmentStart; i < segmentStart+count/concurrent; i++ { 140 err := list.Add(stringutil.Md5(strconv.Itoa(i)+caches.SuffixAll), &caches.Item{ 141 Type: caches.ItemTypeFile, 142 Key: "https://www.example.com/index.html" + strconv.Itoa(i) + caches.SuffixAll + "zip", 143 ExpiresAt: time.Now().Unix() + 60, 144 StaleAt: 0, 145 HeaderSize: 0, 146 BodySize: int64(rand.Int() % 1_000_000), 147 MetaSize: 0, 148 Host: "", 149 ServerId: 1, 150 Week: 0, 151 }) 152 if err != nil { 153 t.Log(err) 154 } 155 } 156 }(c) 157 } 158 wg.Wait() 159 } 160 161 func TestKVFileList_Exist(t *testing.T) { 162 var list = testOpenKVFileList(t) 163 defer func() { 164 _ = list.Close() 165 }() 166 167 for _, hash := range []string{ 168 stringutil.Md5("123456"), 169 stringutil.Md5("654321"), 170 } { 171 b, _, err := list.Exist(hash) 172 if err != nil { 173 t.Fatal(err) 174 } 175 t.Log(hash, "=>", b) 176 } 177 } 178 179 func TestKVFileList_ExistMany(t *testing.T) { 180 var list = testOpenKVFileList(t) 181 defer func() { 182 _ = list.Close() 183 }() 184 185 var countFound int 186 var count = 10 187 if testutils.IsSingleTesting() { 188 count = 2_000_000 189 } 190 191 var before = time.Now() 192 for i := 0; i < count; i++ { 193 ok, _, err := list.Exist(stringutil.Md5(strconv.Itoa(i))) 194 if err != nil { 195 t.Fatal(err) 196 } 197 if ok { 198 countFound++ 199 } 200 } 201 var costSeconds = time.Since(before).Seconds() 202 t.Log("total:", costSeconds*1000, "ms", "found:", countFound, "qps:", fmt.Sprintf("%.2fK/s", float64(count)/costSeconds/1000), "per read:", fmt.Sprintf("%.4fms", costSeconds*1000/float64(count))) 203 } 204 205 func TestKVFileList_ExistQuick(t *testing.T) { 206 var list = testOpenKVFileList(t) 207 defer func() { 208 _ = list.Close() 209 }() 210 211 for _, hash := range []string{ 212 stringutil.Md5("123456"), 213 stringutil.Md5("654321"), 214 } { 215 b, err := list.ExistQuick(hash) 216 if err != nil { 217 t.Fatal(err) 218 } 219 t.Log(hash, "=>", b) 220 } 221 } 222 223 func TestKVFileList_Remove(t *testing.T) { 224 var list = testOpenKVFileList(t) 225 defer func() { 226 _ = list.Close() 227 }() 228 229 for _, hash := range []string{ 230 stringutil.Md5("123456"), 231 stringutil.Md5("654321"), 232 } { 233 err := list.Remove(hash) 234 if err != nil { 235 t.Fatal(err) 236 } 237 } 238 } 239 240 func TestKVFileList_RemoveMany(t *testing.T) { 241 var list = testOpenKVFileList(t) 242 defer func() { 243 _ = list.Close() 244 }() 245 246 var count = 10 247 if testutils.IsSingleTesting() { 248 count = 2_000_000 249 } 250 251 var before = time.Now() 252 for i := 0; i < count; i++ { 253 err := list.Remove(stringutil.Md5(strconv.Itoa(i))) 254 if err != nil { 255 t.Fatal(err) 256 } 257 } 258 var costSeconds = time.Since(before).Seconds() 259 t.Log("total:", costSeconds*1000, "ms", "qps:", fmt.Sprintf("%.2fK/s", float64(count)/costSeconds/1000), "per delete:", fmt.Sprintf("%.4fms", costSeconds*1000/float64(count))) 260 } 261 262 func TestKVFileList_CleanAll(t *testing.T) { 263 var list = testOpenKVFileList(t) 264 defer func() { 265 _ = list.Close() 266 }() 267 268 err := list.CleanAll() 269 if err != nil { 270 t.Fatal(err) 271 } 272 } 273 274 func TestKVFileList_Inspect(t *testing.T) { 275 if !testutils.IsSingleTesting() { 276 return 277 } 278 279 var list = testOpenKVFileList(t) 280 defer func() { 281 _ = list.Close() 282 }() 283 284 err := list.TestInspect(t) 285 if err != nil { 286 t.Fatal(err) 287 } 288 } 289 290 func TestKVFileList_Purge(t *testing.T) { 291 var list = testOpenKVFileList(t) 292 defer func() { 293 _ = list.Close() 294 }() 295 296 var before = time.Now() 297 count, err := list.Purge(4_000, func(hash string) error { 298 //t.Log("hash:", hash) 299 return nil 300 }) 301 if err != nil { 302 t.Fatal(err) 303 } 304 t.Log("cost:", fmt.Sprintf("%.2fms", time.Since(before).Seconds()*1000), "count:", count) 305 } 306 307 func TestKVFileList_PurgeLFU(t *testing.T) { 308 var list = testOpenKVFileList(t) 309 defer func() { 310 _ = list.Close() 311 }() 312 313 var before = time.Now() 314 err := list.PurgeLFU(20000, func(hash string) error { 315 t.Log("hash:", hash) 316 return nil 317 }) 318 if err != nil { 319 t.Fatal(err) 320 } 321 t.Log("cost:", fmt.Sprintf("%.2fms", time.Since(before).Seconds()*1000)) 322 } 323 324 func TestKVFileList_Count(t *testing.T) { 325 var list = testOpenKVFileList(t) 326 defer func() { 327 _ = list.Close() 328 }() 329 330 var before = time.Now() 331 count, err := list.Count() 332 if err != nil { 333 t.Fatal(err) 334 } 335 t.Log("cost:", fmt.Sprintf("%.2fms", time.Since(before).Seconds()*1000), "count:", count) 336 } 337 338 func TestKVFileList_Stat(t *testing.T) { 339 var list = testOpenKVFileList(t) 340 defer func() { 341 _ = list.Close() 342 }() 343 344 var before = time.Now() 345 stat, err := list.Stat(func(hash string) bool { 346 return true 347 }) 348 if err != nil { 349 t.Fatal(err) 350 } 351 t.Log("cost:", fmt.Sprintf("%.2fms", time.Since(before).Seconds()*1000), "stat:", fmt.Sprintf("%+v", stat)) 352 } 353 354 func TestKVFileList_CleanPrefix(t *testing.T) { 355 var list = testOpenKVFileList(t) 356 defer func() { 357 _ = list.Close() 358 }() 359 360 var before = time.Now() 361 362 defer func() { 363 var costSeconds = time.Since(before).Seconds() 364 t.Log("cost:", fmt.Sprintf("%.2fms", costSeconds*1000)) 365 }() 366 367 err := list.CleanPrefix("https://www.example.com/index.html") 368 if err != nil { 369 t.Fatal(err) 370 } 371 } 372 373 func TestKVFileList_CleanMatchPrefix(t *testing.T) { 374 var list = testOpenKVFileList(t) 375 defer func() { 376 _ = list.Close() 377 }() 378 379 var before = time.Now() 380 381 defer func() { 382 var costSeconds = time.Since(before).Seconds() 383 t.Log("cost:", fmt.Sprintf("%.2fms", costSeconds*1000)) 384 }() 385 386 err := list.CleanMatchPrefix("https://*.example.com/index.html") 387 if err != nil { 388 t.Fatal(err) 389 } 390 } 391 392 func TestKVFileList_CleanMatchKey(t *testing.T) { 393 var list = testOpenKVFileList(t) 394 defer func() { 395 _ = list.Close() 396 }() 397 398 var before = time.Now() 399 400 defer func() { 401 var costSeconds = time.Since(before).Seconds() 402 t.Log("cost:", fmt.Sprintf("%.2fms", costSeconds*1000)) 403 }() 404 405 err := list.CleanMatchKey("https://*.example.com/index.html123") 406 if err != nil { 407 t.Fatal(err) 408 } 409 } 410 411 func BenchmarkKVFileList_Exist(b *testing.B) { 412 var list = caches.NewKVFileList(Tea.Root + "/data/stores/cache-stores") 413 err := list.Init() 414 if err != nil { 415 b.Fatal(err) 416 } 417 418 defer func() { 419 _ = list.Close() 420 }() 421 422 b.ResetTimer() 423 424 b.RunParallel(func(pb *testing.PB) { 425 for pb.Next() { 426 _, _, existErr := list.Exist(stringutil.Md5(strconv.Itoa(rand.Int() % 2_000_000))) 427 if existErr != nil { 428 b.Fatal(existErr) 429 } 430 } 431 }) 432 }