It looks like the -pg option does something wrong for Go programs. Example: This program just wastes time in sub functions: -- main.go -- package main func foo () { var i int i = 0 for (i < 1000) { i++ } } func bar () { var i int i = 0 for (i < 1000) { i++ } } func main () { var i int i = 0 for (i < 1000000) { foo(); foo(); bar(); i++ } } -- snip -- $ gccgo -pg -O0 main.go $ ./a.out $ prof ./a.out gmoun.out => index % time self children called name 0.00 0.00 3000000/3000000 main.main [8] [1] 0.0 0.00 0.00 3000000 frame_dummy [1] ^^^ ^^^^ ^^^^ (actual run time was about 5 seconds) Even for this very simple program without Go library dependencies, no timing information seems to be dumped into the gmon.out file. Function calls have all been counted in the "frame_dummy" bucket (double checked that functios have not been inlied). My vague first guess is that maybe the timing information is written to to some place in memory but is read from a different place when generating gmon.out because the profiling code is not aware of Gccgo's threading model(?).
(I've also tried setting GMON_OUT_PREFIX so that the gmon.out file does not get overwritten by different threads, but in either case only one dump file is created.)
The Go runtime seems to register a handler for SIGPROF even if it does not want to profile. So it always uninstalls the handler installed by Glibc on behalf of the -pg option. To me it looks like -pg actually enables the profiling from libgo instead. Some ways to circumvent this: 1) Don't install a SIGPROF handler in the Go runtime if another is already installed (possibly emit a warning or a fatal error if the program attempts to enable the Go profiling). => Simple to implement. 2) Install the SIGPROF handler on the fly when it's needed instead of unconditionally at Go runtime startup. Possibly emit a warning if an existing signal handler is uninstalled in the process. => Cleanest solution. 3) Store the previous signal handler and call it at the start of the Go runtime signal handler. However, this introduces a number several problems (the Go runtime won't notice if the original profiling code wants to uninstall the handler or install a new one or it might overwrite the Go runtime handler; also, the two profiling systems will probably not agree on a common timing interval). => May allow to run Glibc and libgo profiling in parallel but probably has some unfixable issues.