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