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))
}()
Enter fullscreen mode Exit fullscreen mode

It should look something like this:

package main

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

    _ "net/http/pprof"
)

// 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

    // 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

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

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 :)