I am trying to profile my web server I wrote, but my pprof does not contain any data about the handler func.
I am using the httprouter package by julienschmidt, and want to simply benchmark one of my handlers and see the pprof profile for that. For the benchmarking, I am using go-wrk
I set up my web server and pprof like this:
// Configure the server
server := &http.Server{
Addr: ":4000",
Handler: router,
}
go func() {
log.Println(http.ListenAndServe(":6060", nil))
}()
// Start the server
err = server.ListenAndServe()
if err != nil {
panic(err)
}
The router is initialized like this:
// Create the httprouter
router := httprouter.New()
// Register all handlers
router.GET("/entities/:type/map", h.UseHandler(&h.ApiGetEntitiesMapRequest{}, p))
And my handler looks like this:
func (req ApiGetEntitiesMapRequest) Handle(r *http.Request, hrp httprouter.Params, p Params) (interface{}, error) {
test := make([]string, 0)
for i := 0; i < 1000; i++ {
test = append(test, "1")
test = append(test, "2")
// Ensure pprof has some time to collect its data
time.Sleep(10)
}
return test, nil
}
This handler is just a test, where I dynamically append a lot of elements to a slice. The reason for that is, I wanted to test whether these dynamic allocations are represented in the heap profile of pprof.
Now, what I did was:
The request works and my benchmark also reports everything correctly. However, when I type png in the pprof terminal, I get this graph.
The graph does not contain any information about my handler and the costly heap allocations I did in my handler. What am I doing wrong?
So, I finally found the problem!
If you are using a custom mux for handling your requests, you need to register the pprof handler to your mux, in order to get the profiling right:
router.HandlerFunc(http.MethodGet, "/debug/pprof/", pprof.Index)
router.HandlerFunc(http.MethodGet, "/debug/pprof/cmdline", pprof.Cmdline)
router.HandlerFunc(http.MethodGet, "/debug/pprof/profile", pprof.Profile)
router.HandlerFunc(http.MethodGet, "/debug/pprof/symbol", pprof.Symbol)
router.HandlerFunc(http.MethodGet, "/debug/pprof/trace", pprof.Trace)
router.Handler(http.MethodGet, "/debug/pprof/goroutine", pprof.Handler("goroutine"))
router.Handler(http.MethodGet, "/debug/pprof/heap", pprof.Handler("heap"))
router.Handler(http.MethodGet,"/debug/pprof/threadcreate", pprof.Handler("threadcreate"))
router.Handler(http.MethodGet,"/debug/pprof/block", pprof.Handler("block"))
Now I got my desired result!