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 }