Source File
heapdump.go
Belonging Package
runtime
package runtime
import (
)
func ( uintptr) {
stopTheWorld("write heap dump")
var MemStats
readmemstats_m(&)
writeheapdump_m(, &)
})
startTheWorld()
}
const (
fieldKindEol = 0
fieldKindPtr = 1
fieldKindIface = 2
fieldKindEface = 3
tagEOF = 0
tagObject = 1
tagOtherRoot = 2
tagType = 3
tagGoroutine = 4
tagStackFrame = 5
tagParams = 6
tagFinalizer = 7
tagItab = 8
tagOSThread = 9
tagMemStats = 10
tagQueuedFinalizer = 11
tagData = 12
tagBSS = 13
tagDefer = 14
tagPanic = 15
tagMemProf = 16
tagAllocSample = 17
)
var dumpfd uintptr // fd to write the dump to.
var tmpbuf []byte
const (
bufSize = 4096
)
var buf [bufSize]byte
var nbuf uintptr
func ( unsafe.Pointer, uintptr) {
if == 0 {
return
}
if nbuf+ <= bufSize {
copy(buf[nbuf:], (*[bufSize]byte)()[:])
nbuf +=
return
}
write(dumpfd, unsafe.Pointer(&buf), int32(nbuf))
if >= bufSize {
write(dumpfd, , int32())
nbuf = 0
} else {
copy(buf[:], (*[bufSize]byte)()[:])
nbuf =
}
}
func ( byte) {
dwrite(unsafe.Pointer(&), 1)
}
func () {
write(dumpfd, unsafe.Pointer(&buf), int32(nbuf))
nbuf = 0
}
const (
typeCacheBuckets = 256
typeCacheAssoc = 4
)
type typeCacheBucket struct {
t [typeCacheAssoc]*_type
}
var typecache [typeCacheBuckets]typeCacheBucket
:= &typecache[.hash&(typeCacheBuckets-1)]
if == .t[0] {
return
}
for := 1; < typeCacheAssoc; ++ {
for := typeCacheAssoc - 1; > 0; -- {
.t[] = .t[-1]
}
.t[0] =
dumpint(tagType)
dumpint(uint64(uintptr(unsafe.Pointer())))
dumpint(uint64(.size))
if := .uncommon(); == nil || .nameOff(.pkgpath).name() == "" {
dumpstr(.string())
} else {
:= .nameOff(.pkgpath).name()
:= stringStructOf(&)
:= .name()
:= stringStructOf(&)
dumpint(uint64(uintptr(.len) + 1 + uintptr(.len)))
dwrite(.str, uintptr(.len))
dwritebyte('.')
dwrite(.str, uintptr(.len))
}
dumpbool(.kind&kindDirectIface == 0 || .ptrdata != 0)
}
func ( unsafe.Pointer, uintptr, bitvector) {
dumpint(tagObject)
dumpint(uint64(uintptr()))
dumpmemrange(, )
dumpfields()
}
func ( string, unsafe.Pointer) {
dumpint(tagOtherRoot)
dumpstr()
dumpint(uint64(uintptr()))
}
func ( unsafe.Pointer, *funcval, *_type, *ptrtype) {
dumpint(tagFinalizer)
dumpint(uint64(uintptr()))
dumpint(uint64(uintptr(unsafe.Pointer())))
dumpint(uint64(uintptr(unsafe.Pointer(.fn))))
dumpint(uint64(uintptr(unsafe.Pointer())))
dumpint(uint64(uintptr(unsafe.Pointer())))
}
:= .pc
:= int32(-1) // Use the entry map at function entry
if != .entry {
--
= pcdatavalue(, _PCDATA_StackMapIndex, , nil)
}
= 0
}
:= (*stackmap)(funcdata(, _FUNCDATA_LocalsPointerMaps))
var bitvector
if != nil && .n > 0 {
= stackmapdata(, )
} else {
.n = -1
}
dumpint(tagStackFrame)
dumpint(uint64(.sp)) // lowest address in frame
dumpint(uint64(.depth)) // # of frames deep on the stack
dumpint(uint64(uintptr(unsafe.Pointer(.sp)))) // sp of child, or 0 if bottom of stack
dumpmemrange(unsafe.Pointer(.sp), .fp-.sp) // frame contents
dumpint(uint64(.entry))
dumpint(uint64(.pc))
dumpint(uint64(.continpc))
:= funcname()
if == "" {
= "unknown function"
}
dumpstr()
.argoff = .argp - .fp
.arglen = .arglen
.sp = (*uint8)(unsafe.Pointer(.sp))
.depth++
= (*stackmap)(funcdata(, _FUNCDATA_ArgsPointerMaps))
if != nil {
.args = stackmapdata(, )
} else {
.args.n = -1
}
return true
}
func ( *g) {
var , , uintptr
if .syscallsp != 0 {
= .syscallsp
= .syscallpc
= 0
} else {
= .sched.sp
= .sched.pc
= .sched.lr
}
dumpint(tagGoroutine)
dumpint(uint64(uintptr(unsafe.Pointer())))
dumpint(uint64())
dumpint(uint64(.goid))
dumpint(uint64(.gopc))
dumpint(uint64(readgstatus()))
dumpbool(isSystemGoroutine(, false))
dumpbool(false) // isbackground
dumpint(uint64(.waitsince))
dumpstr(.waitreason.String())
dumpint(uint64(uintptr(.sched.ctxt)))
dumpint(uint64(uintptr(unsafe.Pointer(.m))))
dumpint(uint64(uintptr(unsafe.Pointer(._defer))))
dumpint(uint64(uintptr(unsafe.Pointer(._panic))))
dumpint(uint64(0))
} else {
dumpint(uint64(uintptr(unsafe.Pointer(.fn.fn))))
}
dumpint(uint64(uintptr(unsafe.Pointer(.link))))
}
for := ._panic; != nil; = .link {
dumpint(tagPanic)
dumpint(uint64(uintptr(unsafe.Pointer())))
dumpint(uint64(uintptr(unsafe.Pointer())))
:= efaceOf(&.arg)
dumpint(uint64(uintptr(unsafe.Pointer(._type))))
dumpint(uint64(uintptr(unsafe.Pointer(.data))))
dumpint(0) // was p->defer, no longer recorded
dumpint(uint64(uintptr(unsafe.Pointer(.link))))
}
}
case _Grunnable,
_Gsyscall,
_Gwaiting:
dumpgoroutine()
}
}
}
func ( *funcval, unsafe.Pointer, uintptr, *_type, *ptrtype) {
dumpint(tagQueuedFinalizer)
dumpint(uint64(uintptr()))
dumpint(uint64(uintptr(unsafe.Pointer())))
dumpint(uint64(uintptr(unsafe.Pointer(.fn))))
dumpint(uint64(uintptr(unsafe.Pointer())))
dumpint(uint64(uintptr(unsafe.Pointer())))
}
assertWorldStopped()
for , := range mheap_.allspans {
if .state.get() != mSpanInUse {
continue
}
:= .base()
:= .elemsize
:= (.npages << _PageShift) /
if > uintptr(len(freemark)) {
throw("freemark array doesn't have enough entries")
}
for := uintptr(0); < .nelems; ++ {
if .isFree() {
freemark[] = true
}
}
for := uintptr(0); < ; , = +1, + {
if freemark[] {
freemark[] = false
continue
}
dumpobj(unsafe.Pointer(), , makeheapobjbv(, ))
}
}
}
func () {
dumpint(tagParams)
:= uintptr(1)
if *(*byte)(unsafe.Pointer(&)) == 1 {
dumpbool(false) // little-endian ptrs
} else {
dumpbool(true) // big-endian ptrs
}
dumpint(sys.PtrSize)
var , uintptr
for := range mheap_.arenas {
if mheap_.arenas[] == nil {
continue
}
for , := range mheap_.arenas[] {
if == nil {
continue
}
:= arenaBase(arenaIdx()<<arenaL1Shift | arenaIdx())
if == 0 || < {
=
}
if +heapArenaBytes > {
= + heapArenaBytes
}
}
}
dumpint(uint64())
dumpint(uint64())
dumpstr(sys.GOARCH)
dumpstr(sys.Goexperiment)
dumpint(uint64(ncpu))
}
func ( *itab) {
:= ._type
dumptype()
dumpint(tagItab)
dumpint(uint64(uintptr(unsafe.Pointer())))
dumpint(uint64(uintptr(unsafe.Pointer())))
}
func () {
iterate_itabs(itab_callback)
}
func () {
for := allm; != nil; = .alllink {
dumpint(tagOSThread)
dumpint(uint64(uintptr(unsafe.Pointer())))
dumpint(uint64(.id))
dumpint(.procid)
}
}
func ( *MemStats) {
assertWorldStopped()
dumpint(tagMemStats)
dumpint(.Alloc)
dumpint(.TotalAlloc)
dumpint(.Sys)
dumpint(.Lookups)
dumpint(.Mallocs)
dumpint(.Frees)
dumpint(.HeapAlloc)
dumpint(.HeapSys)
dumpint(.HeapIdle)
dumpint(.HeapInuse)
dumpint(.HeapReleased)
dumpint(.HeapObjects)
dumpint(.StackInuse)
dumpint(.StackSys)
dumpint(.MSpanInuse)
dumpint(.MSpanSys)
dumpint(.MCacheInuse)
dumpint(.MCacheSys)
dumpint(.BuckHashSys)
dumpint(.GCSys)
dumpint(.OtherSys)
dumpint(.NextGC)
dumpint(.LastGC)
dumpint(.PauseTotalNs)
for := 0; < 256; ++ {
dumpint(.PauseNs[])
}
dumpint(uint64(.NumGC))
}
func ( *bucket, uintptr, *uintptr, , , uintptr) {
:= (*[100000]uintptr)(unsafe.Pointer())
dumpint(tagMemProf)
dumpint(uint64(uintptr(unsafe.Pointer())))
dumpint(uint64())
dumpint(uint64())
for := uintptr(0); < ; ++ {
:= []
:= findfunc()
if !.valid() {
var [64]byte
:= len()
--
[] = ')'
if == 0 {
--
[] = '0'
} else {
for > 0 {
--
[] = "0123456789abcdef"[&15]
>>= 4
}
}
--
[] = 'x'
--
[] = '0'
--
[] = '('
dumpslice([:])
dumpstr("?")
dumpint(0)
} else {
dumpstr(funcname())
if > 0 && > .entry {
--
}
, := funcline(, )
dumpstr()
dumpint(uint64())
}
}
dumpint(uint64())
dumpint(uint64())
}
assertWorldStopped()
iterate_memprof(dumpmemprof_callback)
for , := range mheap_.allspans {
if .state.get() != mSpanInUse {
continue
}
for := .specials; != nil; = .next {
if .kind != _KindSpecialProfile {
continue
}
:= (*specialprofile)(unsafe.Pointer())
:= .base() + uintptr(.special.offset)
dumpint(tagAllocSample)
dumpint(uint64())
dumpint(uint64(uintptr(unsafe.Pointer(.b))))
}
}
}
var dumphdr = []byte("go1.7 heap dump\n")
func ( *MemStats) {
assertWorldStopped()
for , := range mheap_.allspans {
if .state.get() == mSpanInUse {
.ensureSwept()
}
}
memclrNoHeapPointers(unsafe.Pointer(&typecache), unsafe.Sizeof(typecache))
dwrite(unsafe.Pointer(&dumphdr[0]), uintptr(len(dumphdr)))
dumpparams()
dumpitabs()
dumpobjs()
dumpgs()
dumpms()
dumproots()
dumpmemstats()
dumpmemprof()
dumpint(tagEOF)
flush()
}
func ( uintptr, *MemStats) {
assertWorldStopped()
:= getg()
casgstatus(.m.curg, _Grunning, _Gwaiting)
.waitreason = waitReasonDumpingHeap
dumpfd =
mdump()
func ( bitvector) {
dumpbv(&, 0)
dumpint(fieldKindEol)
}
![]() |
The pages are generated with Golds v0.3.2-preview. (GOOS=darwin GOARCH=amd64) Golds is a Go 101 project developed by Tapir Liu. PR and bug reports are welcome and can be submitted to the issue list. Please follow @Go100and1 (reachable from the left QR code) to get the latest news of Golds. |