Skip to content

Commit 78a3968

Browse files
mknyszekgopherbot
authored andcommitted
runtime/metrics: add metric for current Go-owned thread count
Fixes golang#15490. Change-Id: I6ce9edc46398030ff639e22d4ca4adebccdfe1b7 Reviewed-on: https://go-review.googlesource.com/c/go/+/690399 Auto-Submit: Michael Knyszek <[email protected]> LUCI-TryBot-Result: Go LUCI <[email protected]> Reviewed-by: Michael Pratt <[email protected]>
1 parent ab8121a commit 78a3968

File tree

6 files changed

+35
-3
lines changed

6 files changed

+35
-3
lines changed

src/runtime/metrics.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -532,6 +532,13 @@ func initMetrics() {
532532
sched.stwTotalTimeOther.write(out)
533533
},
534534
},
535+
"/sched/threads/total:threads": {
536+
deps: makeStatDepSet(schedStatsDep),
537+
compute: func(in *statAggregate, out *metricValue) {
538+
out.kind = metricKindUint64
539+
out.scalar = uint64(in.schedStats.threads)
540+
},
541+
},
535542
"/sync/mutex/wait/total:seconds": {
536543
compute: func(_ *statAggregate, out *metricValue) {
537544
out.kind = metricKindFloat64
@@ -787,6 +794,7 @@ type schedStatsAggregate struct {
787794
gNonGo uint64
788795
gWaiting uint64
789796
gCreated uint64
797+
threads uint64
790798
}
791799

792800
// compute populates the schedStatsAggregate with values from the runtime.
@@ -797,6 +805,10 @@ func (a *schedStatsAggregate) compute() {
797805
// approximate.
798806
lock(&sched.lock)
799807

808+
// The total count of threads owned by Go is the number of Ms
809+
// minus extra Ms on the list or in use.
810+
a.threads = uint64(mcount()) - uint64(extraMInUse.Load()) - uint64(extraMLength.Load())
811+
800812
// Collect running/runnable from per-P run queues.
801813
a.gCreated += sched.goroutinesCreated.Load()
802814
for _, p := range allp {

src/runtime/metrics/description.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -498,6 +498,11 @@ var allDesc = []Description{
498498
Kind: KindFloat64Histogram,
499499
Cumulative: true,
500500
},
501+
{
502+
Name: "/sched/threads/total:threads",
503+
Description: "The current count of live threads that are owned by the Go runtime.",
504+
Kind: KindUint64,
505+
},
501506
{
502507
Name: "/sync/mutex/wait/total:seconds",
503508
Description: "Approximate cumulative time goroutines have spent blocked on a sync.Mutex, sync.RWMutex, or runtime-internal lock. This metric is useful for identifying global changes in lock contention. Collect a mutex or block profile using the runtime/pprof package for more detailed contention data.",

src/runtime/metrics/doc.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -572,6 +572,10 @@ Below is the full list of supported metrics, ordered lexicographically.
572572
/sched/pauses/stopping/other:seconds). Bucket counts increase
573573
monotonically.
574574
575+
/sched/threads/total:threads
576+
The current count of live threads that are owned by the Go
577+
runtime.
578+
575579
/sync/mutex/wait/total:seconds
576580
Approximate cumulative time goroutines have spent blocked on a
577581
sync.Mutex, sync.RWMutex, or runtime-internal lock. This metric

src/runtime/metrics_test.go

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1584,13 +1584,16 @@ func TestReadMetricsSched(t *testing.T) {
15841584
running
15851585
waiting
15861586
created
1587+
threads
1588+
numSamples
15871589
)
1588-
var s [5]metrics.Sample
1590+
var s [numSamples]metrics.Sample
15891591
s[notInGo].Name = "/sched/goroutines/not-in-go:goroutines"
15901592
s[runnable].Name = "/sched/goroutines/runnable:goroutines"
15911593
s[running].Name = "/sched/goroutines/running:goroutines"
15921594
s[waiting].Name = "/sched/goroutines/waiting:goroutines"
15931595
s[created].Name = "/sched/goroutines-created:goroutines"
1596+
s[threads].Name = "/sched/threads/total:threads"
15941597

15951598
logMetrics := func(t *testing.T, s []metrics.Sample) {
15961599
for i := range s {
@@ -1608,6 +1611,10 @@ func TestReadMetricsSched(t *testing.T) {
16081611
// goroutines.
16091612
const waitingSlack = 100
16101613

1614+
// threadsSlack is the maximum number of threads left over
1615+
// from other tests and the runtime (sysmon, the template thread, etc.)
1616+
const threadsSlack = 20
1617+
16111618
// Make sure GC isn't running, since GC workers interfere with
16121619
// expected counts.
16131620
defer debug.SetGCPercent(debug.SetGCPercent(-1))
@@ -1694,6 +1701,7 @@ func TestReadMetricsSched(t *testing.T) {
16941701
}, time.Second)
16951702
logMetrics(t, s[:])
16961703
check(t, &s[running], count, count+4)
1704+
check(t, &s[threads], count, count+4+threadsSlack)
16971705
})
16981706

16991707
// Force runnable count to be high.
@@ -1724,6 +1732,7 @@ func TestReadMetricsSched(t *testing.T) {
17241732
t.Run("running", func(t *testing.T) {
17251733
logMetrics(t, s[:])
17261734
checkEq(t, &s[running], 1)
1735+
checkEq(t, &s[threads], 1)
17271736
})
17281737
t.Run("runnable", func(t *testing.T) {
17291738
logMetrics(t, s[:])

src/runtime/proc.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1007,7 +1007,7 @@ func mcommoninit(mp *m, id int64) {
10071007
// when it is just in a register or thread-local storage.
10081008
mp.alllink = allm
10091009

1010-
// NumCgoCall() and others iterate over allm w/o schedlock,
1010+
// NumCgoCall and others iterate over allm w/o schedlock,
10111011
// so we need to publish it safely.
10121012
atomicstorep(unsafe.Pointer(&allm), unsafe.Pointer(mp))
10131013
unlock(&sched.lock)

src/runtime/runtime2.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1225,7 +1225,9 @@ var isIdleInSynctest = [len(waitReasonStrings)]bool{
12251225
}
12261226

12271227
var (
1228-
allm *m
1228+
// Linked-list of all Ms. Written under sched.lock, read atomically.
1229+
allm *m
1230+
12291231
gomaxprocs int32
12301232
numCPUStartup int32
12311233
forcegc forcegcstate

0 commit comments

Comments
 (0)