Skip to content

Commit b7c28f4

Browse files
mknyszekgopherbot
authored andcommitted
runtime/metrics: add CPU stats
This changes adds a breakdown for estimated CPU usage by time. These estimates are not based on real on-CPU counters, so each metric has a disclaimer explaining so. They can, however, be more reasonably compared to a total CPU time metric that this change also adds. Fixes #47216. Change-Id: I125006526be9f8e0d609200e193da5a78d9935be Reviewed-on: https://go-review.googlesource.com/c/go/+/404307 Reviewed-by: Michael Pratt <[email protected]> Reviewed-by: Josh MacDonald <[email protected]> Auto-Submit: Michael Knyszek <[email protected]> Reviewed-by: David Chase <[email protected]> Run-TryBot: Michael Knyszek <[email protected]> TryBot-Result: Gopher Robot <[email protected]>
1 parent 87eda2a commit b7c28f4

11 files changed

+459
-21
lines changed

Diff for: src/runtime/metrics.go

+98
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,83 @@ func initMetrics() {
9090
out.scalar = uint64(NumCgoCall())
9191
},
9292
},
93+
"/cpu/classes/gc/mark/assist:cpu-seconds": {
94+
deps: makeStatDepSet(cpuStatsDep),
95+
compute: func(in *statAggregate, out *metricValue) {
96+
out.kind = metricKindFloat64
97+
out.scalar = float64bits(nsToSec(in.cpuStats.gcAssistTime))
98+
},
99+
},
100+
"/cpu/classes/gc/mark/dedicated:cpu-seconds": {
101+
deps: makeStatDepSet(cpuStatsDep),
102+
compute: func(in *statAggregate, out *metricValue) {
103+
out.kind = metricKindFloat64
104+
out.scalar = float64bits(nsToSec(in.cpuStats.gcDedicatedTime))
105+
},
106+
},
107+
"/cpu/classes/gc/mark/idle:cpu-seconds": {
108+
deps: makeStatDepSet(cpuStatsDep),
109+
compute: func(in *statAggregate, out *metricValue) {
110+
out.kind = metricKindFloat64
111+
out.scalar = float64bits(nsToSec(in.cpuStats.gcIdleTime))
112+
},
113+
},
114+
"/cpu/classes/gc/pause:cpu-seconds": {
115+
deps: makeStatDepSet(cpuStatsDep),
116+
compute: func(in *statAggregate, out *metricValue) {
117+
out.kind = metricKindFloat64
118+
out.scalar = float64bits(nsToSec(in.cpuStats.gcPauseTime))
119+
},
120+
},
121+
"/cpu/classes/gc/total:cpu-seconds": {
122+
deps: makeStatDepSet(cpuStatsDep),
123+
compute: func(in *statAggregate, out *metricValue) {
124+
out.kind = metricKindFloat64
125+
out.scalar = float64bits(nsToSec(in.cpuStats.gcTotalTime))
126+
},
127+
},
128+
"/cpu/classes/idle:cpu-seconds": {
129+
deps: makeStatDepSet(cpuStatsDep),
130+
compute: func(in *statAggregate, out *metricValue) {
131+
out.kind = metricKindFloat64
132+
out.scalar = float64bits(nsToSec(in.cpuStats.idleTime))
133+
},
134+
},
135+
"/cpu/classes/scavenge/assist:cpu-seconds": {
136+
deps: makeStatDepSet(cpuStatsDep),
137+
compute: func(in *statAggregate, out *metricValue) {
138+
out.kind = metricKindFloat64
139+
out.scalar = float64bits(nsToSec(in.cpuStats.scavengeAssistTime))
140+
},
141+
},
142+
"/cpu/classes/scavenge/background:cpu-seconds": {
143+
deps: makeStatDepSet(cpuStatsDep),
144+
compute: func(in *statAggregate, out *metricValue) {
145+
out.kind = metricKindFloat64
146+
out.scalar = float64bits(nsToSec(in.cpuStats.scavengeBgTime))
147+
},
148+
},
149+
"/cpu/classes/scavenge/total:cpu-seconds": {
150+
deps: makeStatDepSet(cpuStatsDep),
151+
compute: func(in *statAggregate, out *metricValue) {
152+
out.kind = metricKindFloat64
153+
out.scalar = float64bits(nsToSec(in.cpuStats.scavengeTotalTime))
154+
},
155+
},
156+
"/cpu/classes/total:cpu-seconds": {
157+
deps: makeStatDepSet(cpuStatsDep),
158+
compute: func(in *statAggregate, out *metricValue) {
159+
out.kind = metricKindFloat64
160+
out.scalar = float64bits(nsToSec(in.cpuStats.totalTime))
161+
},
162+
},
163+
"/cpu/classes/user:cpu-seconds": {
164+
deps: makeStatDepSet(cpuStatsDep),
165+
compute: func(in *statAggregate, out *metricValue) {
166+
out.kind = metricKindFloat64
167+
out.scalar = float64bits(nsToSec(in.cpuStats.userTime))
168+
},
169+
},
93170
"/gc/cycles/automatic:gc-cycles": {
94171
deps: makeStatDepSet(sysStatsDep),
95172
compute: func(in *statAggregate, out *metricValue) {
@@ -345,6 +422,7 @@ type statDep uint
345422
const (
346423
heapStatsDep statDep = iota // corresponds to heapStatsAggregate
347424
sysStatsDep // corresponds to sysStatsAggregate
425+
cpuStatsDep // corresponds to cpuStatsAggregate
348426
numStatsDeps
349427
)
350428

@@ -490,6 +568,23 @@ func (a *sysStatsAggregate) compute() {
490568
})
491569
}
492570

