// PProf acquires a profile, and symbolizes it using a profile // manager. Then it generates a report formatted according to the // options selected through the flags package. func PProf(flagset plugin.FlagSet, fetch plugin.Fetcher, sym plugin.Symbolizer, obj plugin.ObjTool, ui plugin.UI, overrides commands.Commands) error { // Remove any temporary files created during pprof processing. defer tempfile.Cleanup() f, err := getFlags(flagset, overrides, ui) if err != nil { return err } obj.SetConfig(*f.flagTools) sources := f.profileSource if len(sources) > 1 { source := sources[0] // If the first argument is a supported object file, treat as executable. if file, err := obj.Open(source, 0); err == nil { file.Close() f.profileExecName = source sources = sources[1:] } else if *f.flagBuildID == "" && isBuildID(source) { f.flagBuildID = &source sources = sources[1:] } } // errMu protects concurrent accesses to errset and err. errset is set if an // error is encountered by one of the goroutines grabbing a profile. errMu, errset := sync.Mutex{}, false // Fetch profiles. wg := sync.WaitGroup{} profs := make([]*profile.Profile, len(sources)) for i, source := range sources { wg.Add(1) go func(i int, src string) { defer wg.Done() p, grabErr := grabProfile(src, f.profileExecName, *f.flagBuildID, fetch, sym, obj, ui, f) if grabErr != nil { errMu.Lock() defer errMu.Unlock() errset, err = true, grabErr return } profs[i] = p }(i, source) } wg.Wait() if errset { return err } // Merge profiles. prof := profs[0] for _, p := range profs[1:] { if err = prof.Merge(p, 1); err != nil { return err } } if *f.flagBase != "" { // Fetch base profile and subtract from current profile. base, err := grabProfile(*f.flagBase, f.profileExecName, *f.flagBuildID, fetch, sym, obj, ui, f) if err != nil { return err } if err = prof.Merge(base, -1); err != nil { return err } } if err := processFlags(prof, ui, f); err != nil { return err } if !*f.flagRuntime { prof.RemoveUninteresting() } if *f.flagInteractive { return interactive(prof, obj, ui, f) } return generate(false, prof, obj, ui, f) }