Skip to content

Commit cc6a7fc

Browse files
committed
runtime: increase precision of gctrace times
Currently we truncate gctrace clock and CPU times to millisecond precision. As a result, many phases are typically printed as 0, which is fine for user consumption, but makes gathering statistics and reports over GC traces difficult. In 1.4, the gctrace line printed times in microseconds. This was better for statistics, but not as easy for users to read or interpret, and it generally made the trace lines longer. This change strikes a balance between these extremes by printing milliseconds, but including the decimal part to two significant figures down to microsecond precision. This remains easy to read and interpret, but includes more precision when it's useful. For example, where the code currently prints, gc #29 @1.629s 0%: 0+2+0+12+0 ms clock, 0+2+0+0/12/0+0 ms cpu, 4->4->2 MB, 4 MB goal, 1 P this prints, gc #29 @1.629s 0%: 0.005+2.1+0+12+0.29 ms clock, 0.005+2.1+0+0/12/0+0.29 ms cpu, 4->4->2 MB, 4 MB goal, 1 P Fixes #10970. Change-Id: I249624779433927cd8b0947b986df9060c289075 Reviewed-on: https://go-review.googlesource.com/10554 Reviewed-by: Russ Cox <[email protected]>
1 parent 3216631 commit cc6a7fc

File tree

1 file changed

+40
-13
lines changed

1 file changed

+40
-13
lines changed

src/runtime/mgc.go

+40-13
Original file line numberDiff line numberDiff line change
@@ -994,19 +994,26 @@ func gc(mode int) {
994994
printlock()
995995
print("gc #", memstats.numgc,
996996
" @", string(itoaDiv(sbuf[:], uint64(tEnd-runtimeInitTime)/1e6, 3)), "s ",
997-
util, "%: ",
998-
(tScan-tSweepTerm)/1e6,
999-
"+", (tInstallWB-tScan)/1e6,
1000-
"+", (tMark-tInstallWB)/1e6,
1001-
"+", (tMarkTerm-tMark)/1e6,
1002-
"+", (tEnd-tMarkTerm)/1e6, " ms clock, ",
1003-
sweepTermCpu/1e6,
1004-
"+", scanCpu/1e6,
1005-
"+", installWBCpu/1e6,
1006-
"+", gcController.assistTime/1e6,
1007-
"/", (gcController.dedicatedMarkTime+gcController.fractionalMarkTime)/1e6,
1008-
"/", gcController.idleMarkTime/1e6,
1009-
"+", markTermCpu/1e6, " ms cpu, ",
997+
util, "%: ")
998+
prev := tSweepTerm
999+
for i, ns := range []int64{tScan, tInstallWB, tMark, tMarkTerm, tEnd} {
1000+
if i != 0 {
1001+
print("+")
1002+
}
1003+
print(string(fmtNSAsMS(sbuf[:], uint64(ns-prev))))
1004+
prev = ns
1005+
}
1006+
print(" ms clock, ")
1007+
for i, ns := range []int64{sweepTermCpu, scanCpu, installWBCpu, gcController.assistTime, gcController.dedicatedMarkTime + gcController.fractionalMarkTime, gcController.idleMarkTime, markTermCpu} {
1008+
if i == 4 || i == 5 {
1009+
// Separate mark time components with /.
1010+
print("/")
1011+
} else if i != 0 {
1012+
print("+")
1013+
}
1014+
print(string(fmtNSAsMS(sbuf[:], uint64(ns))))
1015+
}
1016+
print(" ms cpu, ",
10101017
heap0>>20, "->", heap1>>20, "->", heap2>>20, " MB, ",
10111018
heapGoal>>20, " MB goal, ",
10121019
maxprocs, " P")
@@ -1514,3 +1521,23 @@ func itoaDiv(buf []byte, val uint64, dec int) []byte {
15141521
buf[i] = byte(val + '0')
15151522
return buf[i:]
15161523
}
1524+
1525+
// fmtNSAsMS nicely formats ns nanoseconds as milliseconds.
1526+
func fmtNSAsMS(buf []byte, ns uint64) []byte {
1527+
if ns >= 10e6 {
1528+
// Format as whole milliseconds.
1529+
return itoaDiv(buf, ns/1e6, 0)
1530+
}
1531+
// Format two digits of precision, with at most three decimal places.
1532+
x := ns / 1e3
1533+
if x == 0 {
1534+
buf[0] = '0'
1535+
return buf[:1]
1536+
}
1537+
dec := 3
1538+
for x >= 100 {
1539+
x /= 10
1540+
dec--
1541+
}
1542+
return itoaDiv(buf, x, dec)
1543+
}

0 commit comments

Comments
 (0)