diamondburned

Profiling in Go is dead easy

Profiling in Go is dead easy. You should do it.

It is always better to have actual empirical evidence showing that your code is slow rather than blindly taking a guess at where it might be slow, or even worse, rewriting a chunk of code to use the fast* libraries without understanding how it works (I'm looking at you, fiber, fasthttp and fastjson).

There are 2 primary ways to profile a Go application: using a net/http/pprof server for long-running applications, or using runtime/pprof for short-running applications. This article will provide example copy-paste-friendly snippets of code for both.

net/http/pprof

Insert the following snippet, but replace package main with your package name.

package main

import (
   "net/http"
   _ "net/http/pprof"
)

func init() {
   go func() {
       println("Serving HTTP at 127.0.0.1:48574 for profiler at /debug/pprof")
       panic(http.ListenAndServe("127.0.0.1:48574", nil))
   }()
}

Run the application, then use the following command to profile for 10 seconds:

go tool pprof http://127.0.0.1:48574/debug/pprof/profile?seconds=10

runtime/pprof

Insert the following piece of code into the main() function:

{
   f, err := os.Create("/tmp/cpuprofile.pprof")
   if err != nil {
       log.Fatal("could not create CPU profile: ", err)
   }
   defer f.Close()

   if err := pprof.StartCPUProfile(f); err != nil {
       log.Fatal("could not start CPU profile: ", err)
   }
   defer pprof.StopCPUProfile()
}

Run the application, then use the following command to read the profile:

go tool pprof /tmp/cpuprofile.pprof

Interpreting the profiles isn't within the scope of this article; consult the Profiling Go Programs blog post written by Russ Cox for more information.

Thoughts? Leave a comment