DEV Community

Agam
Agam

Posted on • Edited on

25 1

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

Sentry image

See why 4M developers consider Sentry, “not bad.”

Fixing code doesn’t have to be the worst part of your day. Learn how Sentry can help.

Learn more

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

The Most Contextual AI Development Assistant

Pieces.app image

Our centralized storage agent works on-device, unifying various developer tools to proactively capture and enrich useful materials, streamline collaboration, and solve complex problems through a contextual understanding of your unique workflow.

👥 Ideal for solo developers, teams, and cross-company projects

Learn more