I am trying to generate PNG of goroutine
profile with this demo, but it reports error parsing profile: unrecognized profile format. failed to fetch any source profiles
package main
import (
"fmt"
"log"
"os"
"os/exec"
"runtime/pprof"
"time"
)
func main() {
// start demo go routine
go func() {
for {
time.Sleep(time.Second)
}
}()
// get executable binary path
exePath, err := os.Executable()
if err != nil {
log.Println(err.Error())
return
}
log.Println("exePath", exePath)
// generate goroutine profile
profilePath := exePath ".profile"
f, err := os.Create(profilePath)
if err != nil {
log.Println(err.Error())
return
}
defer f.Close()
if err := pprof.Lookup("goroutine").WriteTo(f, 2); err != nil {
log.Println(err.Error())
return
}
// generate PNG
pngPath := exePath ".png"
result, err := exec.Command("go", "tool", "pprof", "-png", "-output", pngPath, exePath, profilePath).CombinedOutput()
if err != nil {
log.Println("make error:", err.Error())
}
log.Println("make result:", string(result))
}
CodePudding user response:
You are using a debug value of 2
in pprof.Lookup("goroutine").WriteTo(f, 2)
. This will produce an output which the pprof tool can't parse, it is meant as directly human readable.
From the pprof.(*Profile).WriteTo docs:
The debug parameter enables additional output. Passing debug=0 writes the gzip-compressed protocol buffer described in https://github.com/google/pprof/tree/master/proto#overview. Passing debug=1 writes the legacy text format with comments translating addresses to function names and line numbers, so that a programmer can read the profile without tools.
The predefined profiles may assign meaning to other debug values; for example, when printing the "goroutine" profile, debug=2 means to print the goroutine stacks in the same form that a Go program uses when dying due to an unrecovered panic.
Changing this line to pprof.Lookup("goroutine").WriteTo(f, 0)
resolves the issue.
Also, not relevant to the issue, but you might want to consider closing the file f.Close()
before using it in the pprof command. WriteTo
should flush the file to disk, but it can't hurt.
if err := pprof.Lookup("goroutine").WriteTo(f, 2); err != nil {
log.Println(err.Error())
return
}
if err := f.Close(); err != nil {
log.Println(err.Error())
return
}
// generate PNG
...