Skip to content

Commit 0495438

Browse files
RaduBerinderickystewart
authored andcommitted
cockroach: runtime: add grunningnanos
Add a routine that returns the wall time spent by current goroutine in the running state.
1 parent ad772a4 commit 0495438

File tree

7 files changed

+61
-19
lines changed

7 files changed

+61
-19
lines changed

api/go1.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30870,3 +30870,4 @@ pkg unicode/utf8, func RuneStart(uint8) bool
3087030870
pkg unicode/utf8, func Valid([]uint8) bool
3087130871
pkg unicode/utf8, func ValidString(string) bool
3087230872
pkg context, func PropagateCancel(Context, func()) bool
30873+
pkg runtime, func Grunningnanos() int64

src/runtime/extern.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,10 @@ It is a comma-separated list of name=val pairs setting these named variables:
111111
making every garbage collection a stop-the-world event. Setting gcstoptheworld=2
112112
also disables concurrent sweeping after the garbage collection finishes.
113113
114+
gcnoassist: setting gcnoassist=1 disables garbage collection assist, minimizing
115+
garbage collection overhead for user goroutines at the expense of a higher risk
116+
of out-of-memory failures with high allocation rates.
117+
114118
gctrace: setting gctrace=1 causes the garbage collector to emit a single line to standard
115119
error at each collection, summarizing the amount of memory collected and the
116120
length of the pause. The format of this line is subject to change. Included in

src/runtime/malloc.go

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1696,20 +1696,22 @@ func postMallocgcDebug(x unsafe.Pointer, elemsize uintptr, typ *_type) {
16961696
//
16971697
// Returns the G for which the assist credit was accounted.
16981698
func deductAssistCredit(size uintptr) {
1699-
// Charge the current user G for this allocation.
1700-
assistG := getg()
1701-
if assistG.m.curg != nil {
1702-
assistG = assistG.m.curg
1703-
}
1704-
// Charge the allocation against the G. We'll account
1705-
// for internal fragmentation at the end of mallocgc.
1706-
assistG.gcAssistBytes -= int64(size)
1707-
1708-
if assistG.gcAssistBytes < 0 {
1709-
// This G is in debt. Assist the GC to correct
1710-
// this before allocating. This must happen
1711-
// before disabling preemption.
1712-
gcAssistAlloc(assistG)
1699+
if debug.gcnoassist == 0 {
1700+
// Charge the current user G for this allocation.
1701+
assistG := getg()
1702+
if assistG.m.curg != nil {
1703+
assistG = assistG.m.curg
1704+
}
1705+
// Charge the allocation against the G. We'll account
1706+
// for internal fragmentation at the end of mallocgc.
1707+
assistG.gcAssistBytes -= int64(size)
1708+
1709+
if assistG.gcAssistBytes < 0 {
1710+
// This G is in debt. Assist the GC to correct
1711+
// this before allocating. This must happen
1712+
// before disabling preemption.
1713+
gcAssistAlloc(assistG)
1714+
}
17131715
}
17141716
}
17151717

src/runtime/proc.go

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1232,6 +1232,11 @@ func casfrom_Gscanstatus(gp *g, oldval, newval uint32) {
12321232
dumpgstatus(gp)
12331233
throw("casfrom_Gscanstatus: gp->status is not in scan state")
12341234
}
1235+
// We're transitioning into the running state, record the timestamp for
1236+
// subsequent use.
1237+
if newval == _Grunning {
1238+
gp.lastsched = nanotime()
1239+
}
12351240
releaseLockRankAndM(lockRankGscan)
12361241
}
12371242

@@ -1247,6 +1252,11 @@ func castogscanstatus(gp *g, oldval, newval uint32) bool {
12471252
r := gp.atomicstatus.CompareAndSwap(oldval, newval)
12481253
if r {
12491254
acquireLockRankAndM(lockRankGscan)
1255+
// We're transitioning out of running, record how long we were in the
1256+
// state.
1257+
if oldval == _Grunning {
1258+
gp.runningnanos += nanotime() - gp.lastsched
1259+
}
12501260
}
12511261
return r
12521262

@@ -1312,7 +1322,18 @@ func casgstatus(gp *g, oldval, newval uint32) {
13121322
})
13131323
}
13141324

