runtime,runtime/metrics: add heap goal and GC cycle metrics

This change adds three new metrics: the heap goal, GC cycle count, and
forced GC count. These metrics are identical to their MemStats
counterparts.

For #37112.

Change-Id: I5a5e8dd550c0d646e5dcdbdf38274895e27cdd88
Reviewed-on: https://go-review.googlesource.com/c/go/+/247044
Run-TryBot: Michael Knyszek <mknyszek@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Trust: Michael Knyszek <mknyszek@google.com>
Reviewed-by: Michael Pratt <mpratt@google.com>
This commit is contained in:
Michael Anthony Knyszek 2020-08-06 16:47:58 +00:00 committed by Michael Knyszek
parent 07c3f65d53
commit a8b28ebc87
4 changed files with 86 additions and 8 deletions

View file

@ -7,6 +7,7 @@ package runtime
// Metrics implementation exported to runtime/metrics. // Metrics implementation exported to runtime/metrics.
import ( import (
"runtime/internal/atomic"
"unsafe" "unsafe"
) )
@ -38,6 +39,34 @@ func initMetrics() {
return return
} }
metrics = map[string]metricData{ metrics = map[string]metricData{
"/gc/cycles/automatic:gc-cycles": {
deps: makeStatDepSet(sysStatsDep),
compute: func(in *statAggregate, out *metricValue) {
out.kind = metricKindUint64
out.scalar = in.sysStats.gcCyclesDone - in.sysStats.gcCyclesForced
},
},
"/gc/cycles/forced:gc-cycles": {
deps: makeStatDepSet(sysStatsDep),
compute: func(in *statAggregate, out *metricValue) {
out.kind = metricKindUint64
out.scalar = in.sysStats.gcCyclesForced
},
},
"/gc/cycles/total:gc-cycles": {
deps: makeStatDepSet(sysStatsDep),
compute: func(in *statAggregate, out *metricValue) {
out.kind = metricKindUint64
out.scalar = in.sysStats.gcCyclesDone
},
},
"/gc/heap/goal:bytes": {
deps: makeStatDepSet(sysStatsDep),
compute: func(in *statAggregate, out *metricValue) {
out.kind = metricKindUint64
out.scalar = in.sysStats.heapGoal
},
},
"/gc/heap/objects:objects": { "/gc/heap/objects:objects": {
deps: makeStatDepSet(heapStatsDep), deps: makeStatDepSet(heapStatsDep),
compute: func(in *statAggregate, out *metricValue) { compute: func(in *statAggregate, out *metricValue) {
@ -256,6 +285,9 @@ type sysStatsAggregate struct {
buckHashSys uint64 buckHashSys uint64
gcMiscSys uint64 gcMiscSys uint64
otherSys uint64 otherSys uint64
heapGoal uint64
gcCyclesDone uint64
gcCyclesForced uint64
} }
// compute populates the sysStatsAggregate with values from the runtime. // compute populates the sysStatsAggregate with values from the runtime.
@ -264,6 +296,9 @@ func (a *sysStatsAggregate) compute() {
a.buckHashSys = memstats.buckhash_sys.load() a.buckHashSys = memstats.buckhash_sys.load()
a.gcMiscSys = memstats.gcMiscSys.load() a.gcMiscSys = memstats.gcMiscSys.load()
a.otherSys = memstats.other_sys.load() a.otherSys = memstats.other_sys.load()
a.heapGoal = atomic.Load64(&memstats.next_gc)
a.gcCyclesDone = uint64(memstats.numgc)
a.gcCyclesForced = uint64(memstats.numforcedgc)
systemstack(func() { systemstack(func() {
lock(&mheap_.lock) lock(&mheap_.lock)

View file

@ -50,6 +50,29 @@ type Description struct {
// The English language descriptions below must be kept in sync with the // The English language descriptions below must be kept in sync with the
// descriptions of each metric in doc.go. // descriptions of each metric in doc.go.
var allDesc = []Description{ var allDesc = []Description{
{
Name: "/gc/cycles/automatic:gc-cycles",
Description: "Count of completed GC cycles generated by the Go runtime.",
Kind: KindUint64,
Cumulative: true,
},
{
Name: "/gc/cycles/forced:gc-cycles",
Description: "Count of completed forced GC cycles.",
Kind: KindUint64,
Cumulative: true,
},
{
Name: "/gc/cycles/total:gc-cycles",
Description: "Count of all completed GC cycles.",
Kind: KindUint64,
Cumulative: true,
},
{
Name: "/gc/heap/goal:bytes",
Description: "Heap size target for the end of the GC cycle.",
Kind: KindUint64,
},
{ {
Name: "/gc/heap/objects:objects", Name: "/gc/heap/objects:objects",
Description: "Number of objects, live or unswept, occupying heap memory.", Description: "Number of objects, live or unswept, occupying heap memory.",

View file

@ -44,6 +44,18 @@ the documentation of the Name field of the Description struct.
Supported metrics Supported metrics
/gc/cycles/automatic:gc-cycles
Count of completed GC cycles generated by the Go runtime.
/gc/cycles/forced:gc-cycles
Count of completed forced GC cycles.
/gc/cycles/total:gc-cycles
Count of all completed GC cycles.
/gc/heap/goal:bytes
Heap size target for the end of the GC cycle.
/gc/heap/objects:objects /gc/heap/objects:objects
Number of objects, live or unswept, occupying heap memory. Number of objects, live or unswept, occupying heap memory.

View file

@ -72,6 +72,14 @@ func TestReadMetrics(t *testing.T) {
checkUint64(t, name, samples[i].Value.Uint64(), mstats.Sys) checkUint64(t, name, samples[i].Value.Uint64(), mstats.Sys)
case "/gc/heap/objects:objects": case "/gc/heap/objects:objects":
checkUint64(t, name, samples[i].Value.Uint64(), mstats.HeapObjects) checkUint64(t, name, samples[i].Value.Uint64(), mstats.HeapObjects)
case "/gc/heap/goal:bytes":
checkUint64(t, name, samples[i].Value.Uint64(), mstats.NextGC)
case "/gc/cycles/automatic:gc-cycles":
checkUint64(t, name, samples[i].Value.Uint64(), uint64(mstats.NumGC-mstats.NumForcedGC))
case "/gc/cycles/forced:gc-cycles":
checkUint64(t, name, samples[i].Value.Uint64(), uint64(mstats.NumForcedGC))
case "/gc/cycles/total:gc-cycles":
checkUint64(t, name, samples[i].Value.Uint64(), uint64(mstats.NumGC))
} }
} }
} }