Bug 70787

Summary: No time and child info with -pg and gccgo
Product: gcc Reporter: Dominik Vogt <vogt>
Component: goAssignee: Ian Lance Taylor <ian>
Status: UNCONFIRMED ---    
Severity: normal CC: krebbel
Priority: P3    
Version: 7.0   
Target Milestone: ---   
Host: Target:
Build: Known to work:
Known to fail: Last reconfirmed:

Description Dominik Vogt 2016-04-25 13:44:31 UTC
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(?).
Comment 1 Dominik Vogt 2016-04-25 13:54:17 UTC
(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.)
Comment 2 Dominik Vogt 2016-04-26 11:38:40 UTC
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.