1325+
now := nanotime()
1326+
if newval == _Grunning {
1327+
// We're transitioning into the running state, record the timestamp for
1328+
// subsequent use.
1329+
gp.lastsched = now
1330+
}
1331+
13151332
if oldval == _Grunning {
1333+
// We're transitioning out of running, record how long we were in the
1334+
// state.
1335+
gp.runningnanos += now - gp.lastsched
1336+
13161337
// Track every gTrackingPeriod time a goroutine transitions out of running.
13171338
if casgstatusAlwaysTrack || gp.trackingSeq%gTrackingPeriod == 0 {
13181339
gp.tracking = true
@@ -1333,7 +1354,6 @@ func casgstatus(gp *g, oldval, newval uint32) {
13331354
// We transitioned out of runnable, so measure how much
13341355
// time we spent in this state and add it to
13351356
// runnableTime.
1336-
now := nanotime()
13371357
gp.runnableTime += now - gp.trackingStamp
13381358
gp.trackingStamp = 0
13391359
case _Gwaiting:
@@ -1346,7 +1366,6 @@ func casgstatus(gp *g, oldval, newval uint32) {
13461366
// a more representative estimate of the absolute value.
13471367
// gTrackingPeriod also represents an accurate sampling period
13481368
// because we can only enter this state from _Grunning.
1349-
now := nanotime()
13501369
sched.totalMutexWaitTime.Add((now - gp.trackingStamp) * gTrackingPeriod)
13511370
gp.trackingStamp = 0
13521371
}
@@ -1357,12 +1376,10 @@ func casgstatus(gp *g, oldval, newval uint32) {
13571376
break
13581377
}
13591378
// Blocking on a lock. Write down the timestamp.
1360-
now := nanotime()
13611379
gp.trackingStamp = now
13621380
case _Grunnable:
13631381
// We just transitioned into runnable, so record what
13641382
// time that happened.
1365-
now := nanotime()
13661383
gp.trackingStamp = now
13671384
case _Grunning:
13681385
// We're transitioning into running, so turn off
@@ -1411,6 +1428,10 @@ func casGToPreemptScan(gp *g, old, new uint32) {
14111428
// ordering between the gscan and synctest locks. The bubble doesn't
14121429
// distinguish between _Grunning and _Gpreempted anyway, so not
14131430
// notifying it is fine.
1431+
1432+
// We're transitioning out of running, record how long we were in the
1433+
// state.
1434+
gp.runningnanos += nanotime() - gp.lastsched
14141435
}
14151436

14161437
// casGFromPreempted attempts to transition gp from _Gpreempted to
@@ -4220,6 +4241,14 @@ func dropg() {
42204241
setGNoWB(&gp.m.curg, nil)
42214242
}
42224243

4244+
// Grunningnanos returns the wall time spent by current g in the running state.
4245+
// A goroutine may be running on an OS thread that's descheduled by the OS
4246+
// scheduler, this time still counts towards the metric.
4247+
func Grunningnanos() int64 {
4248+
gp := getg()
4249+
return gp.runningnanos + nanotime() - gp.lastsched
4250+
}
4251+
42234252
func parkunlock_c(gp *g, lock unsafe.Pointer) bool {
42244253
unlock((*mutex)(lock))
42254254
return true
@@ -4472,6 +4501,8 @@ func gdestroy(gp *g) {
44724501
gp.labels = nil
44734502
gp.timer = nil
44744503
gp.bubble = nil
4504+
gp.lastsched = 0
4505+
gp.runningnanos = 0
44754506

44764507
if gcBlackenEnabled != 0 && gp.gcAssistBytes > 0 {
44774508
// Flush assist credit to the global pool. This gives

src/runtime/runtime1.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -319,6 +319,7 @@ var debug struct {
319319
gcpacertrace int32
320320
gcshrinkstackoff int32
321321
gcstoptheworld int32
322+
gcnoassist int32
322323
gctrace int32
323324
invalidptr int32
324325
madvdontneed int32 // for Linux; issue 28466
@@ -383,6 +384,7 @@ var dbgvars = []*dbgVar{
383384
{name: "gcpacertrace", value: &debug.gcpacertrace},
384385
{name: "gcshrinkstackoff", value: &debug.gcshrinkstackoff},
385386
{name: "gcstoptheworld", value: &debug.gcstoptheworld},
387+
{name: "gcnoassist", value: &debug.gcnoassist},
386388
{name: "gctrace", value: &debug.gctrace},
387389
{name: "harddecommit", value: &debug.harddecommit},
388390
{name: "inittrace", value: &debug.inittrace},

src/runtime/runtime2.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -491,6 +491,8 @@ type g struct {
491491

492492
coroarg *coro // argument during coroutine transfers
493493
bubble *synctestBubble
494+
lastsched int64 // timestamp when the G last started running
495+
runningnanos int64 // wall time spent in the running state
494496

495497
// Per-G tracer state.
496498
trace gTraceState

src/runtime/sizeof_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ func TestSizeof(t *testing.T) {
2020
_32bit uintptr // size on 32bit platforms
2121
_64bit uintptr // size on 64bit platforms
2222
}{
23-
{runtime.G{}, 280, 440}, // g, but exported for testing
23+
{runtime.G{}, 296, 456}, // g, but exported for testing
2424
{runtime.Sudog{}, 56, 88}, // sudog, but exported for testing
2525
}
2626

0 commit comments

Comments
 (0)