Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Go profiling profile is empty

Tags:

memory

go

I'm following this tutorial on Go profiling and did as advised:

flag.Parse()
if *cpuprofile != "" {
    f, err := os.Create(*cpuprofile)
    if err != nil {
        log.Fatal(err)
    }
    pprof.StartCPUProfile(f)
    defer pprof.StopCPUProfile()
}

I then started my code with the flag -cpuprofile=myprogram.prof and the file got created. Then I started the pprof tool with

go tool pprof myprogram myprogram.prof

Well, myprogram reads a big json file and maps it to a big map[string]string, so there is a lot going on in my program, but when I do like top10 in pprof, I get:

Entering interactive mode (type "help" for commands)
(pprof) top10
profile is empty
like image 211
Gatonito Avatar asked Feb 17 '17 13:02

Gatonito


4 Answers

Most probably your code is executing too fast, even if you think it's doing a lot. Happened to me several times.

You can play with changing the sampling rate via runtime.SetCPUProfileRate. - set it to the value above default 100, unit is Hz. Please note the Go authors don't recommend values above 500 - see explanation.

Do it just before pprof.StartCPUProfile. You will also see the warning runtime: cannot set cpu profile rate until previous profile has finished - please see this answer for explanation.

HTH

like image 75
Wojciech Kaczmarek Avatar answered Nov 11 '22 16:11

Wojciech Kaczmarek


For profiling go programs you can use pprof as a web server. You need to add a bit of code to your main file of your go program/application to start the pprof server which will continuously serve the resource usage details for your program on the server and you can easily get all the relevant details. If you follow the code below the you can see the details of your program on your browser at http://localhost:6060/debug/pprof/ (Need to refresh the page to see the updated data)

You may see the code snippet below or go to the following link for the complete code: github.com/arbaaz-khan/GoLangLearning/blob/master/ProfilingGoProgram/profile_go_prog.go

go func() {
    log.Printf("Starting Server! \t Go to http://localhost:6060/debug/pprof/\n")
    err := http.ListenAndServe("localhost:6060", nil)
    if err != nil {
        log.Printf("Failed to start the server! Error: %v", err)
        wg.Done()
    }
}()

Hope it helps!

like image 29
Arbaaz Avatar answered Nov 11 '22 14:11

Arbaaz


If you use ctrl-c to stop the program, make sure you pass in profile.NoShutdownHook param in profile.Start().

like image 2
johann Avatar answered Nov 11 '22 14:11

johann


Most probably you are not handling the System Interrupt signal. You should explicitly handle it in order for "pprof.StopCPUProfile()" to write the profile data successfully, otherwise, the program exits to fast when exited with "ctrl+c". Here is an example solution:

var f *os.File

func main() {
    flag.Parse()
    if *cpuProfile != "" {
        cpuProfileFile, err := os.Create(*cpuProfile)
        if err != nil {
            log.Fatal(err)
        }
       defer f.Close()
       pprof.StartCPUProfile(cpuProfileFile)
    }
        
    c := make(chan os.Signal, 2)                    
    signal.Notify(c, os.Interrupt, syscall.SIGTERM) // subscribe to system signals
    onKill := func(c chan os.Signal) {
        select {
        case <-c: 
            defer f.Close()
            defer pprof.StopCPUProfile()
            defer os.Exit(0)
        }
    }

    // try to handle os interrupt(signal terminated)
    go onKill(c)
}
like image 2
tpopov Avatar answered Nov 11 '22 16:11

tpopov