3

I have a go binary, which uses cobra for subcommands. Each subcommand has it's own flags. I'd like to be able to create a CPU profile for a command with a specific set of parameters, like for example:

myBinary dryRun -c configs/config.json

However, if I try to run it, like this:

go tool pprof -pdf myBinary -- dryRun -c configs/config.json

I get the following error:

-: open --: no such file or directory
dryRun: open dryRun: no such file or directory
-c: open -c: no such file or directory
configs/config.json: parsing profile: unrecognized profile format

If I try to quote the entire command, it's also not working. Is there any way to get go tool pprof to pass other command line arguments?

EDIT: This is how I'm trying to profile:

func main() {
    defer profile.Start().Stop()

    fmt.Println("running version", version, "built on", date)
    fmt.Println()
    cmd.Execute()

    time.Sleep(2 * time.Second)
}
Geo
  • 93,257
  • 117
  • 344
  • 520
  • 4
    `go tool pprof` isn't for running your application, it's for analyzing profiler data. The binary passed to it is to allow it to analyze the profile and associate profiler data with instructions in the binary. So, you cannot pass parameters to your executable this way because it isn't running your executable in the first place. – Adrian Sep 12 '18 at 20:55
  • 1
    [This Go blog post](https://blog.golang.org/profiling-go-programs), as well as the rest of the Go documentation regarding pprof and profiling (eg https://golang.org/pkg/runtime/pprof/ and https://golang.org/pkg/net/http/pprof/), provide a wealth of information on how pprof works and how to profile Go programs. – Adrian Sep 12 '18 at 20:57
  • @Adrian, unfortunately, nothing I do seems to work. Always, I get something more or less similar to `Duration: 5.49s, Total samples = 0`, and `No samples were found with the default sample value type.`. The duration of course varies, and I even inserted some sleeps but I'm still not getting anything out of pprof. I've also added a code sample showing how I'm creating the profile data ( taken from the docs ) – Geo Sep 13 '18 at 18:46
  • That would seem to be a completely different question from the original question. Perhaps a new post would be appropriate. – Adrian Sep 13 '18 at 19:13
  • @Adrian , I've posted https://stackoverflow.com/questions/52320597/how-can-i-get-samples-when-running-go-with-pkg-profile-enabled . Could you have a look? – Geo Sep 13 '18 at 19:33
  • As mentioned in the first comment, and [here](https://gperftools.github.io/gperftools/cpuprofile.html) there are a few different ways to run the profiler: after building with the profiler enabled, (1) set the environment variable CPUPROFILE, (2) set the environment variables CPUPROFILE and CPUPROFILESIGNAL, and send the corresponding signal, (3) add `ProfilerStart()` and `ProfilerStop()` in your code (before building). After this, running `pprof` is just for viewing the generated profile from the actual run. – ShreevatsaR Oct 19 '20 at 03:54

1 Answers1

0

@Geo

Had the same issue profiling a cobra command line app with pprof

you just need to embed your flag choices in a separate main.go and call the package directly

In my case I managed to work around this by

  • creating another folder at top level which I added to .gitignore
  • created package main with a func main()

you will need to edit the main func for each combination you want to try but you end up with a binary you can pprof without any flags

the cobra command I am profiling

https://github.com/mutl3y/PRTG_VMware/blob/dev1/cmd/summary.go

my example of profiling it

/profiling/main.go

package main

import (
    "github.com/mutl3y/PRTG_VMware/VMware"
    "github.com/pkg/profile"
    "log"
    "net/url"
    "time"
)

func main() {
    defer profile.Start().Stop()
    u, err := url.Parse("https://192.168.59.4/sdk")
    if err != nil {
        log.Fatalf("failed to parse url")
    }
    c, err := VMware.NewClient(u, "prtg@heynes.local", ".l3tm31n", 2*time.Second)
    if err != nil {
        log.Fatalf("failed %v", err)
    }

    err = c.VmSummary("", "vm-13", &VMware.LimitsStruct{}, time.Second, true,[]string{})
    if err != nil {
        log.Fatalf("vmSummaryfailed %v", err)

    }

}
mutl3y
  • 1
  • 1