aboutsummaryrefslogtreecommitdiff
path: root/src/runtime/heapdump.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/runtime/heapdump.go')
-rw-r--r--src/runtime/heapdump.go79
1 files changed, 47 insertions, 32 deletions
diff --git a/src/runtime/heapdump.go b/src/runtime/heapdump.go
index 4c35309211..33e224d587 100644
--- a/src/runtime/heapdump.go
+++ b/src/runtime/heapdump.go
@@ -20,8 +20,19 @@ import (
func runtime_debug_WriteHeapDump(fd uintptr) {
stopTheWorld("write heap dump")
+ // Keep m on this G's stack instead of the system stack.
+ // Both readmemstats_m and writeheapdump_m have pretty large
+ // peak stack depths and we risk blowing the system stack.
+ // This is safe because the world is stopped, so we don't
+ // need to worry about anyone shrinking and therefore moving
+ // our stack.
+ var m MemStats
systemstack(func() {
- writeheapdump_m(fd)
+ // Call readmemstats_m here instead of deeper in
+ // writeheapdump_m because we might blow the system stack
+ // otherwise.
+ readmemstats_m(&m)
+ writeheapdump_m(fd, &m)
})
startTheWorld()
@@ -539,36 +550,40 @@ func dumpms() {
}
}
-func dumpmemstats() {
+//go:systemstack
+func dumpmemstats(m *MemStats) {
+ // These ints should be identical to the exported
+ // MemStats structure and should be ordered the same
+ // way too.
dumpint(tagMemStats)
- dumpint(memstats.alloc)
- dumpint(memstats.total_alloc)
- dumpint(memstats.sys)
- dumpint(memstats.nlookup)
- dumpint(memstats.nmalloc)
- dumpint(memstats.nfree)
- dumpint(memstats.heap_alloc)
- dumpint(memstats.heap_sys)
- dumpint(memstats.heap_idle)
- dumpint(memstats.heap_inuse)
- dumpint(memstats.heap_released)
- dumpint(memstats.heap_objects)
- dumpint(memstats.stacks_inuse)
- dumpint(memstats.stacks_sys)
- dumpint(memstats.mspan_inuse)
- dumpint(memstats.mspan_sys)
- dumpint(memstats.mcache_inuse)
- dumpint(memstats.mcache_sys)
- dumpint(memstats.buckhash_sys)
- dumpint(memstats.gc_sys)
- dumpint(memstats.other_sys)
- dumpint(memstats.next_gc)
- dumpint(memstats.last_gc_unix)
- dumpint(memstats.pause_total_ns)
+ dumpint(m.Alloc)
+ dumpint(m.TotalAlloc)
+ dumpint(m.Sys)
+ dumpint(m.Lookups)
+ dumpint(m.Mallocs)
+ dumpint(m.Frees)
+ dumpint(m.HeapAlloc)
+ dumpint(m.HeapSys)
+ dumpint(m.HeapIdle)
+ dumpint(m.HeapInuse)
+ dumpint(m.HeapReleased)
+ dumpint(m.HeapObjects)
+ dumpint(m.StackInuse)
+ dumpint(m.StackSys)
+ dumpint(m.MSpanInuse)
+ dumpint(m.MSpanSys)
+ dumpint(m.MCacheInuse)
+ dumpint(m.MCacheSys)
+ dumpint(m.BuckHashSys)
+ dumpint(m.GCSys)
+ dumpint(m.OtherSys)
+ dumpint(m.NextGC)
+ dumpint(m.LastGC)
+ dumpint(m.PauseTotalNs)
for i := 0; i < 256; i++ {
- dumpint(memstats.pause_ns[i])
+ dumpint(m.PauseNs[i])
}
- dumpint(uint64(memstats.numgc))
+ dumpint(uint64(m.NumGC))
}
func dumpmemprof_callback(b *bucket, nstk uintptr, pstk *uintptr, size, allocs, frees uintptr) {
@@ -639,7 +654,7 @@ func dumpmemprof() {
var dumphdr = []byte("go1.7 heap dump\n")
-func mdump() {
+func mdump(m *MemStats) {
// make sure we're done sweeping
for _, s := range mheap_.allspans {
if s.state.get() == mSpanInUse {
@@ -654,13 +669,13 @@ func mdump() {
dumpgs()
dumpms()
dumproots()
- dumpmemstats()
+ dumpmemstats(m)
dumpmemprof()
dumpint(tagEOF)
flush()
}
-func writeheapdump_m(fd uintptr) {
+func writeheapdump_m(fd uintptr, m *MemStats) {
_g_ := getg()
casgstatus(_g_.m.curg, _Grunning, _Gwaiting)
_g_.waitreason = waitReasonDumpingHeap
@@ -674,7 +689,7 @@ func writeheapdump_m(fd uintptr) {
dumpfd = fd
// Call dump routine.
- mdump()
+ mdump(m)
// Reset dump file.
dumpfd = 0