diff options
Diffstat (limited to 'src/runtime/heapdump.go')
-rw-r--r-- | src/runtime/heapdump.go | 76 |
1 files changed, 44 insertions, 32 deletions
diff --git a/src/runtime/heapdump.go b/src/runtime/heapdump.go index 6fcd9746af..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,39 +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.alloc) - dumpint(memstats.heap_sys.load()) - dumpint(memstats.heap_sys.load() - memstats.heap_inuse) - dumpint(memstats.heap_inuse) - dumpint(memstats.heap_released) - dumpint(memstats.heap_objects) - dumpint(memstats.stacks_inuse) - dumpint(memstats.stacks_sys.load()) - dumpint(memstats.mspan_inuse) - dumpint(memstats.mspan_sys.load()) - dumpint(memstats.mcache_inuse) - dumpint(memstats.mcache_sys.load()) - dumpint(memstats.buckhash_sys.load()) - dumpint(memstats.gcMiscSys.load() + memstats.gcWorkBufInUse + memstats.gcProgPtrScalarBitsInUse) - dumpint(memstats.other_sys.load()) - 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) { @@ -642,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 { @@ -657,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 @@ -677,7 +689,7 @@ func writeheapdump_m(fd uintptr) { dumpfd = fd // Call dump routine. - mdump() + mdump(m) // Reset dump file. dumpfd = 0 |