]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: add readMetrics latency benchmark
authorMichael Anthony Knyszek <mknyszek@google.com>
Wed, 5 Aug 2020 23:10:46 +0000 (23:10 +0000)
committerMichael Knyszek <mknyszek@google.com>
Mon, 26 Oct 2020 18:29:12 +0000 (18:29 +0000)
This change adds a new benchmark to the runtime tests for measuring the
latency of the new metrics implementation, based on the
ReadMemStats latency benchmark. readMetrics will have more metrics added
to it in the future, and this benchmark will serve as a way to measure
the cost of adding additional metrics.

Change-Id: Ib05e3ed4afa49a70863fc0c418eab35b72263e24
Reviewed-on: https://go-review.googlesource.com/c/go/+/247042
Run-TryBot: Michael Knyszek <mknyszek@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Trust: Michael Knyszek <mknyszek@google.com>
Reviewed-by: Emmanuel Odeke <emmanuel@orijtech.com>
Reviewed-by: Michael Pratt <mpratt@google.com>
src/runtime/gc_test.go
src/runtime/metrics_test.go

index 9edebdada68055a5de018ab8732d9ee0ea9e02ea..7870f31ae9e43c231bae26908625192d832695bb 100644 (file)
@@ -518,7 +518,7 @@ func BenchmarkReadMemStats(b *testing.B) {
        hugeSink = nil
 }
 
-func BenchmarkReadMemStatsLatency(b *testing.B) {
+func applyGCLoad(b *testing.B) func() {
        // We’ll apply load to the runtime with maxProcs-1 goroutines
        // and use one more to actually benchmark. It doesn't make sense
        // to try to run this test with only 1 P (that's what
@@ -563,6 +563,14 @@ func BenchmarkReadMemStatsLatency(b *testing.B) {
                        runtime.KeepAlive(hold)
                }()
        }
+       return func() {
+               close(done)
+               wg.Wait()
+       }
+}
+
+func BenchmarkReadMemStatsLatency(b *testing.B) {
+       stop := applyGCLoad(b)
 
        // Spend this much time measuring latencies.
        latencies := make([]time.Duration, 0, 1024)
@@ -579,12 +587,11 @@ func BenchmarkReadMemStatsLatency(b *testing.B) {
                runtime.ReadMemStats(&ms)
                latencies = append(latencies, time.Now().Sub(start))
        }
-       close(done)
-       // Make sure to stop the timer before we wait! The goroutines above
-       // are very heavy-weight and not easy to stop, so we could end up
+       // Make sure to stop the timer before we wait! The load created above
+       // is very heavy-weight and not easy to stop, so we could end up
        // confusing the benchmarking framework for small b.N.
        b.StopTimer()
-       wg.Wait()
+       stop()
 
        // Disable the default */op metrics.
        // ns/op doesn't mean anything because it's an average, but we
index f00aad07c4b3b54bf004a5f7988b7d791c643351..d925b057b0e381fa31f48e35e4129b504c4bcf07 100644 (file)
@@ -7,8 +7,10 @@ package runtime_test
 import (
        "runtime"
        "runtime/metrics"
+       "sort"
        "strings"
        "testing"
+       "time"
        "unsafe"
 )
 
@@ -112,3 +114,39 @@ func TestReadMetricsConsistency(t *testing.T) {
                t.Errorf(`"/memory/classes/total:bytes" does not match sum of /memory/classes/**: got %d, want %d`, totalVirtual.got, totalVirtual.want)
        }
 }
+
+func BenchmarkReadMetricsLatency(b *testing.B) {
+       stop := applyGCLoad(b)
+
+       // Spend this much time measuring latencies.
+       latencies := make([]time.Duration, 0, 1024)
+       _, samples := prepareAllMetricsSamples()
+
+       // Hit metrics.Read continuously and measure.
+       b.ResetTimer()
+       for i := 0; i < b.N; i++ {
+               start := time.Now()
+               metrics.Read(samples)
+               latencies = append(latencies, time.Now().Sub(start))
+       }
+       // Make sure to stop the timer before we wait! The load created above
+       // is very heavy-weight and not easy to stop, so we could end up
+       // confusing the benchmarking framework for small b.N.
+       b.StopTimer()
+       stop()
+
+       // Disable the default */op metrics.
+       // ns/op doesn't mean anything because it's an average, but we
+       // have a sleep in our b.N loop above which skews this significantly.
+       b.ReportMetric(0, "ns/op")
+       b.ReportMetric(0, "B/op")
+       b.ReportMetric(0, "allocs/op")
+
+       // Sort latencies then report percentiles.
+       sort.Slice(latencies, func(i, j int) bool {
+               return latencies[i] < latencies[j]
+       })
+       b.ReportMetric(float64(latencies[len(latencies)*50/100]), "p50-ns")
+       b.ReportMetric(float64(latencies[len(latencies)*90/100]), "p90-ns")
+       b.ReportMetric(float64(latencies[len(latencies)*99/100]), "p99-ns")
+}