571+
// cpuStatsAggregate represents CPU stats obtained from the runtime
572+
// acquired together to avoid skew and inconsistencies.
573+
type cpuStatsAggregate struct {
574+
cpuStats
575+
}
576+
577+
// compute populates the cpuStatsAggregate with values from the runtime.
578+
func (a *cpuStatsAggregate) compute() {
579+
a.cpuStats = work.cpuStats
580+
}
581+
582+
// nsToSec takes a duration in nanoseconds and converts it to seconds as
583+
// a float64.
584+
func nsToSec(ns int64) float64 {
585+
return float64(ns) / 1e9
586+
}
587+
493588
// statAggregate is the main driver of the metrics implementation.
494589
//
495590
// It contains multiple aggregates of runtime statistics, as well
@@ -499,6 +594,7 @@ type statAggregate struct {
499594
ensured statDepSet
500595
heapStats heapStatsAggregate
501596
sysStats sysStatsAggregate
597+
cpuStats cpuStatsAggregate
502598
}
503599

504600
// ensure populates statistics aggregates determined by deps if they
@@ -517,6 +613,8 @@ func (a *statAggregate) ensure(deps *statDepSet) {
517613
a.heapStats.compute()
518614
case sysStatsDep:
519615
a.sysStats.compute()
616+
case cpuStatsDep:
617+
a.cpuStats.compute()
520618
}
521619
}
522620
a.ensured = a.ensured.union(missing)

Diff for: src/runtime/metrics/description.go

