Golang profiling simplified

post, Mar 7, 2017 on Mitja Felicijan's blog

Many posts have been written regarding profiling in Golang and I haven’t found +proper tutorial regarding this. Almost all of them are missing some part of +important information and it gets pretty frustrating when you have a deadline +and are not finding simple distilled solution.

Nevertheless, after searching and experimenting I have found a solution that +works for me and probably should also for you.

Where are my pprof files?

By default pprof files are generated in /tmp/ folder. You can override folder +where this files are generated programmatically in your golang code as we will +see below in example.

Why is my CPU profile empty?

I have found out that sometimes CPU profile is empty because program was not +executing long enough. Programs, that execute too quickly don’t produce pprof +file in my cases. Well, file is generated but only contains 4KB of information.

Profiling

As you can see from examples we are executing dummy_benchmark functions to +ensure some sort of execution. Memory profiling can be done without such a +“complex” function. But CPU profiling needs it.

Both memory and CPU profiling examples are almost the same. Only parameters in +main function when calling profile.Start are different. When we set +profile.ProfilePath(“.”) we tell profiler to store pprof files in the same +folder as our program.

Memory profiling

package main
+
+import (
+  "fmt"
+  "time"
+  "github.com/pkg/profile"
+)
+
+func dummy_benchmark() {
+
+  fmt.Println("first set ...")
+  for i := 0; i < 918231333; i++ {
+    i *= 2
+    i /= 2
+  }
+
+  <-time.After(time.Second*3)
+
+  fmt.Println("sencond set ...")
+  for i := 0; i < 9182312232; i++ {
+    i *= 2
+    i /= 2
+  }
+}
+
+func main() {
+  defer profile.Start(profile.MemProfile, profile.ProfilePath("."), profile.NoShutdownHook).Stop()
+  dummy_benchmark()
+}
+

CPU profiling

package main
+
+import (
+  "fmt"
+  "time"
+  "github.com/pkg/profile"
+)
+
+func dummy_benchmark() {
+
+  fmt.Println("first set ...")
+  for i := 0; i < 918231333; i++ {
+    i *= 2
+    i /= 2
+  }
+
+  <-time.After(time.Second*3)
+
+  fmt.Println("sencond set ...")
+  for i := 0; i < 9182312232; i++ {
+    i *= 2
+    i /= 2
+  }
+}
+
+func main() {
+  defer profile.Start(profile.CPUProfile, profile.ProfilePath("."), profile.NoShutdownHook).Stop()
+  dummy_benchmark()
+}
+

Generating profiling reports

# memory profiling
+go build mem.go
+./mem
+go tool pprof -pdf ./mem mem.pprof > mem.pdf
+
+# cpu profiling
+go build cpu.go
+./cpu
+go tool pprof -pdf ./cpu cpu.pprof > cpu.pdf
+

This will generate PDF document with visualized profile.