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  }