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()
}
Now let's profile it, to do that we need to:
- Install dependencies:
apt-get install graphviz gv
(debian) orbrew install graphviz
(mac) - Install pprof:
go get -u github.com/google/pprof
- Add an import:
import _ "net/http/pprof"
- Add a server for
pprof
: ```
go func() {
fmt.Println(http.ListenAndServe("localhost:6060", nil))
}()
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()
}
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`
Top comments (1)
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 :)