diff --git a/go.mod b/go.mod index 728ccb10c8..c0fd80cd50 100644 --- a/go.mod +++ b/go.mod @@ -6,6 +6,7 @@ require ( github.com/abbot/go-http-auth v0.4.0 github.com/andybalholm/brotli v1.1.0 github.com/aryszka/jobqueue v0.0.3 + github.com/benburkert/pbench v0.0.0-20160623210926-4ec5821845ef github.com/cenkalti/backoff v2.2.1+incompatible github.com/cespare/xxhash/v2 v2.3.0 github.com/cjoudrey/gluahttp v0.0.0-20201111170219-25003d9adfa9 @@ -94,6 +95,7 @@ require ( github.com/envoyproxy/protoc-gen-validate v1.0.4 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect + github.com/gavv/monotime v0.0.0-20190418164738-30dba4353424 // indirect github.com/go-ini/ini v1.67.0 // indirect github.com/go-jose/go-jose/v4 v4.0.2 // indirect github.com/go-logr/logr v1.4.2 // indirect diff --git a/go.sum b/go.sum index 5836018b9f..2b96962ef7 100644 --- a/go.sum +++ b/go.sum @@ -42,6 +42,8 @@ github.com/armon/go-metrics v0.4.1 h1:hR91U9KYmb6bLBYLQjyM+3j+rcd/UhE+G78SFnF8gJ github.com/armon/go-metrics v0.4.1/go.mod h1:E6amYzXo6aW1tqzoZGT755KkbgrJsSdpwZ+3JqfkOG4= github.com/aryszka/jobqueue v0.0.3 h1:O5YbgzQCjRomudwnDTY5BrHUNJhvPHQHq7GfGpE+ybs= github.com/aryszka/jobqueue v0.0.3/go.mod h1:SdxqI6HZ4E1Lss94tey5OfjcAu3bdCDWS1AQzzIN4m4= +github.com/benburkert/pbench v0.0.0-20160623210926-4ec5821845ef h1:+7ZJvJGiV4hUBdjhEDhfGdjBCOmhVi0YQ5n+6g/ei+k= +github.com/benburkert/pbench v0.0.0-20160623210926-4ec5821845ef/go.mod h1:hrhDSsc41bBqGejYXbvMh6qexfcC2vXjodP5gufwWyI= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= @@ -151,6 +153,8 @@ github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMo github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= +github.com/gavv/monotime v0.0.0-20190418164738-30dba4353424 h1:Vh7rylVZRZCj6W41lRlP17xPk4Nq260H4Xo/DDYmEZk= +github.com/gavv/monotime v0.0.0-20190418164738-30dba4353424/go.mod h1:vmp8DIyckQMXOPl0AQVHt+7n5h7Gb7hS6CUydiV8QeA= github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= diff --git a/routing/endpointregistry_test.go b/routing/endpointregistry_test.go index d6627a1e39..2af21b562c 100644 --- a/routing/endpointregistry_test.go +++ b/routing/endpointregistry_test.go @@ -2,11 +2,13 @@ package routing_test import ( "fmt" + "os" "runtime/metrics" "sync" "testing" "time" + "github.com/benburkert/pbench" "github.com/stretchr/testify/assert" "github.com/zalando/skipper/eskip" "github.com/zalando/skipper/routing" @@ -290,7 +292,11 @@ func benchmarkIncInflightRequests(b *testing.B, name string, goroutines int) { const key string = "some key" const mapSize int = 10000 - b.Run(name, func(b *testing.B) { + percentileBench := pbench.New(b) + percentileBench.ReportPercentile(0.95) + percentileBench.ReportPercentile(0.99) + + percentileBench.Run(name, func(b *pbench.B) { r := routing.NewEndpointRegistry(routing.RegistryOptions{}) now := time.Now() @@ -300,23 +306,23 @@ func benchmarkIncInflightRequests(b *testing.B, name string, goroutines int) { r.GetMetrics(key).IncInflightRequest() r.GetMetrics(key).SetDetected(now) - wg := sync.WaitGroup{} b.ResetTimer() b.ReportAllocs() - for i := 0; i < goroutines; i++ { - wg.Add(1) - go func() { - defer wg.Done() - metrics := r.GetMetrics(key) - for n := 0; n < b.N/goroutines; n++ { - metrics.IncInflightRequest() - } - }() - } - wg.Wait() - printTotalMutexWaitTime(b) + oldGOMAXPROCS := os.Getenv("GOMAXPROCS") + defer os.Setenv("GOMAXPROCS", oldGOMAXPROCS) + os.Setenv("GOMAXPROCS", "1") + b.SetParallelism(goroutines) + + b.RunParallel(func(pb *pbench.PB) { + metrics := r.GetMetrics(key) + for pb.Next() { + metrics.IncInflightRequest() + } + }) }) + + printTotalMutexWaitTime(b) } func BenchmarkIncInflightRequests(b *testing.B) { @@ -330,7 +336,11 @@ func benchmarkGetInflightRequests(b *testing.B, name string, goroutines int) { const key string = "some key" const mapSize int = 10000 - b.Run(name, func(b *testing.B) { + percentileBench := pbench.New(b) + percentileBench.ReportPercentile(0.95) + percentileBench.ReportPercentile(0.99) + + percentileBench.Run(name, func(b *pbench.B) { r := routing.NewEndpointRegistry(routing.RegistryOptions{}) now := time.Now() for i := 1; i < mapSize; i++ { @@ -340,24 +350,24 @@ func benchmarkGetInflightRequests(b *testing.B, name string, goroutines int) { r.GetMetrics(key).SetDetected(now) var dummy int64 - wg := sync.WaitGroup{} b.ResetTimer() b.ReportAllocs() - for i := 0; i < goroutines; i++ { - wg.Add(1) - go func() { - defer wg.Done() - metrics := r.GetMetrics(key) - for n := 0; n < b.N/goroutines; n++ { - dummy = metrics.InflightRequests() - } - }() - } - dummy++ - wg.Wait() - printTotalMutexWaitTime(b) + oldGOMAXPROCS := os.Getenv("GOMAXPROCS") + defer os.Setenv("GOMAXPROCS", oldGOMAXPROCS) + os.Setenv("GOMAXPROCS", "1") + b.SetParallelism(goroutines) + + b.RunParallel(func(pb *pbench.PB) { + metrics := r.GetMetrics(key) + for pb.Next() { + dummy = metrics.InflightRequests() + } + }) + dummy++ }) + + printTotalMutexWaitTime(b) } func BenchmarkGetInflightRequests(b *testing.B) { @@ -371,7 +381,11 @@ func benchmarkGetDetectedTime(b *testing.B, name string, goroutines int) { const key string = "some key" const mapSize int = 10000 - b.Run(name, func(b *testing.B) { + percentileBench := pbench.New(b) + percentileBench.ReportPercentile(0.95) + percentileBench.ReportPercentile(0.99) + + percentileBench.Run(name, func(b *pbench.B) { r := routing.NewEndpointRegistry(routing.RegistryOptions{}) now := time.Now() for i := 1; i < mapSize; i++ { @@ -384,21 +398,24 @@ func benchmarkGetDetectedTime(b *testing.B, name string, goroutines int) { wg := sync.WaitGroup{} b.ResetTimer() b.ReportAllocs() - for i := 0; i < goroutines; i++ { - wg.Add(1) - go func() { - defer wg.Done() - metrics := r.GetMetrics(key) - for n := 0; n < b.N/goroutines; n++ { - dummy = metrics.DetectedTime() - } - }() - } + + oldGOMAXPROCS := os.Getenv("GOMAXPROCS") + defer os.Setenv("GOMAXPROCS", oldGOMAXPROCS) + os.Setenv("GOMAXPROCS", "1") + b.SetParallelism(goroutines) + + b.RunParallel(func(pb *pbench.PB) { + metrics := r.GetMetrics(key) + for pb.Next() { + dummy = metrics.DetectedTime() + } + }) + dummy = dummy.Add(time.Second) wg.Wait() - - printTotalMutexWaitTime(b) }) + + printTotalMutexWaitTime(b) } func BenchmarkGetDetectedTime(b *testing.B) {