`go tool pprof` reports error `unrecognized profile format`

Issue

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

Solution

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

Answered By – Dylan Reimerink

Answer Checked By – Candace Johnson (GoLangFix Volunteer)

Leave a Reply

Your email address will not be published.