diff --git a/go.mod b/go.mod index f73968c..f792ffc 100644 --- a/go.mod +++ b/go.mod @@ -3,6 +3,6 @@ module git.crumpington.com/public/toolbox go 1.16 require ( - golang.org/x/sys v0.0.0-20201119102817-f84b799fce68 // indirect + golang.org/x/sys v0.0.0-20201119102817-f84b799fce68 golang.org/x/term v0.0.0-20210317153231-de623e64d2a6 ) diff --git a/kvmemcache/bench/bench/main.go b/kvmemcache/bench/bench/main.go new file mode 100644 index 0000000..323467a --- /dev/null +++ b/kvmemcache/bench/bench/main.go @@ -0,0 +1,76 @@ +package main + +import ( + "fmt" + "math/rand" + "sync" + "time" + + "git.crumpington.com/public/toolbox/kvmemcache" +) + +const ( + mean = 1000000 + stdDev = 100 + computeTime = 2 * time.Millisecond + + cacheSize = 800 + cacheTTL = time.Second + + numThreads = 8 + numCalls = 1024 * 1024 +) + +func randKey() string { + fSample := rand.NormFloat64()*stdDev + mean + sample := int64(fSample) + return fmt.Sprintf("%d", sample) +} + +func run(c *kvmemcache.Cache, wg *sync.WaitGroup) { + defer wg.Done() + for i := 0; i < numCalls; i++ { + key := randKey() + _, _ = c.Get(key) + } +} + +func main() { + c := kvmemcache.New(kvmemcache.Config{ + MaxSize: cacheSize, + TTL: cacheTTL, + Src: func(key string) (interface{}, error) { + time.Sleep(computeTime) + return key, nil + }, + }) + + wg := &sync.WaitGroup{} + wg.Add(numThreads) + + t0 := time.Now() + + for i := 0; i < numThreads; i++ { + go run(c, wg) + } + + wg.Wait() + + dt := time.Since(t0) + dtSec := float64(dt) / float64(time.Second) + stats := c.Stats() + + fmt.Printf(` +Time taken: %12.3f sec +Hits: %12d +Misses: %12d +Calls/sec: %12.3f +Speedup: %12.3f +`, + dtSec, + stats.Hits, + stats.Misses, + float64(stats.Hits+stats.Misses)/dtSec, + float64(numThreads*numCalls*computeTime)/float64(dt), + ) +} diff --git a/kvmemcache/bench/thunderingherd/main.go b/kvmemcache/bench/thunderingherd/main.go new file mode 100644 index 0000000..e6609ac --- /dev/null +++ b/kvmemcache/bench/thunderingherd/main.go @@ -0,0 +1,45 @@ +package main + +import ( + "log" + "sync" + "time" + + "git.crumpington.com/public/toolbox/kvmemcache" +) + +func main() { + N := 1024 * 2048 + trigger := make(chan bool) + + c := kvmemcache.New(kvmemcache.Config{ + MaxSize: 4, + Src: func(key string) (interface{}, error) { + <-trigger + return key, nil + }, + }) + + readyGroup := sync.WaitGroup{} + doneGroup := sync.WaitGroup{} + + readyGroup.Add(N) + doneGroup.Add(N) + + for i := 0; i < N; i++ { + go func() { + readyGroup.Done() + c.Get("a") + doneGroup.Done() + }() + } + + readyGroup.Wait() + + t0 := time.Now() + trigger <- true + doneGroup.Wait() + dt := time.Since(t0) + + log.Printf("%v", dt) +}