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  }