github.com/haalcala/mattermost-server-change-repo@v0.0.0-20210713015153-16753fbeee5f/services/cache/lru_striped_bench_test.go (about) 1 // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 // See LICENSE.txt for license information. 3 4 package cache_test 5 6 import ( 7 "fmt" 8 "runtime" 9 "sync" 10 "testing" 11 12 "github.com/cespare/xxhash/v2" 13 14 "github.com/mattermost/mattermost-server/v5/services/cache" 15 ) 16 17 const ( 18 m = 500_000 19 ) 20 21 func BenchmarkLRUStriped(b *testing.B) { 22 opts := cache.LRUOptions{ 23 Name: "", 24 Size: 128, 25 DefaultExpiry: 0, 26 InvalidateClusterEvent: "", 27 StripedBuckets: runtime.NumCPU() - 1, 28 } 29 30 cache, err := cache.NewLRUStriped(opts) 31 if err != nil { 32 panic(err) 33 } 34 // prepare keys and initial cache values and set routine 35 keys := make([]string, 0, m) 36 // bucketKeys is to demonstrate that splitted locks is working correctly 37 // by assigning one sequence of key for each bucket. 38 bucketKeys := make([][]string, opts.StripedBuckets) 39 for i := 0; i < m; i++ { 40 key := fmt.Sprintf("%d-key-%d", i, i) 41 keys = append(keys, key) 42 bucketKey := xxhash.Sum64String(key) % uint64(opts.StripedBuckets) 43 bucketKeys[bucketKey] = append(bucketKeys[bucketKey], key) 44 } 45 for i := 0; i < opts.Size; i++ { 46 cache.Set(keys[i], "preflight") 47 } 48 49 wgGet := &sync.WaitGroup{} 50 wgSet := &sync.WaitGroup{} 51 // need buffered chan because if the set routine finished before we write into the chan, 52 // we're left without any consumer, making any write to the chan waiting forever. 53 stopSet := make(chan bool, 1) 54 set := func() { 55 defer wgSet.Done() 56 for i := 0; i < m; i++ { 57 select { 58 case <-stopSet: 59 return 60 default: 61 _ = cache.Set(keys[i], "ignored") 62 } 63 } 64 } 65 66 get := func(bucket int) { 67 defer wgGet.Done() 68 var out string 69 for i := 0; i < m; i++ { 70 _ = cache.Get(bucketKeys[bucket][i%opts.Size], &out) 71 } 72 } 73 74 b.StopTimer() 75 b.ResetTimer() 76 for i := 0; i < b.N; i++ { 77 wgSet.Add(1) 78 go set() 79 for j := 0; j < opts.StripedBuckets; j++ { 80 wgGet.Add(1) 81 go get(j) 82 } 83 84 b.StartTimer() 85 wgGet.Wait() 86 b.StopTimer() 87 88 stopSet <- true 89 wgSet.Wait() 90 } 91 }