Fetching profile over HTTP from http://mem_2023-11-02_05:47:58/debug/pprof/profile mem_2023-11-02_05:47:58: Get "http://mem_2023-11-02_05:47:58/debug/pprof/profile": dial tcp: lookup mem_2023-11-02_05:47: no such host failed to fetch any source profiles
报错信息可能因go的版本而有所不同。上图go的版本是go version go1.21.0 darwin/arm64
cui := &sources[0] spew.Println("cui is: ",cui) spew.Println("cui.err is: ",cui.err)
wg := sync.WaitGroup{} wg.Add(len(sources)) for i := range sources { gofunc(s *profileSource) { defer wg.Done() s.p, s.msrc, s.remote, s.err = grabProfile(s.source, s.addr, fetch, obj, ui, tr) }(&sources[i]) } wg.Wait()
fmt.Println("----一番处理后------")
spew.Println("cui2 is: ",cui) spew.Println("cui2.err is: ",cui.err)
1 2 3 4 5 6 7
cui is: <*>{mem_2023-11-02_05:47:58 <*>{[mem_2023-11-02_05:47:58] <nil> false false -1 -1 false } <nil> <nil> false <nil>} cui.err is: <nil> shuang said Fetching profile over HTTP from http://mem_2023-11-02_05:47:58/debug/pprof/profile ----一番处理后------ cui2 is: <*>{mem_2023-11-02_05:47:58 <*>{[mem_2023-11-02_05:47:58] <nil> false false -1 -1 false } <nil> <nil> false <*>Get "http://mem_2023-11-02_05:47:58/debug/pprof/profile": dial tcp: lookup mem_2023-11-02_05:47: no such host} cui2.err is: <*>Get "http://mem_2023-11-02_05:47:58/debug/pprof/profile": dial tcp: lookup mem_2023-11-02_05:47: no such host 爽哥说,s.err错误是: %#v Get "http://mem_2023-11-02_05:47:58/debug/pprof/profile": dial tcp: lookup mem_2023-11-02_05:47: no such host
// grabProfile fetches a profile. Returns the profile, sources for the // profile mappings, a bool indicating if the profile was fetched // remotely, and an error. funcgrabProfile(s *source, source string, fetcher plugin.Fetcher, obj plugin.ObjTool, ui plugin.UI, tr http.RoundTripper) (p *profile.Profile, msrc plugin.MappingSources, remote bool, err error) { var src string duration, timeout := time.Duration(s.Seconds)*time.Second, time.Duration(s.Timeout)*time.Second if fetcher != nil { p, src, err = fetcher.Fetch(source, duration, timeout) if err != nil { return } } if err != nil || p == nil { // Fetch the profile over HTTP or from a file. p, src, err = fetch(source, duration, timeout, ui, tr) if err != nil { return } }
if err = p.CheckValid(); err != nil { return }
// Update the binary locations from command line and paths. locateBinaries(p, s, obj, ui)
// Collect the source URL for all mappings. if src != "" { msrc = collectMappingSources(p, src) remote = true if strings.HasPrefix(src, "http://"+testSourceAddress) { // Treat test inputs as local to avoid saving // testcase profiles during driver testing. remote = false } } return }
// 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. funcPProf(eo *plugin.Options)error { // Remove any temporary files created during pprof processing. defer cleanupTempFiles()
// fetchProfiles fetches and symbolizes the profiles specified by s. // It will merge all the profiles it is able to retrieve, even if // there are some failures. It will return an error if it is unable to // fetch any profiles. funcfetchProfiles(s *source, o *plugin.Options) (*profile.Profile, error) { sources := make([]profileSource, 0, len(s.Sources)) for _, src := range s.Sources { sources = append(sources, profileSource{ addr: src, source: s, }) }
// chunkedGrab fetches the profiles described in source and merges them into // a single profile. It fetches a chunk of profiles concurrently, with a maximum // chunk size to limit its memory usage. funcchunkedGrab(sources []profileSource, fetch plugin.Fetcher, obj plugin.ObjTool, ui plugin.UI, tr http.RoundTripper) (*profile.Profile, plugin.MappingSources, bool, int, error) { const chunkSize = 128
var p *profile.Profile var msrc plugin.MappingSources var save bool var count int
for start := 0; start < len(sources); start += chunkSize { end := start + chunkSize if end > len(sources) { end = len(sources) } chunkP, chunkMsrc, chunkSave, chunkCount, chunkErr := concurrentGrab(sources[start:end], fetch, obj, ui, tr) switch { case chunkErr != nil: returnnil, nil, false, 0, chunkErr case chunkP == nil: continue case p == nil: p, msrc, save, count = chunkP, chunkMsrc, chunkSave, chunkCount default: p, msrc, chunkErr = combineProfiles([]*profile.Profile{p, chunkP}, []plugin.MappingSources{msrc, chunkMsrc}) if chunkErr != nil { returnnil, nil, false, 0, chunkErr } if chunkSave { save = true } count += chunkCount } }
// grabProfile fetches a profile. Returns the profile, sources for the // profile mappings, a bool indicating if the profile was fetched // remotely, and an error. funcgrabProfile(s *source, source string, fetcher plugin.Fetcher, obj plugin.ObjTool, ui plugin.UI, tr http.RoundTripper) (p *profile.Profile, msrc plugin.MappingSources, remote bool, err error) {
fmt.Println("这里肯定到了6789") var src string duration, timeout := time.Duration(s.Seconds)*time.Second, time.Duration(s.Timeout)*time.Second
// Update the binary locations from command line and paths. locateBinaries(p, s, obj, ui)
// Collect the source URL for all mappings. if src != "" { msrc = collectMappingSources(p, src) remote = true if strings.HasPrefix(src, "http://"+testSourceAddress) { // Treat test inputs as local to avoid saving // testcase profiles during driver testing. remote = false } } return }
// fetch fetches a profile from source, within the timeout specified, // producing messages through the ui. It returns the profile and the // url of the actual source of the profile for remote profiles. funcfetch(source string, duration, timeout time.Duration, ui plugin.UI, tr http.RoundTripper) (p *profile.Profile, src string, err error) {
src777 is: http://mem_2023-11-02_04:44:30 err888 is: http fetch: Get "http://mem_2023-11-02_04:44:30": dial tcp: lookup mem_2023-11-02_01:40: no such host
// fetch fetches a profile from source, within the timeout specified, // producing messages through the ui. It returns the profile and the // url of the actual source of the profile for remote profiles. funcfetch(source string, duration, timeout time.Duration, ui plugin.UI, tr http.RoundTripper) (p *profile.Profile, src string, err error) { var f io.ReadCloser fmt.Println("这是爽哥新修改的google/pprof的fetch方法")
// First determine whether the source is a file, if not, it will be treated as a URL. if _, openErr := os.Stat(source); openErr == nil { if isPerfFile(source) { f, err = convertPerfData(source, ui) } else { f, err = os.Open(source) } } else { sourceURL, timeout := adjustURL(source, duration, timeout) if sourceURL != "" { ui.Print("Fetching profile over HTTP from " + sourceURL) if duration > 0 { ui.Print(fmt.Sprintf("Please wait... (%v)", duration)) } f, err = fetchURL(sourceURL, timeout, tr) src = sourceURL } } if err == nil { defer f.Close() p, err = profile.Parse(f) } return }
执行 ./all.bash重新编译Go源码
而后回到 /Users/fliter/20231014/go/src/pprof2 目录下,再次执行 go tool pprof mem_2023-11-02_04:44:30
// adjustURL applies the duration/timeout values and Go specific defaults. funcadjustURL(source string, duration, timeout time.Duration) (string, time.Duration) { //
fmt.Println("彭齐777") // Try adding http:// to catch sources of the form hostname:port/path. // url.Parse treats "hostname" as the scheme. u, err = url.Parse("http://" + source) spew.Dump("uuuuuu ,err is:", u, err)
// A Fetcher reads and returns the profile named by src. src can be a // local file path or a URL. duration and timeout are units specified // by the end user, or 0 by default. duration refers to the length of // the profile collection, if applicable, and timeout is the amount of // time to wait for a profile before returning an error. Returns the // fetched profile, the URL of the actual source of the profile, or an // error. type Fetcher interface { Fetch(src string, duration, timeout time.Duration) (*profile.Profile, string, error) }
The code below doesn’t seem to do anything related to “the current directory”, but just whether it is an exisiting file. It seems it can be a path with a directory, which could even contain a “:” like “my:dir/file”? Either the code or comment needs to be adjusted.