github.com/xgzlucario/GigaCache@v0.0.0-20240508025442-54204e9c8a6b/example/main.go (about)

     1  package main
     2  
     3  import (
     4  	"fmt"
     5  	"runtime"
     6  	"slices"
     7  	"strconv"
     8  	"time"
     9  
    10  	"net/http"
    11  	_ "net/http/pprof"
    12  
    13  	cache "github.com/xgzlucario/GigaCache"
    14  )
    15  
    16  type Quantile struct {
    17  	f []float64
    18  }
    19  
    20  func NewQuantile(size int) *Quantile {
    21  	return &Quantile{f: make([]float64, 0, size)}
    22  }
    23  
    24  func (q *Quantile) Add(v float64) {
    25  	q.f = append(q.f, v)
    26  }
    27  
    28  func (q *Quantile) quantile(p float64) float64 {
    29  	r := q.f[int(float64(len(q.f))*p)]
    30  	return r
    31  }
    32  
    33  func (q *Quantile) Print() {
    34  	slices.Sort(q.f)
    35  	fmt.Printf("90th: %.0f ns\n", q.quantile(0.9))
    36  	fmt.Printf("99th: %.0f ns\n", q.quantile(0.99))
    37  	fmt.Printf("999th: %.0f ns\n", q.quantile(0.999))
    38  }
    39  
    40  const N = 100 * 10000
    41  
    42  func main() {
    43  	go func() {
    44  		_ = http.ListenAndServe("localhost:6060", nil)
    45  	}()
    46  
    47  	options := cache.DefaultOptions
    48  
    49  	for _, arg := range []int{3} {
    50  		options.EvictInterval = arg
    51  		fmt.Println("=====Options=====")
    52  		fmt.Printf("%+v\n", options)
    53  		benchmark(options)
    54  		runtime.GC()
    55  	}
    56  }
    57  
    58  func benchmark(options cache.Options) {
    59  	quant := NewQuantile(N)
    60  
    61  	var count int64
    62  	var memStats runtime.MemStats
    63  
    64  	bc := cache.New(options)
    65  
    66  	// Set test
    67  	start := time.Now()
    68  	var now time.Time
    69  	for j := 0; ; j++ {
    70  		k := strconv.FormatUint(cache.FastRand64(), 36)
    71  
    72  		if j%10 == 0 {
    73  			now = time.Now()
    74  			if now.Sub(start) > time.Minute {
    75  				break
    76  			}
    77  		}
    78  
    79  		bc.SetEx(k, []byte(k), time.Second)
    80  		count++
    81  
    82  		if j%10 == 0 {
    83  			cost := float64(time.Since(now)) / float64(time.Nanosecond)
    84  			quant.Add(cost)
    85  		}
    86  	}
    87  
    88  	// Stat
    89  	stat := bc.Stat()
    90  
    91  	fmt.Printf("[Cache] %.0fs | %dw | len: %dw | alloc: %v (unused: %.1f%%)\n",
    92  		time.Since(start).Seconds(),
    93  		count/1e4,
    94  		stat.Len/1e4,
    95  		formatSize(stat.Alloc),
    96  		stat.UnusedRate(),
    97  	)
    98  	fmt.Printf("[Evict] probe: %vw / %vw (%.1f%%) | mgr: %d\n",
    99  		stat.Evict/1e5, stat.Probe/1e5, stat.EvictRate(),
   100  		stat.Migrates)
   101  
   102  	// mem stats
   103  	runtime.ReadMemStats(&memStats)
   104  	fmt.Printf("[Mem] mem: %.0fMB | sys: %.0fMB | gc: %d | gcpause: %.0f us\n",
   105  		float64(memStats.Alloc)/1024/1024,
   106  		float64(memStats.Sys)/1024/1024,
   107  		memStats.NumGC,
   108  		float64(memStats.PauseTotalNs)/float64(memStats.NumGC)/1000)
   109  
   110  	// quant print
   111  	quant.Print()
   112  
   113  	fmt.Println("-----------------------------------------------------")
   114  }
   115  
   116  const (
   117  	KB = 1024
   118  	MB = 1024 * KB
   119  )
   120  
   121  // formatSize
   122  func formatSize[T float64 | uint64](size T) string {
   123  	switch {
   124  	case size < KB:
   125  		return fmt.Sprintf("%.0fB", float64(size))
   126  	case size < MB:
   127  		return fmt.Sprintf("%.1fKB", float64(size)/KB)
   128  	default:
   129  		return fmt.Sprintf("%.1fMB", float64(size)/MB)
   130  	}
   131  }