DEV Community

Agam
Agam

Posted on • Updated on

How to profile Go with pprof in 30 seconds

If you are interested in developer trends you should check out my new newsletter at: unzip.dev


I was looking for a quick intro profiling in Go but everything was cumbersome, it seems that everyone points to pprof.

Let's say this is the code you want to profile:



package main

import (
    "fmt"
    "sync"
    "time"
)

// Some function that does work
func hardWork(wg *sync.WaitGroup) {
    defer wg.Done()
    fmt.Printf("Start: %v\n", time.Now())

    // Memory
    a := []string{}
    for i := 0; i < 500000; i++ {
        a = append(a, "aaaa")
    }

    // Blocking
    time.Sleep(2 * time.Second)
    fmt.Printf("End: %v\n", time.Now())
}

func main() {
    var wg sync.WaitGroup
    wg.Add(1)
    go hardWork(&wg)
    wg.Wait()
}



Enter fullscreen mode Exit fullscreen mode

Now let's profile it, to do that we need to:

  1. Install dependencies: apt-get install graphviz gv (debian) or brew install graphviz (mac)
  2. Install pprof: go get -u github.com/google/pprof
  3. Add an import: import _ "net/http/pprof"
  4. Add a server for pprof: ```

go func() {
fmt.Println(http.ListenAndServe("localhost:6060", nil))
}()


It should look something like this:
Enter fullscreen mode Exit fullscreen mode

package main

import (
"fmt"
"net/http"
"sync"
"time"

_ "net/http/pprof"
Enter fullscreen mode Exit fullscreen mode

)

// Some function that does work
func hardWork(wg *sync.WaitGroup) {
defer wg.Done()
fmt.Printf("Start: %v\n", time.Now())

// Memory
a := []string{}
for i := 0; i < 500000; i++ {
    a = append(a, "aaaa")
}

// Blocking
time.Sleep(2 * time.Second)
fmt.Printf("End: %v\n", time.Now())
Enter fullscreen mode Exit fullscreen mode

}

func main() {
var wg sync.WaitGroup

// Server for pprof
go func() {
    fmt.Println(http.ListenAndServe("localhost:6060", nil))
}()
wg.Add(1) // pprof - so we won't exit prematurely
wg.Add(1) // for the hardWork
go hardWork(&wg)
wg.Wait()
Enter fullscreen mode Exit fullscreen mode

}


When you type: `go tool pprof http://localhost:6060/debug/pprof/heap` while the server is running (in a different terminal) and then type `png` you will get something like the following:
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/58ozh4fcl7pp6gozt4aa.png)

As you can see, `hardWork` is consuming some memory.
If you want to check the goroutines you can replace the line to:
`go tool pprof http://localhost:6060/debug/pprof/goroutine`

You can choose between:
- CPU: `profile?seconds=10`
- Memory: `heap`
- Goroutines: `goroutine`
- Goroutine blocking: `block`
- Locks: `mutex`
- Tracing: `trace?seconds=5`
Enter fullscreen mode Exit fullscreen mode

Top comments (1)

Collapse
 
asahasrabuddhe profile image
Ajitem Sahasrabuddhe

This is great! This article helped me a lot to debug a memory leak in my application. Really appreciate the time you took to write this up. Thanks a lot :)