Last active
June 16, 2019 12:20
-
-
Save DanielMorsing/591b26c5f0dbe0d780c45be124a6c6b9 to your computer and use it in GitHub Desktop.
Patch that adds stack growth events to the trace viewer
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/src/cmd/trace/trace.go b/src/cmd/trace/trace.go | |
index f39a397d0d..de8348e996 100644 | |
--- a/src/cmd/trace/trace.go | |
+++ b/src/cmd/trace/trace.go | |
@@ -739,6 +739,8 @@ func generateTrace(params *traceParams, consumer traceConsumer) error { | |
ctx.emitInstant(ev, "task start", "user event") | |
case trace.EvUserTaskEnd: | |
ctx.emitInstant(ev, "task end", "user event") | |
+ case trace.EvGoCopyStack: | |
+ ctx.emitInstant(ev, "copystack", "") | |
} | |
// Emit any counter updates. | |
ctx.emitThreadCounters(ev) | |
diff --git a/src/internal/trace/parser.go b/src/internal/trace/parser.go | |
index c371ff3092..bf2ec56721 100644 | |
--- a/src/internal/trace/parser.go | |
+++ b/src/internal/trace/parser.go | |
@@ -437,8 +437,11 @@ func parseEvents(ver int, rawEvents []rawEvent, strings map[uint64]string) (even | |
EvGoBlockSelect, EvGoBlockSync, EvGoBlockCond, EvGoBlockNet, | |
EvGoSysBlock, EvGoBlockGC: | |
lastG = 0 | |
- case EvGoSysExit, EvGoWaiting, EvGoInSyscall: | |
+ case EvGoSysExit, EvGoWaiting, EvGoInSyscall, EvGoCopyStack: | |
e.G = e.Args[0] | |
+ if raw.typ == EvGoCopyStack { | |
+ e.P = int(e.Args[1]) | |
+ } | |
case EvUserTaskCreate: | |
// e.Args 0: taskID, 1:parentID, 2:nameID | |
e.SArgs = []string{strings[e.Args[2]]} | |
@@ -835,6 +838,11 @@ func postProcessTrace(ver int, events []*Event) error { | |
} else { | |
return fmt.Errorf("invalid user region mode: %q", ev) | |
} | |
+ case EvGoCopyStack: | |
+ if err := checkRunning(p, g, ev, true); err != nil { | |
+ return err | |
+ } | |
+ g.ev = ev | |
} | |
gs[ev.G] = g | |
@@ -1058,7 +1066,8 @@ const ( | |
EvUserTaskEnd = 46 // end of task [timestamp, internal task id, stack] | |
EvUserRegion = 47 // trace.WithRegion [timestamp, internal task id, mode(0:start, 1:end), stack, name string] | |
EvUserLog = 48 // trace.Log [timestamp, internal id, key string id, stack, value string] | |
- EvCount = 49 | |
+ EvGoCopyStack = 49 // copystack [timestamp, goroutine id] | |
+ EvCount = 50 | |
) | |
var EventDescriptions = [EvCount]struct { | |
@@ -1117,4 +1126,5 @@ var EventDescriptions = [EvCount]struct { | |
EvUserTaskEnd: {"UserTaskEnd", 1011, true, []string{"taskid"}, nil}, | |
EvUserRegion: {"UserRegion", 1011, true, []string{"taskid", "mode", "typeid"}, []string{"name"}}, | |
EvUserLog: {"UserLog", 1011, true, []string{"id", "keyid"}, []string{"category", "message"}}, | |
+ EvGoCopyStack: {"GoCopyStack", 1011, true, []string{"g", "pid"}, nil}, | |
} | |
diff --git a/src/runtime/stack.go b/src/runtime/stack.go | |
index d5d09ba7d7..5e2fbc875c 100644 | |
--- a/src/runtime/stack.go | |
+++ b/src/runtime/stack.go | |
@@ -1052,6 +1052,9 @@ func newstack() { | |
print("stack grow done\n") | |
} | |
casgstatus(gp, _Gcopystack, _Grunning) | |
+ if trace.enabled { | |
+ traceCopyStack(gp) | |
+ } | |
gogo(&gp.sched) | |
} | |
diff --git a/src/runtime/trace.go b/src/runtime/trace.go | |
index 08e92d2efe..52aa3de378 100644 | |
--- a/src/runtime/trace.go | |
+++ b/src/runtime/trace.go | |
@@ -68,7 +68,8 @@ const ( | |
traceEvUserTaskEnd = 46 // end of a task [timestamp, internal task id, stack] | |
traceEvUserRegion = 47 // trace.WithRegion [timestamp, internal task id, mode(0:start, 1:end), stack, name string] | |
traceEvUserLog = 48 // trace.Log [timestamp, internal task id, key string id, stack, value string] | |
- traceEvCount = 49 | |
+ traceEvGoCopyStack = 49 // copystack [timestamp, goroutine id] | |
+ traceEvCount = 50 | |
// Byte is used but only 6 bits are available for event type. | |
// The remaining 2 bits are used to specify the number of arguments. | |
// That means, the max event type value is 63. | |
@@ -609,6 +610,12 @@ func traceAcquireBuffer() (mp *m, pid int32, bufp *traceBufPtr) { | |
return mp, traceGlobProc, &trace.buf | |
} | |
+func traceAcquireGlobal() (mp *m, pid int32, bufp *traceBufPtr) { | |
+ mp = acquirem() | |
+ lock(&trace.bufLock) | |
+ return mp, traceGlobProc, &trace.buf | |
+} | |
+ | |
// traceReleaseBuffer releases a buffer previously acquired with traceAcquireBuffer. | |
func traceReleaseBuffer(pid int32) { | |
if pid == traceGlobProc { | |
@@ -1219,3 +1226,19 @@ func trace_userLog(id uint64, category, message string) { | |
traceReleaseBuffer(pid) | |
} | |
+ | |
+func traceCopyStack(gp *g) { | |
+ if !trace.enabled { | |
+ return | |
+ } | |
+ // we have to use the global proc buffer here | |
+ // in case we are copying the stack while emitting | |
+ // a trace event. | |
+ mp, pid, bufp := traceAcquireGlobal() | |
+ actualpid := pid | |
+ if p := mp.p.ptr(); p != nil { | |
+ actualpid = p.id | |
+ } | |
+ traceEventLocked(0, mp, pid, bufp, traceEvGoCopyStack, 1, uint64(gp.goid), uint64(actualpid)) | |
+ traceReleaseBuffer(pid) | |
+} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment