aboutsummaryrefslogtreecommitdiff
path: root/src/runtime/histogram.go
diff options
context:
space:
mode:
authorMichael Anthony Knyszek <mknyszek@google.com>2021-01-06 23:05:22 +0000
committerMichael Knyszek <mknyszek@google.com>2021-01-08 03:43:44 +0000
commitae9771713383c1ee01a544cd50cfdbc22841380a (patch)
treeb6cf30b25d9ce1123073ef103594ec7017a919eb /src/runtime/histogram.go
parenta9ccd2d79574eead8c20d2bca4562cf2fd412787 (diff)
downloadgo-ae9771713383c1ee01a544cd50cfdbc22841380a.tar.gz
go-ae9771713383c1ee01a544cd50cfdbc22841380a.zip
runtime,runtime/metrics: use explicit histogram boundaries
This change modifies the semantics of runtime/metrics.Float64Histogram.Buckets to remove implicit buckets to that extend to positive and negative infinity and instead defines all bucket boundaries as explicitly listed. Bucket boundaries remain the same as before except /gc/heap/allocs-by-size:objects and /gc/heap/frees-by-size:objects no longer have a bucket that extends to negative infinity. This change simplifies the Float64Histogram API, making it both easier to understand and easier to use. Also, add a test for allocs-by-size and frees-by-size that checks them against MemStats. Fixes #43443. Change-Id: I5620f15bd084562dadf288f733c4a8cace21910c Reviewed-on: https://go-review.googlesource.com/c/go/+/281238 Run-TryBot: Michael Knyszek <mknyszek@google.com> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Austin Clements <austin@google.com> Reviewed-by: Michael Pratt <mpratt@google.com> Trust: Michael Knyszek <mknyszek@google.com>
Diffstat (limited to 'src/runtime/histogram.go')
-rw-r--r--src/runtime/histogram.go32
1 files changed, 28 insertions, 4 deletions
diff --git a/src/runtime/histogram.go b/src/runtime/histogram.go
index d48e856cd0..42baa6c5e2 100644
--- a/src/runtime/histogram.go
+++ b/src/runtime/histogram.go
@@ -7,6 +7,7 @@ package runtime
import (
"runtime/internal/atomic"
"runtime/internal/sys"
+ "unsafe"
)
const (
@@ -69,7 +70,13 @@ const (
// for concurrent use. It is also safe to read all the values
// atomically.
type timeHistogram struct {
- counts [timeHistNumSuperBuckets * timeHistNumSubBuckets]uint64
+ counts [timeHistNumSuperBuckets * timeHistNumSubBuckets]uint64
+
+ // underflow counts all the times we got a negative duration
+ // sample. Because of how time works on some platforms, it's
+ // possible to measure negative durations. We could ignore them,
+ // but we record them anyway because it's better to have some
+ // signal that it's happening than just missing samples.
underflow uint64
}
@@ -107,14 +114,30 @@ func (h *timeHistogram) record(duration int64) {
atomic.Xadd64(&h.counts[superBucket*timeHistNumSubBuckets+subBucket], 1)
}
+const (
+ fInf = 0x7FF0000000000000
+ fNegInf = 0xFFF0000000000000
+)
+
+func float64Inf() float64 {
+ inf := uint64(fInf)
+ return *(*float64)(unsafe.Pointer(&inf))
+}
+
+func float64NegInf() float64 {
+ inf := uint64(fNegInf)
+ return *(*float64)(unsafe.Pointer(&inf))
+}
+
// timeHistogramMetricsBuckets generates a slice of boundaries for
// the timeHistogram. These boundaries are represented in seconds,
// not nanoseconds like the timeHistogram represents durations.
func timeHistogramMetricsBuckets() []float64 {
- b := make([]float64, timeHistTotalBuckets-1)
+ b := make([]float64, timeHistTotalBuckets+1)
+ b[0] = float64NegInf()
for i := 0; i < timeHistNumSuperBuckets; i++ {
superBucketMin := uint64(0)
- // The (inclusive) minimum for the first bucket is 0.
+ // The (inclusive) minimum for the first non-negative bucket is 0.
if i > 0 {
// The minimum for the second bucket will be
// 1 << timeHistSubBucketBits, indicating that all
@@ -141,8 +164,9 @@ func timeHistogramMetricsBuckets() []float64 {
// Convert the subBucketMin which is in nanoseconds to a float64 seconds value.
// These values will all be exactly representable by a float64.
- b[i*timeHistNumSubBuckets+j] = float64(subBucketMin) / 1e9
+ b[i*timeHistNumSubBuckets+j+1] = float64(subBucketMin) / 1e9
}
}
+ b[len(b)-1] = float64Inf()
return b
}