package main
import(
_ “net/http/pprof”
“github.com/felixge/fgprof”
)
func main() {
http.DefaultServeMux.Handle(“/debug/fgprof”, fgprof.Handler())
go func() {
log.Println(http.ListenAndServe(“:6060”, nil))
}()
// <code to profile> } <!-- more --> How it Works fgprof fgprof is implemented as a background goroutine that wakes up 99 times per second and calls runtime.GoroutineProfile. This returns a list of all goroutines regardless of their current On/Off CPU scheduling status and their call stacks.
This data is used to maintain an in-memory stack counter which can be converted to the pprof or folded output format. The meat of the implementation is super simple and < 100 lines of code, you should check it out.
Go’s builtin CPU Profiler
The builtin Go CPU profiler uses the setitimer(2) system call to ask the operating system to be sent a SIGPROF signal 100 times a second. Each signal stops the Go process and gets delivered to a random thread’s sigtrampgo() function. This function then proceeds to call sigprof() or sigprofNonGo() to record the thread’s current stack.
Since Go uses non-blocking I/O, Goroutines that wait on I/O are parked and not running on any threads. Therefore they end up being largely invisible to Go’s builtin CPU profiler.
https://www.mianshigee.com/project/felixge-fgprof/