github.com/GuanceCloud/cliutils@v1.1.21/cmd/diskcache/main.go (about)

     1  // Unless explicitly stated otherwise all files in this repository are licensed
     2  // under the MIT License.
     3  // This product includes software developed at Guance Cloud (https://www.guance.com/).
     4  // Copyright 2021-present Guance, Inc.
     5  
     6  //nolint:gosec
     7  package main
     8  
     9  import (
    10  	"flag"
    11  	"log"
    12  	"math/rand"
    13  	"sync"
    14  	"time"
    15  
    16  	dc "github.com/GuanceCloud/cliutils/diskcache"
    17  	"github.com/GuanceCloud/cliutils/metrics"
    18  )
    19  
    20  var (
    21  	path, http       string
    22  	capacity         int64
    23  	disableGoMetrics bool
    24  	putLatency,
    25  	getLatency,
    26  	runtime,
    27  	workers,
    28  	sampleMax,
    29  	sampleMin int
    30  
    31  	cache *dc.DiskCache
    32  	wg    sync.WaitGroup
    33  
    34  	dataBuf []byte
    35  
    36  	tick *time.Ticker
    37  )
    38  
    39  const (
    40  	GB = 1024 * 1024 * 1024
    41  )
    42  
    43  //nolint:gochecknoinits
    44  func init() {
    45  	flag.StringVar(&path, "path", "./diskcache", "cache path")
    46  	flag.Int64Var(&capacity, "cap", 32, "cache capacity(GB)")
    47  	flag.IntVar(&workers, "workers", 1, "concurrent Put/Get workers")
    48  	flag.IntVar(&sampleMax, "smax", 32768, "maximum sample size(KB)")
    49  	flag.IntVar(&sampleMin, "smin", 4, "minimal sample size(KB)")
    50  	flag.IntVar(&runtime, "runtime", 5, "run time(minute) for the test")
    51  	flag.BoolVar(&disableGoMetrics, "disable-gom", false, "disable golang metrics")
    52  	flag.IntVar(&putLatency, "put-lat", 100, "put latency(ms) randome range(from 0)")
    53  	flag.IntVar(&getLatency, "get-lat", 100, "get latency(ms) randome range(from 0)")
    54  	flag.StringVar(&http, "http", "localhost:9090", "bind HTTP to serve /metrics")
    55  }
    56  
    57  func main() {
    58  	flag.Parse()
    59  	var err error
    60  
    61  	dataBuf = make([]byte, 32*1024*1024) // 32MB data buffer
    62  	tick = time.NewTicker(time.Duration(runtime) * time.Minute)
    63  
    64  	cache, err = dc.Open(dc.WithPath(path), dc.WithCapacity(capacity*GB))
    65  	if err != nil {
    66  		log.Panic(err)
    67  	}
    68  
    69  	run()
    70  }
    71  
    72  // get random bytes from dataBuf.
    73  func getSamples() []byte {
    74  	r := rand.New(rand.NewSource(time.Now().UnixNano()))
    75  
    76  	n := (sampleMin + (r.Int() % sampleMax)) * 1024 // in KB
    77  	if n >= len(dataBuf) {
    78  		n = len(dataBuf)
    79  	}
    80  
    81  	start := r.Int() % len(dataBuf)
    82  
    83  	if start+n > len(dataBuf) {
    84  		return dataBuf[len(dataBuf)-n:] // return last n bytes
    85  	} else {
    86  		return dataBuf[start : start+n]
    87  	}
    88  }
    89  
    90  func put(n int) {
    91  	wg.Add(workers)
    92  	for i := 0; i < workers; i++ {
    93  		go func() {
    94  			defer wg.Done()
    95  			for {
    96  				select {
    97  				case <-tick.C:
    98  					return
    99  				default:
   100  					r := rand.New(rand.NewSource(time.Now().UnixNano()))
   101  					time.Sleep(time.Millisecond * time.Duration(r.Int()%getLatency))
   102  					cache.Put(getSamples()) //nolint:errcheck
   103  				}
   104  			}
   105  		}()
   106  	}
   107  }
   108  
   109  func get(n int) {
   110  	wg.Add(workers)
   111  	for i := 0; i < workers; i++ {
   112  		go func() {
   113  			defer wg.Done()
   114  
   115  			for {
   116  				select {
   117  				case <-tick.C:
   118  					for {
   119  						// read them all without weekend.
   120  						if err := cache.Get(func(_ []byte) error {
   121  							r := rand.New(rand.NewSource(time.Now().UnixNano()))
   122  							time.Sleep(time.Millisecond * time.Duration(r.Int()%getLatency))
   123  							return nil
   124  						}); err != nil {
   125  							return
   126  						}
   127  					}
   128  				default:
   129  					cache.Get(func(_ []byte) error { // nolint: errcheck
   130  						r := rand.New(rand.NewSource(time.Now().UnixNano()))
   131  						time.Sleep(time.Millisecond * time.Duration(r.Int()%getLatency))
   132  						return nil
   133  					})
   134  				}
   135  			}
   136  		}()
   137  	}
   138  }
   139  
   140  func run() {
   141  	put(workers)
   142  	get(workers)
   143  
   144  	ms := metrics.NewMetricServer()
   145  	ms.DisableGoMetrics = disableGoMetrics
   146  	ms.Listen = http
   147  
   148  	go func() {
   149  		if err := ms.Start(); err != nil {
   150  			log.Panic(err)
   151  		}
   152  	}()
   153  
   154  	wg.Wait()
   155  }