+116
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,122 @@ var allDesc = []Description{
5757
Kind: KindUint64,
5858
Cumulative: true,
5959
},
60+
{
61+
Name: "/cpu/classes/gc/mark/assist:cpu-seconds",
62+
Description: "Estimated total CPU time goroutines spent performing GC tasks " +
63+
"to assist the GC and prevent it from falling behind the application. " +
64+
"This metric is an overestimate, and not directly comparable to " +
65+
"system CPU time measurements. Compare only with other /cpu/classes " +
66+
"metrics.",
67+
Kind: KindFloat64,
68+
Cumulative: true,
69+
},
70+
{
71+
Name: "/cpu/classes/gc/mark/dedicated:cpu-seconds",
72+
Description: "Estimated total CPU time spent performing GC tasks on " +
73+
"processors (as defined by GOMAXPROCS) dedicated to those tasks. " +
74+
"This includes time spent with the world stopped due to the GC. " +
75+
"This metric is an overestimate, and not directly comparable to " +
76+
"system CPU time measurements. Compare only with other /cpu/classes " +
77+
"metrics.",
78+
Kind: KindFloat64,
79+
Cumulative: true,
80+
},
81+
{
82+
Name: "/cpu/classes/gc/mark/idle:cpu-seconds",
83+
Description: "Estimated total CPU time spent performing GC tasks on " +
84+
"spare CPU resources that the Go scheduler could not otherwise find " +
85+
"a use for. This should be subtracted from the total GC CPU time to " +
86+
"obtain a measure of compulsory GC CPU time. " +
87+
"This metric is an overestimate, and not directly comparable to " +
88+
"system CPU time measurements. Compare only with other /cpu/classes " +
89+
"metrics.",
90+
Kind: KindFloat64,
91+
Cumulative: true,
92+
},
93+
{
94+
Name: "/cpu/classes/gc/pause:cpu-seconds",
95+
Description: "Estimated total CPU time spent with the application paused by " +
96+
"the GC. Even if only one thread is running during the pause, this is " +
97+
"computed as GOMAXPROCS times the pause latency because nothing else " +
98+
"can be executing. This is the exact sum of samples in /gc/pause:seconds " +
99+
"if each sample is multiplied by GOMAXPROCS at the time it is taken. " +
100+
"This metric is an overestimate, and not directly comparable to " +
101+
"system CPU time measurements. Compare only with other /cpu/classes " +
102+
"metrics.",
103+
Kind: KindFloat64,
104+
Cumulative: true,
105+
},
106+
{
107+
Name: "/cpu/classes/gc/total:cpu-seconds",
108+
Description: "Estimated total CPU time spent performing GC tasks. " +
109+
"This metric is an overestimate, and not directly comparable to " +
110+
"system CPU time measurements. Compare only with other /cpu/classes " +
111+
"metrics. Sum of all metrics in /cpu/classes/gc.",
112+
Kind: KindFloat64,
113+
Cumulative: true,
114+
},
115+
{
116+
Name: "/cpu/classes/idle:cpu-seconds",
117+
Description: "Estimated total available CPU time not spent executing any Go or Go runtime code. " +
118+
"In other words, the part of /cpu/classes/total:cpu-seconds that was unused. " +
119+
"This metric is an overestimate, and not directly comparable to " +
120+
"system CPU time measurements. Compare only with other /cpu/classes " +
121+
"metrics.",
122+
Kind: KindFloat64,
123+
Cumulative: true,
124+
},
125+
{
126+
Name: "/cpu/classes/scavenge/assist:cpu-seconds",
127+
Description: "Estimated total CPU time spent returning unused memory to the " +
128+
"underlying platform in response eagerly in response to memory pressure. " +
129+
"This metric is an overestimate, and not directly comparable to " +
130+
"system CPU time measurements. Compare only with other /cpu/classes " +
131+
"metrics.",
132+
Kind: KindFloat64,
133+
Cumulative: true,
134+
},
135+
{
136+
Name: "/cpu/classes/scavenge/background:cpu-seconds",
137+
Description: "Estimated total CPU time spent performing background tasks " +
138+
"to return unused memory to the underlying platform. " +
139+
"This metric is an overestimate, and not directly comparable to " +
140+
"system CPU time measurements. Compare only with other /cpu/classes " +
141+
"metrics.",
142+
Kind: KindFloat64,
143+
Cumulative: true,
144+
},
145+
{
146+
Name: "/cpu/classes/scavenge/total:cpu-seconds",
147+
Description: "Estimated total CPU time spent performing tasks that return " +
148+
"unused memory to the underlying platform. " +
149+
"This metric is an overestimate, and not directly comparable to " +
150+
"system CPU time measurements. Compare only with other /cpu/classes " +
151+
"metrics. Sum of all metrics in /cpu/classes/scavenge.",
152+
Kind: KindFloat64,
153+
Cumulative: true,
154+
},
155+
{
156+
Name: "/cpu/classes/total:cpu-seconds",
157+
Description: "Estimated total available CPU time for user Go code " +
158+
"or the Go runtime, as defined by GOMAXPROCS. In other words, GOMAXPROCS " +
159+
"integrated over the wall-clock duration this process has been executing for. " +
160+
"This metric is an overestimate, and not directly comparable to " +
161+
"system CPU time measurements. Compare only with other /cpu/classes " +
162+
"metrics. Sum of all metrics in /cpu/classes.",
163+
Kind: KindFloat64,
164+
Cumulative: true,
165+
},
166+
{
167+
Name: "/cpu/classes/user:cpu-seconds",
168+
Description: "Estimated total CPU time spent running user Go code. This may " +
169+
"also include some small amount of time spent in the Go runtime. " +
170+
"This metric is an overestimate, and not directly comparable to " +
171+
"system CPU time measurements. Compare only with other /cpu/classes " +
172+
"metrics.",
173+
Kind: KindFloat64,
174+
Cumulative: true,
175+
},
60176
{
61177
Name: "/gc/cycles/automatic:gc-cycles",
62178
Description: "Count of completed GC cycles generated by the Go runtime.",

Diff for: src/runtime/metrics/doc.go

+84
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,90 @@ Below is the full list of supported metrics, ordered lexicographically.
5454
/cgo/go-to-c-calls:calls
5555
Count of calls made from Go to C by the current process.
5656
57+
/cpu/classes/gc/mark/assist:cpu-seconds
58+
Estimated total CPU time goroutines spent performing GC tasks
59+
to assist the GC and prevent it from falling behind the application.
60+
This metric is an overestimate, and not directly comparable to
61+
system CPU time measurements. Compare only with other /cpu/classes
62+
metrics.
63+
64+
/cpu/classes/gc/mark/dedicated:cpu-seconds
65+
Estimated total CPU time spent performing GC tasks on
66+
processors (as defined by GOMAXPROCS) dedicated to those tasks.
67+
This includes time spent with the world stopped due to the GC.
68+
This metric is an overestimate, and not directly comparable to
69+
system CPU time measurements. Compare only with other /cpu/classes
70+
metrics.
71+
72+
/cpu/classes/gc/mark/idle:cpu-seconds
73+
Estimated total CPU time spent performing GC tasks on
74+
spare CPU resources that the Go scheduler could not otherwise find
75+
a use for. This should be subtracted from the total GC CPU time to
76+
obtain a measure of compulsory GC CPU time.
77+
This metric is an overestimate, and not directly comparable to
78+
system CPU time measurements. Compare only with other /cpu/classes
79+
metrics.
80+
81+
/cpu/classes/gc/pause:cpu-seconds
82+
Estimated total CPU time spent with the application paused by
83+
the GC. Even if only one thread is running during the pause, this is
84+
computed as GOMAXPROCS times the pause latency because nothing else
85+
can be executing. This is the exact sum of samples in /gc/pause:seconds
86+
if each sample is multiplied by GOMAXPROCS at the time it is taken.
87+
This metric is an overestimate, and not directly comparable to
88+
system CPU time measurements. Compare only with other /cpu/classes
89+
metrics.
90+
91+
/cpu/classes/gc/total:cpu-seconds
92+
Estimated total CPU time spent performing GC tasks.
93+
This metric is an overestimate, and not directly comparable to
94+
system CPU time measurements. Compare only with other /cpu/classes
95+
metrics. Sum of all metrics in /cpu/classes/gc.
96+
97+
/cpu/classes/idle:cpu-seconds
98+
Estimated total available CPU time not spent executing any Go or Go
99+
runtime code. In other words, the part of /cpu/classes/total:cpu-seconds
100+
that was unused.
101+
This metric is an overestimate, and not directly comparable to
102+
system CPU time measurements. Compare only with other /cpu/classes
103+
metrics.
104+
105+
/cpu/classes/scavenge/assist:cpu-seconds
106+
Estimated total CPU time spent returning unused memory to the
107+
underlying platform in response eagerly in response to memory pressure.
108+
This metric is an overestimate, and not directly comparable to
109+
system CPU time measurements. Compare only with other /cpu/classes
110+
metrics.
111+
112+
/cpu/classes/scavenge/background:cpu-seconds
113+
Estimated total CPU time spent performing background tasks
114+
to return unused memory to the underlying platform.
115+
This metric is an overestimate, and not directly comparable to
116+
system CPU time measurements. Compare only with other /cpu/classes
117+
metrics.
118+
119+
/cpu/classes/scavenge/total:cpu-seconds
120+
Estimated total CPU time spent performing tasks that return
121+
unused memory to the underlying platform.
122+
This metric is an overestimate, and not directly comparable to
123+
system CPU time measurements. Compare only with other /cpu/classes
124+
metrics. Sum of all metrics in /cpu/classes/scavenge.
125+
126+
/cpu/classes/total:cpu-seconds
127+
Estimated total available CPU time for user Go code or the Go runtime, as
128+
defined by GOMAXPROCS. In other words, GOMAXPROCS integrated over the
129+
wall-clock duration this process has been executing for.
130+
This metric is an overestimate, and not directly comparable to
131+
system CPU time measurements. Compare only with other /cpu/classes
132+
metrics. Sum of all metrics in /cpu/classes.
133+
134+
/cpu/classes/user:cpu-seconds
135+
Estimated total CPU time spent running user Go code. This may
136+
also include some small amount of time spent in the Go runtime.
137+
This metric is an overestimate, and not directly comparable to
138+
system CPU time measurements. Compare only with other /cpu/classes
139+
metrics.
140+
57141
/gc/cycles/automatic:gc-cycles
58142
Count of completed GC cycles generated by the Go runtime.
59143

0 commit comments

Comments
 (0)