Heap profile reader for Go
Runtime patch: https://codereview.appspot.com/37540043/
You call debug.WriteHeapDump(fd uintptr) to write a heap dump to the given file descriptor from within your Go program (that's runtime/debug).
The code in this directory is for a hprof utility which converts from the internal dump format to the hprof format.
go build dumptohprof.go readdump.go dumptohprof dumpfile dump.hprof jhat dump.hprof (might need to download jhat)
then navigate a browser to localhost:7000 and poke around. A good example is "show heap histogram".
jhat is one simple analysis tool - there are a bunch of others out there. My converter only fills in data that jhat requires, though, other tools may need more info to work.
It's a java-centric format, so there is a lot of junk that doesn't translate well from Go.
The Go heap contains no type information for objects which have no pointers in them. You'll just see "noptrX" types for different sizes X.
The Go heap also contains no field names for objects, so you'll just see fX for different offsets X in the object.
Below is a description of the internal format of the heap dump.
The file starts with the bytes "go1.3 heap dump\n". The rest of the file is encoded in records of different kind. Most values in these records are encoded with a variable-sized integer encoding (uvarint) compatible with ReadUvarint in encoding/binary.
Each record starts with a "kind" which is uvarint encoded. These are the possible kinds: 1: object 3: eof 4: stackroot 5: dataroot 6: otherroot 7: type 8: stack frame 9: stack 10: dump params 11: finalizer 12: itab
Strings are encoded with a Uvarint size followed by that many bytes of string (UTF8 encoded)
Each kind of record has a different layout. Here are the layouts:
object: 1 uvarint addr uvarint address of object start type uvarint address of type, 0 if unknown kind uvarint 0 - regular T, 1 - array of T, 2 - channel of T (must be 0 if type is 0) size uvarint total size (size of sizeclass, type.size may be a bit smaller) data size bytes
eof: 3 uvarint
stackroot: 4 uvarint addr uvarint address where pointer was found rootptr uvarint possible ptr to an object frame uvarint sp of frame this pointer came from
dataroot: 5 uvarint addr uvarint address where pointer was found rootptr uvarint possible ptr to an object
otherroot: 6 uvarint description string rootptr uvarint possible ptr to an object
type: 7 uvarint addr uvarint identifier for type (Type*) size uvarint size of this type of object name string efaceptr uvarint 1 = the data field of an Eface with this type is a ptr nfields uvarint number of fields in an object of this type. fields [2]uvarint* list of <kind,offset> of fields. Increasing offset order. kinds: 0:Ptr 1:String 2:Slice 3:Iface 4:Eface TODO: field names, ...
goroutine:
8 uvarint
addr uvarint thread identifier
tos uvarint top (the currently running) frame of stack
goid uvarint ID of goroutine
gopc uvarint pc of creation point
status uvarint idle=0, runnable=1, syscall=3, waiting=4
issystem uvarint
isbackground uvarint
waitsince uvarint
waitreason string
stack frame: 9 uvarint addr uvarint sp of frame parent uvarint sp of parent's frame, or nil if bottom of stack entry uvarint pc of function entry pc uvarint pc code is suspended at name string function name
dump params: 10 uvarint endian uvarint 0=little endian, 1=big endian ptrsize uvarint ptr size in bytes. 4 or 8 hchansize uvarint size of channel header in bytes. heapstart uvarint start of heap heapend uvarint end of heap
finalizer data: 11 uvarint obj uvarint object that has a finalizer funcval uvarint funcval ptr code uvarint code ptr (funcval->fn) fint uvarint interface argument type of finalizer function ot uvarint object type
itab data: 12 uvarint addr uvarint Itab* ptr uvarint 1 = the data field of an Iface with this itab is a ptr